この章ではSQLの構文について説明します。 この章の内容は、データの定義や変更のためにSQLコマンドを適用する方法について詳しく説明する以後の章を理解する上での基礎となります。
規則や概念によっては、SQLデータベースによって異なっていたり、あるいは、PostgreSQLに固有のものなどがありますので、SQLについて熟知しているユーザもこの章を注意深く読むことをお勧めします。
SQLの入力は、ひと続きのコマンドから成ります。 コマンドはトークンが繋がったもので構成され、最後はセミコロン(";")で終わります。 入力ストリームの終了もやはりコマンドを終わらせます。 どのトークンが有効かは特定のコマンドの構文によります。
トークンはキーワード、識別子、引用符で囲まれた識別子、リテラル(もしくは定数)、特別な文字シンボルです。 トークンは通常空白(スペース、タブ、改行)で区切られますが、あいまいさがなければ(一般的には特別な文字が他のトークン型と隣接している場合のみ)必要ありません。
さらに、入力された SQL にコメントが付いていても構いません。 コメントはトークンではなく、効果は空白と同じです。
たとえば、以下のものは(構文的に)正しいSQLの入力です。
SELECT * FROM MY_TABLE; UPDATE MY_TABLE SET A = 5; INSERT INTO MY_TABLE VALUES (3, 'hi there');
この例は1行に1つのコマンドを記述した、3つのコマンドが連続しています(必ずしも1つのコマンドを1行で書く必要はありません。 1行に複数のコマンドを入力することも可能ですし、1つのコマンドを複数行に分けて記述することも可能です)。
SQL構文は、どのトークンがコマンドを識別し、どれがオペランドでどれがパラメータかに関してはさほど首尾一貫していません。 最初のいくつかのトークンは一般にコマンド名です。 したがって、上記の例において"SELECT"、"UPDATE"、"INSERT"コマンドについて通常説明することになります。 しかしたとえばUPDATEコマンドでは、SETトークンが特定の位置に常に記述されなければなりませんし、この例で使われているINSERTコマンドを完結するためにはVALUESトークンが必要です。 それぞれのコマンドの正確な構文規則はパートVIで説明されています。
上記の例に出てくるSELECT、UPDATE、もしくは、VALUESのようなトークンはキーワードの一例です。 キーワードとは、SQL言語で決まった意味を持っている単語です。 MY_TABLEトークンやAトークンは識別子の一例です。 これらは、使われるコマンドによって、テーブル、列、他のデータベースオブジェクトの名前を識別します。 したがって、単に"名前"と呼ばれることもあります。 キーワードと識別子は同じ語彙の構造を持つため、言語を知らなくてはトークンが識別子なのかキーワードなのかわからないということになります。 全てのキーワードのリストは付録Cにあります。
SQL識別子とキーワードは、文字(a〜zか読み分け記号と非Latin文字)、アンダースコア(_)で始まらなければいけません。 識別子またはキーワードの中で続く文字は、文字、アンダースコア、数字(0〜9)を使用することができます。 標準SQLの記述に従うと、ドル印は識別子内では使用できないことに注意してください。 ですから、これを使用するとアプリケーションの移植性は低くなります。 標準SQLでは数字を含む、あるいはアンダースコアで始まったり終わったりするキーワードは定義されていません。 従って、この形式の識別子は標準の今後の拡張と競合する可能性がないという意味で安全といえます。
システムは NAMEDATALEN-1文字以上の識別子の文字数を使いません。 より長い名前をコマンドで書くことはできますが、短く切られてしまいます。 デフォルトでは NAMEDATALENは64なので、識別子は最長で63です。 この制限が問題になる場合は、src/include/postgres_ext.h内のNAMEDATALEN定数の値を変更して増やすことができます。
識別子とキーワード名は大文字と小文字を区別しません。 従って、
UPDATE MY_TABLE SET A = 5;
は、以下の文と同じ意味になります。
uPDaTE my_TabLE SeT a = 5;
慣習的には、キーワードを大文字で、名前を小文字で書きます。 たとえば下記のようになります。
UPDATE my_table SET a = 5;
識別子には他の種類もあります。 区切り識別子あるいは引用符付き識別子です。 任意の文字の連なりを二重引用符(")で囲んだものです。 区切り識別子は常に識別子であって、キーワードではありません。 ですから "select"は"select"という名前の列あるいはテーブルを問い合わせるために使えますが、引用符のつかないselect はキーワードとして理解され、したがってテーブルもしくは列名が期待される部分では解析エラーを起こします。 引用符付き識別子は下記の例のように書くことができます。
UPDATE "my_table" SET "a" = 5;
引用符付き識別子は、二重引用符自身以外であればどのような文字でも使えます。 (二重引用符を含めたい場合は、二重引用符を2つ入力します。) この決まりがあることによって、普段使えない空白やアンパサンド(&)を含むテーブル名や列名を作ることが可能です。 この場合においても長さの制限は適用されます。
引用符がつかない名前は常に小文字に解釈されますが、識別子を引用符で囲むことによって大文字と小文字が区別されるようになります。 たとえば、識別子FOO、foo、"foo"はPostgreSQLによれば同じものとして解釈されますが、"Foo"と"FOO"は、これら3つとも、またお互いとも違ったものとして解釈されます。 (PostgreSQLが引用符の付かない名前を小文字として解釈することは 標準SQLと互換性がありません。標準SQLでは引用符の付かない名前は大文字に解釈されるべきだとされています。 したがって標準SQLによれば、fooは"FOO"と同じであるべきで、"foo"とは異なるはずなのです。 もし移植可能なアプリケーションを書きたいならば、特定の名前は常に引用符で囲むか、あるいは全く囲まないのいずれかに統一することをお勧めします。)
PostgreSQLには、3つの暗黙に型付けされる定数があります。 文字列、ビット文字列、そして数字です。 定数は明示的な型で指定することもでき、その場合はシステムによる、より正確な表現と効率のよい操作が可能になります。 暗黙の定数については以下に説明します。 明示的な定数は後ほど説明します。
SQLの文字列定数は任意の文字の並びを単一引用符("'")で囲ったもので、'This is a string'のようになります。 SQLでは2つ連続した単一引用符を入力することにより、単一引用符を文字列の中に埋め込むことができます(例:'Dianne''s horse')。 PostgreSQLでは、単一引用符の代わりにバックスラッシュ("\")を使うこともできます。 (例:'Dianne\'s horse')
C言語形式のバックスラッシュによるエスケープも有効です。 \bはバックスペース、\fは改頁、\nは改行、\rは復帰(キャリッジリターン)、\tはタブ、xxxが8進数である場合、\xxxは対応するASCIIコードを意味します。 (この場合、そのバイトの並びがサーバ側の文字セット符号化方式内で有効なものであるかどうかは生成者側の責任です。) ここに示した以外のバックスラッシュに続く文字は、文字通りに解釈されます。 したがって、文字列定数にバックスラッシュを含む場合は、バックスラッシュを2つ入力してください。
文字コード0の文字は文字列定数の中には含められません。
2つの文字列定数が、少なくとも1つの改行を含んだ空白で区切られている場合は、2つの定数は連結されて、あたかも1つの定数として書かれたように効率的に処理されます。 例を示します。
SELECT 'foo' 'bar';
は、
SELECT 'foobar';
と同じです。
SELECT 'foo' 'bar';
は有効な構文ではありません。 (この奇妙な振る舞いはSQLで決められているもので、PostgreSQLではこの標準に従っています。)
ビット文字列定数はB(大文字もしくは小文字)が引用符の始まりの前についている(間に空白はありません)文字列定数のように見えます。 たとえばB'1001'のようになります。 ビット文字列定数の中で許可される文字は0と1のみです。
その他にも、ビット文字列定数はX'1FF'といった具合に、先頭にX(大文字または小文字)を使用して16進表記で指定することもできます。 この表記は、各16進数値をそれぞれ4つの2進数値に置き換えたビット文字列定数と同等です。
どちらの形式のビット文字列定数でも、通常の文字列定数と同じように複数行にわたって続けて書くことができます。
数値定数は下記の一般的な形で受け付けられます。
digits digits.[digits][e[+-]digits] [digits].digits[e[+-]digits] digitse[+-]digits
ここで digitsは1つ以上の10進数字(0〜9)です。 小数点を使用する場合は、少なくとも1つの数字が小数点の前か後になくてはなりません。 指数印eの付く形式を使う場合にはeの後に少なくとも1つの数字がなければいけません。 スペースや他の文字は、定数の中に埋め込むことはできません。 プラスまたはマイナスの符号を先頭につけても、定数の一部とは見なされないことに注意してください。 これらの符号は定数に適用される演算子と見なされます。
下記は有効な数値定数のいくつかの例です。
42
3.5
4.
.001
5e2
1.925e-3
小数点も指数句も含まない数値定数の場合、まずその値がinteger型(32ビット)に適合すればinteger型であるとみなされます。 そうでない場合、bigint型(64ビット)で適合すればbigint型とみなされます。 どちらでもない場合は、numeric型とみなされます。 定数が小数点または指数句あるいはその両方を含む場合は、常に最初にnumeric型であるとみなされます。
数値定数に最初に割り振られるデータ型は、型解決アルゴリズムの開始点にすぎません。 ほとんどの場合、定数には文脈に基づいて自動的に正しい型が割り振られます。 必要であれば、特定のデータ型をキャストして、数値がそのデータ型として解釈されるように強制することができます。 たとえば、以下のようにして数値をreal型(float4)として処理することができます。
REAL '1.23' -- 文字列書式 1.23::REAL -- (歴史的な)PostgreSQL書式
任意の型の定数は下記の表記のいずれかを使って入力することができます。
type 'string' 'string'::type CAST ( 'string' AS type )
文字列のテキストはtypeと呼ばれる型の入力変換ルーチンへと渡されます。 結果は指示された型の定数です。 明示的な型キャストは、もし定数がどの型でなければならないかについて曖昧な点がなければ(たとえば引数がオーバーロードされていない関数に渡される場合)省略しても構いません。 その場合自動的に型強制されます。
関数のような構文を使って型強制を指定することも可能です。
typename ( 'string' )
しかし、全ての型の名前でこの方法は使用できません。 詳細は項4.2.8を参照して下さい。
::、CAST()や関数呼び出し構文も、項4.2.8で説明した通り、任意の式の実行時の型変換を指定するために使うことができます。 しかし、type'string'という形式はリテラル定数を指定する場合にのみ使うことができます。 この他type 'string'には、配列型では動作しないことという制限があります。 配列型の定数を指定する場合は::かCAST()を使用して下さい。
演算子はNAMEDATALEN-1までの(デフォルトは63です)長さの、以下に示すリストに含まれる文字の並びです。
+ - * / < > = ~ ! @ # % ^ & | ` ?
しかし、演算子の名前にはいくつかの制約があります。--と/*は演算子名の中に使うことができません。 なぜならこれらはコメントの始まりと解釈されるからです。
複数文字の演算子名は、その名前が少なくとも下記の文字の 1 つ以上を含まない限り、+や-で終わることができません。
~ ! @ # % ^ & | ` ?
たとえば、@-は演算子名として認められていますが、*-は認められていません。 この制限によりPostgreSQLは、SQLに準拠する問い合わせをトークン同士の間に空白を要求せず、解析することができます。
非SQL標準の演算子名を使う場合、通常は曖昧さを回避するために、隣り合った演算子を空白で区切る必要があります。 たとえば@という左単項演算子を定義した場合、X*@Yとは書けません。 PostgreSQLがこれを確実に1つではなく2つの演算子名として解釈できるように、X* @Yと書く必要があります。
英数字ではないいくつかの文字は、演算子であることとは異なる特殊な意味を持っています。 使用法の詳細はそれぞれの構文要素についてのところで説明します。 この節では、単にその存在を知らせ、これらの文字の目的をまとめることに留めます。
直後に数字が続くドル記号($)は、関数定義の本体中の位置パラメータを表すために使われます。 他の文脈ではドル記号は演算子名の一部であるかもしれません。
括弧(())は、通常どおり式をまとめ優先するという意味を持ちます。 場合によっては括弧は、特定のSQLコマンドの固定構文の一部として要求されることがあります。
大かっこ([])は、配列要素を選択するために使われます。 配列に関する詳しい情報は項8.10を参照してください。
カンマ(,)は、リストの要素を区切るために構文的構造体で使われることがあります。
セミコロン(;)は、SQLコマンドの終わりを意味します。 文字列定数または引用符付き識別子以外では、コマンドの途中では使うことができません。
コロン(:)は、配列から"一部分"を取りだすために使われます。 (項8.10を参照してください。) いくつかのSQL方言(埋め込みSQLなど)では、コロンは変数名の接頭辞として使われます。
アスタリスク(*)は、SELECTコマンドの中、あるいはCOUNT集約関数と一緒に使われる場合、特殊な意味を持ちます。
ピリオド(.)は、数値定数の中で使われます。 また、スキーマ、テーブル、列名を区切るためにも使われます。
コメントは二重ハイフンで始まる任意の文字の並びで、行の終わりまで続きます。 たとえば以下のようになります。
-- これは標準SQLのコメントです
他にも、C言語様式のブロックコメントも使用できます。
/* ネストされた複数行に渡る * コメント /* ネストされたブロックコメント */ */
コメントは/*で始まり、対応する*/で終わります。 これらのブロックコメントはC言語とは異なり、標準SQLで指定されているようにネストできます。 したがって、既存のブロックコメントを含む可能性のある大きなコードのブロックをコメントアウトすることができます。
コメントは、その後の構文解析が行われる前に入力ストリームから取り去られ、空白によって適切に置き換えられます。
表4-1は、PostgreSQLの演算子の優先順位と結合性を示しています。 ほとんどの演算子は同じ優先順位を持ち左結合します。 演算子の優先順位と結合性はパーサに組み込まれています。 これは非直感的な動作を導く可能性があります。 たとえば、ブーリアン演算子<と>は、ブーリアン演算子<=と>=とは違った優先順位を持ちます。 さらに、二項演算子と単項演算子を組み合わせて使う場合は括弧を加える必要がある場合があります。 たとえば下記のような場合です。
SELECT 5 ! - 6;
は、
SELECT 5 ! (- 6);
と解析されます。 なぜならば、パーサは!が中置ではなく接尾演算子として定義されていることに最後まで気がつかないためです。 この場合、求める結果を得るためには下記のように書く必要があります。
SELECT (5 !) - 6;
これが拡張性を求めるゆえの代償です。
表 4-1. 演算子の優先順位(強いものから)
演算子/要素 | 結合性 | 説明 |
---|---|---|
. | 左 | テーブル/列名の区切り文字 |
:: | 左 | PostgreSQL方式の型キャスト |
[ ] | 左 | 配列要素選択 |
- | 右 | 単項減算 |
^ | 左 | 羃乗 |
* / % | 左 | 掛け算、割り算、剰余 |
+ - | 左 | 加算、減算 |
IS | IS TRUE、IS FALSE、IS UNKNOWN、IS NULL | |
ISNULL | NULLかどうかを試す | |
NOTNULL | 非NULLかどうかを試す | |
(any other) | 左 | その他すべての組み込み、あるいはユーザ定義の演算子 |
IN | メンバーシップを設定する | |
BETWEEN | 含有 | |
OVERLAPS | 時間間隔の重複 | |
LIKE ILIKE SIMILAR | 文字列パターンのマッチング | |
< > | 小なり、大なり | |
= | 右 | 等しい、代入 |
NOT | 右 | 論理否定 |
AND | 左 | 論理積 |
OR | 左 | 論理和 |
演算子優先順位の規則は、上記で触れた組み込み演算子と同じ名前を持つユーザ定義演算子にも当てはまります。 たとえばもし"+"演算子をある独自のデータ型に定義すると、新しい演算子が何をするかにかかわらず、"+"組み込み演算子と同じ優先順位を持つようになります。
次の例のように、OPERATOR構文でスキーマで修飾された演算子名を使用する場合、
SELECT 3 OPERATOR(pg_catalog.+) 4;
OPERATOR構文は、表4-1の"any other"演算子で示されているデフォルトの優先順位を持つとみなされます。 これは、OPERATOR()にどの特定の演算子が入る場合でも変わりません。