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はブロック構造の言語です。 関数本体のテキスト全体はブロックでなければなりません。
ブロックは以下のように定義されます。
[ <<label>> ]
[ DECLARE
declarations ]
BEGIN
statements
END [ label ];
(引用元:PostgreSQL 11.5文書 第43章 PL/pgSQL - SQL手続き言語 43.2.PL/pgSQLの構造)
つまり、「関数の変数宣言~関数処理完了(END;)」までの一連のまとまりを「ブロック」と言う。