LoginSignup
0
0

More than 1 year has passed since last update.

【PostgreSQL】変数への値の代入を禁止する「CONSTANT」と、変数へ値を代入する「:=」を併記できるのはなぜ?

Posted at

OSS-DB Silver 取得に向けて勉強中です。

『OSS教科書 OSS-DB Silver ver.2.0対応(翔泳社)』(緑本)と
『徹底攻略OSS-DB Silver 問題集 ver2.0対応(インプレス)』(黒本)
に取り組んでいます。

CONSTANTの使い方について疑問を持ったので、
記事にしながら疑問解消しようと思います。

先に結論

Q:変数への値の代入を禁止する「CONSTANT」と、変数へ値を代入する「:=」を併記できるのはなぜ?

A:
「CONSTANT」の役割は「初期値以外の代入を禁止する」ことだから。
単に値の代入を禁止しているのではない。「初期値」を定め、そこからの変更を認めていない、ということ。

疑問

黒本10章問32(p226)中のSQLの意味を調べるために引いた緑本p243に、下記のようにありました。

CONSTANTを付与すると、その変数への値の代入は禁止されます。
変数へ値を代入する際には「:=」という書式を使います。
(引用元:緑本 8章SQLとオブジェクト 8-12関数とプロシージャ p243)

問32にはCONSTANTは登場しませんが、気になるので調べてみます。


この時点で私は

CONSTANTを付与すると、その変数への値の代入は禁止されるのだから、
CONSTANTを使ったときには、「:=」は併用できないのだろう

と思いました。しかし、ドキュメントでCONSTANTの解説&使用例を確認すると

CONSTANTオプションにより、そのブロック内でその値が不変になるように、その変数への初期化後の代入は禁止されます。
(中略)
例:
quantity integer DEFAULT 32;
url varchar := 'http://mysite.com';
user_id CONSTANT integer := 10;
(引用元:PostgreSQL 11.5文書 第43章 PL/pgSQL - SQL手続き言語 43.3. 宣言

とありました。
「CONSTANT」と「:=」が併用されています。

疑問:変数への値の代入を禁止する「CONSTANT」と、変数へ値を代入する「:=」を併記できるのはなぜ?

「変数の代入」自体について、私が全く理解でいていないのだろうな、という予感がしています。
とにもかくにも、調べつつ理解していこうと思います。

変数宣言の構文と例

変数宣言の一般的な構文↓

name [ CONSTANT ] type [ COLLATE collation_name ] [ NOT NULL ] [ { DEFAULT | := | = } expression ];

変数宣言の例↓

quantity integer DEFAULT 32;
url varchar := 'http://mysite.com';
user_id CONSTANT integer := 10;
(引用元:PostgreSQL 11.5文書 第43章 PL/pgSQL - SQL手続き言語 43.3.宣言

読み解く(何言語?意味は?)

Q1:この構文は何言語?

A:PL/pgSQL

PL/pgSQLとは・・・
PostgreSQLデータベースシステム用の読み込み可能な手続き言語。
PLはProcedural Language(手続き型言語)の略。

SQLは基本的には1行で完結するので、手続的なプログラムを書くのは難しい言語。
そのSQLに手続き的な処理を可能にさせるための言語がPL/pgSQL。
(参考:『わたしとぼくのPL/pgSQL』)
(参考:PostgreSQL 11.5文書 第43章 PL/pgSQL - SQL手続き言語 43.3.宣言

Q2:この例文、どこで使う?
関数の構造(基本形)は以下の通り。

DECLARE
変数の宣言
BEGIN
関数の処理記述
END;

上記の「変数の宣言」に入るのが、例文。

Q3:この例文の意味は?

A:以下の通り

quantity integer DEFAULT 32;
変数名はquantity。
数値データ型は整数(integer)。
デフォルト値は32。

url varchar := 'http://mysite.com';
変数名はurl。
文字データ型は上限付き可変長(varchar)。
変数に代入する値は'http://mysite.com'。

user_id CONSTANT integer := 10;
変数名はuser_id。
この変数への値の代入は禁止。 ←疑問の該当箇所!
数値データ型は整数(integer)。
変数に代入する値は10。 ←疑問の該当箇所!

「代入禁止」と「代入する数値は10」が併記されるのはなぜ?

user_id integer := 10;
「CONSTANT」(この変数への値の代入は禁止)
と宣言しておきながら、直後に
「:= 10」(変数に代入する値は10)
と宣言している、というのはなぜなのでしょうか?

「代入する値は「10」で、その後他の値を代入することは認めない」という意味なのでしょうか?
だとしたら、「DEFAULT」で良いはずです。DEFAULTとの違いは何なのでしょうか?

ドキュメントにこうありました。

DEFAULT句が指定された場合、ブロックに入った時に変数に代入される初期値を指定します。 DEFAULT句が指定されない場合、変数はSQLのNULL値に初期化されます。
CONSTANTオプションにより、そのブロック内でその値が不変になるように、その変数への初期化後の代入は禁止されます。
(引用元:PostgreSQL 11.5文書 第43章 PL/pgSQL - SQL手続き言語 43.3.宣言

つまり

・「代入する値は「10」で、その後他の値を代入することは認めない」という意味なのでしょうか?
→Yes。最初に1回だけ値を指定して、その後は代入する値を変更できなくなる、ということ。

・だとしたら、「DEFAULT」で良いはずです。DEFAULTとの違いは何なのでしょうか?
→DEFAULTではダメ。DEFAULTは、初期値。ずっと固定される値ではなく、あくまで最初だけの値。

解決です!

余談 ブロックって何?

ドキュメントに出てきた「ブロック」って何を指すのでしょうか?

PL/pgSQLはブロック構造の言語です。 関数本体のテキスト全体はブロックでなければなりません。
ブロックは以下のように定義されます。

PL/pgSQL
[ <<label>> ]
[ DECLARE
    declarations ]
BEGIN
    statements
END [ label ];

(引用元:PostgreSQL 11.5文書 第43章 PL/pgSQL - SQL手続き言語 43.2.PL/pgSQLの構造

つまり、「関数の変数宣言~関数処理完了(END;)」までの一連のまとまりを「ブロック」と言う。

参考

『わたしとぼくのPL/pgSQL (技術の泉シリーズ(NextPublishing)) Kindle版』目黒 聖

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0