すべてのプロダクト
Search
ドキュメントセンター

PolarDB:Lexicalの構造

最終更新日:Jun 03, 2024

SQL入力は、一連のコマンドで構成されます。 コマンドは、トークンのシーケンスで構成され、セミコロン (";") で終了します。 入力ストリームの終わりはまた、コマンドを終了させる。 どのトークンが有効であるかは、特定のコマンドの構文に依存する。

概要

トークンは、キーワード識別子引用された識別子リテラル (または定数) 、または特殊文字シンボルにすることができます。 トークンは通常、空白 (スペース、タブ、改行) で区切られますが、あいまいさがない場合 (通常、特殊文字が他のトークンの種類に隣接している場合にのみそうである) は必要ありません。

たとえば、以下は (構文的に) 有効なSQL入力です。

SELECT * からMY_TABLE;
    UPDATE MY_TABLE SET A = 5;
    MY_TABLE値に挿入します (3、'hi there'); 

これは、行ごとに1つずつ、3つのコマンドのシーケンスです (ただし、これは必須ではありません。1つの行に複数のコマンドを配置することができ、コマンドを行に分割することができます) 。

さらに、コメントはSQL入力で発生する可能性があります。 それらはトークンではなく、事実上空白と同等です。

SQL構文は、どのトークンがコマンドを識別し、どのトークンがオペランドまたはパラメータであるかに関してあまり一貫していない。 最初のいくつかのトークンは一般にコマンド名であるため、上記の例では、通常、「SELECT」、「UPDATE」、および「INSERT」コマンドについて説明します。 しかし、例えば、UPDATEコマンドは、常にSETトークンが特定の位置に現れることを必要とし、INSERTのこの特定のバリエーションは、完了するためにVALUESも必要とする。

識別子とキーワード

上記の例のSELECTUPDATEVALUESなどのトークンは、SQL言語で固定された意味を持つキーワードの例です。 トークンMY_TABLEおよびAは、識別子の例である。 これらは、使用するコマンドに応じて、テーブル、列、またはその他のデータベースオブジェクトの名前を識別します。 したがって、それらは単に「名前」と呼ばれることもあります。 キーワードと識別子は同じ語彙構造を持っています。つまり、言語を知らなければ、トークンが識別子であるかキーワードであるかを知ることはできません。

SQL識別子とキーワードは、文字 (a-zだけでなく、発音区別符号と非ラテン文字を含む文字) またはアンダースコア (_) で始まる必要があります。 識別子またはキーワードの後続の文字は、文字、アンダースコア、数字 (09) 、またはドル記号 ($) です。 SQL標準の文字によると、ドル記号は識別子に許可されていないため、それらを使用するとアプリケーションの移植性が低下する可能性があります。 SQL標準は、数字を含むキーワード、またはアンダースコアで開始または終了するキーワードを定義しないため、この形式の識別子は、標準の将来の拡張機能との競合の可能性に対して安全です。

システムはNAMEDATALENを超えない-1バイトの識別子を使用します。長い名前はコマンドに書き込むことができますが、切り捨てられます。 デフォルトでは、NAMEDATALENは64なので、識別子の最大長は63バイトです。 この制限に問題がある場合は、src/include/pg_config_manual.hNAMEDATALEN定数を変更することで引き上げることができます。

キーワードと引用符なしの識別子は大文字と小文字を区別しません。 したがって:

UPDATE MY_TABLE SET A = 5;

と同等に書くことができます:

uPDaTE my_TabLE SeT a = 5;

よく使用される規則は、大文字でキーワードを、小文字で名前を書くことです。

UPDATE my_table SET a = 5;

第2の種類の識別子: 区切り識別子または引用識別子がある。 これは、任意の文字列を二重引用符 (") で囲むことによって形成されます。 区切られた識別子は常に識別子であり、キーワードではありません。 したがって、「select」を使用して「select」という名前の列またはテーブルを指すことができますが、引用符のないselectはキーワードと見なされるため、テーブルまたは列の名前が予想される場合に使用されると解析エラーが発生します。 この例は、次のような引用符付き識別子で記述できます。

UPDATE "my_table" SET "a" = 5;

引用された識別子には、コードゼロの文字を除く任意の文字を含めることができます。 (二重引用符を含めるには、二重引用符を2つ書きます。) これにより、スペースやアンパサンドを含むものなど、他の方法では不可能なテーブルまたは列名を構築できます。 長さの制限は依然として適用される。

識別子を引用すると、大文字と小文字が区別されますが、引用されていない名前は常に小文字に折りたたまれます。 たとえば、識別子FOOfoo、および「foo」はPostgreSQLでは同じと見なされますが、「Foo」「FOO」はこれら3つとは異なります。 (引用されていない名前の小文字inPostgreSQLへの折りたたみは、引用されていない名前を大文字に折りたたむ必要があるというSQL標準と互換性がありません。 したがって、fooは、規格によれば、「FOO」ではなく「foo」と同等であるべきである。 ポータブルアプリケーションを作成する場合は、常に特定の名前を引用するか、引用しないことをお勧めします。

引用された識別子の変形により、コードポイントによって識別されるエスケープされたUnicode文字を含めることができます。 この変形は、U& (大文字または小文字のUの後にアンパサンドが続く) で始まり、その間にスペースがない (U&"foo" など) 。 (これは演算子 & とのあいまいさを作成することに注意してください。 この問題を回避するには、演算子の周りのスペースを使用します。引用符の内側には、バックスラッシュの後に4桁の16進コードポイント番号を書き込むか、バックスラッシュの後にプラス記号の後に6桁の16進コードポイント番号を書き込むことで、Unicode文字をエスケープ形式で指定できます。 たとえば、識別子「データ」

U&"d\0061t\+ 000061"

次のそれほど些細な例は、ロシア語の「slon」 (象) をキリル文字で書いています。

U&"\0441\043B\043E\043D"

バックスラッシュとは異なるエスケープ文字が必要な場合は、文字列の後にUESCAPE句を使用して指定できます。

U&"d!0061t! 000061" UESCAPE '!'

エスケープ文字は、16進数字、プラス記号、単一引用符、二重引用符、または空白文字以外の任意の単一文字とすることができる。 エスケープ文字は、UESCAPEの後に二重引用符ではなく、一重引用符で書かれていることに注意してください。

識別子にエスケープ文字を文字通り含めるには、2回書き込みます。

4桁または6桁のエスケープフォームのいずれかを使用して、UTF-16のサロゲートペアを指定して、U + FFFFよりも大きなコードポイントで文字を作成できますが、6桁のフォームを使用できるため、技術的にはこれは不要です。 (代理ペアは直接保存されませんが、単一のコードポイントに結合されます。)

サーバーのエンコードがUTF-8されていない場合、これらのエスケープシーケンスのいずれかによって識別されるUnicodeコードポイントは実際のサーバーのエンコードに変換されます。

定数

PostgreSQLには、暗黙的に型指定された定数には、文字列、ビット文字列、および数値の3種類があります。 定数は、システムによるより正確な表現およびより効率的な処理を可能にすることができる明示的な型で指定することもできる。 これらの代替案は、以下のサブセクションで議論される。

文字列定数

SQLの文字列定数は、一重引用符 (') で囲まれた文字の任意のシーケンスです。たとえば、「This is A string」です。 文字列定数内に単一引用符文字を含めるには、2つの隣接する単一引用符、たとえば「Dianne」の馬」を書きます。 これは二重引用符 (") と同じではないことに注意してください。

少なくとも1つの改行を持つ空白で区切られた2つの文字列定数は連結され、文字列が1つの定数として書き込まれたかのように効果的に扱われます。 設定例:

SELECT 'foo'
    'バー'; 

は以下と同等です。

SELECT 'foobar';

しかし:

SELECT 'foo' 'bar';

は有効な構文ではありません。 (この少し奇妙な動作はSQLによって指定されます。PostgreSQLは標準に従います。)

Cスタイルのエスケープを持つ文字列定数

PostgreSQLは、SQL標準の拡張である「エスケープ」文字列定数も受け入れます。 エスケープ文字列定数は、例えばE'foo' のような、最初の単一引用符の直前に文字E (大文字または小文字) を書くことによって指定される。 (エスケープ文字列定数を行にまたがって続ける場合は、最初のオープニングクォートの前にのみEを書きます。) エスケープ文字列内で、バックスラッシュ文字 (\) は、Cのようなバックスラッシュエスケープシーケンスを開始します。バックスラッシュとそれに続く文字の組み合わせは、特殊なバイト値を表します。

バックスラッシュエスケープ

バックスラッシュエスケープシーケンス

解釈

\b

バックスペース

\f

フォームフィード

\n

改行

\r

キャリッジリターン

\t

タブ

\, \, \(o= 0-7)

octalバイト値

\x, \x (h= 0-9, A-F)

16進バイト値

\u\U (x= 0-9、A-F)

16ビットまたは32ビットの16進数Unicode文字値

バックスラッシュに続く他のキャラクターは文字通り取られます。 したがって、バックスラッシュ文字を含めるには、バックスラッシュ (\\) を2つ書きます。 また、''の通常の方法に加えて、\' を書くことで、単一の引用符をエスケープ文字列に含めることができます。

作成するバイトシーケンスは、特に8進数または16進数のエスケープを使用する場合、サーバー文字セットのエンコーディングで有効な文字を作成する責任があります。 便利な代替手段は、Unicodeエスケープまたは代替のUnicodeエスケープ構文を使用することです。その後、サーバーは文字変換が可能であることを確認します。

重要

設定パラメーターstandard_conforming_stringsoffの場合、PostgreSQLは通常の文字列定数とエスケープ文字列定数の両方でバックスラッシュエスケープを認識します。 ただし、PostgreSQL 9.1の時点では、デフォルトはonです。つまり、バックスラッシュエスケープはエスケープ文字列定数でのみ認識されます。 この動作は標準に準拠していますが、バックスラッシュのエスケープが常に認識されていた履歴動作に依存するアプリケーションを壊す可能性があります。 回避策として、このパラメーターをoffに設定できますが、バックスラッシュエスケープを使用しないように移行することをお勧めします。 バックスラッシュエスケープを使用して特殊文字を表す必要がある場合は、文字列定数にEを記述します。

standard_conforming_stringsに加えて、設定パラメーターescape_string_warningbackslash_quoteは、文字列定数のバックスラッシュの処理を管理します。

unicodeエスケープを持つ文字列定数

PostgreSQLは、コードポイントで任意のUnicode文字を指定できる文字列の別の種類のエスケープ構文もサポートしています。 Unicodeエスケープ文字列定数は、U& (大文字または小文字のUの後にアンパサンドが続く) で始まります。たとえば、U&'foo' のように、間にスペースはありません。 (これは演算子 & とのあいまいさを作成することに注意してください。 この問題を回避するには、演算子の周りのスペースを使用します。引用符の内側には、バックスラッシュの後に4桁の16進コードポイント番号を書き込むか、バックスラッシュの後にプラス記号の後に6桁の16進コードポイント番号を書き込むことで、Unicode文字をエスケープ形式で指定できます。 たとえば、文字列 'data'

U&'d\0061t\+ 000061 '

次のそれほど些細な例は、ロシア語の「slon」 (象) をキリル文字で書いています。

U&'\0441\043B\043E\043D'

バックスラッシュとは異なるエスケープ文字が必要な場合は、文字列の後にUESCAPE句を使用して指定できます。

U&'d!0061t!+ 000061 'UESCAPE'!'

エスケープ文字は、16進数字、プラス記号、単一引用符、二重引用符、または空白文字以外の任意の単一文字とすることができる。

文字列にエスケープ文字を文字通り含めるには、2回書き込みます。

4桁または6桁のエスケープフォームのいずれかを使用して、UTF-16のサロゲートペアを指定して、U + FFFFよりも大きなコードポイントで文字を作成できますが、6桁のフォームを使用できるため、技術的にはこれは不要です。 (代理ペアは直接保存されませんが、単一のコードポイントに結合されます。)

サーバーのエンコードがUTF-8されていない場合、これらのエスケープシーケンスのいずれかによって識別されるUnicodeコードポイントは実際のサーバーのエンコードに変換されます。

また、文字列定数のUnicodeエスケープ構文は、設定パラメーターstandard_conforming_stringsがオンになっている場合にのみ機能します。 これは、この構文がSQL文を解析するクライアントを混乱させ、SQLインジェクションや同様のセキュリティ問題につながる可能性があるためです。 パラメーターがoffに設定されている場合、この構文はエラーメッセージで拒否されます。

ドル引用文字列定数

文字列定数を指定するための標準構文は通常便利ですが、それぞれを2倍にする必要があるため、目的の文字列に多くの単一引用符が含まれている場合を理解するのは困難です。 このような状況でより読みやすいクエリを可能にするために、PostgreSQLは「ドル引用」と呼ばれる別の方法で文字列定数を記述します。 ドル引用文字列定数は、ドル記号 ($) 、0文字以上のオプションの「タグ」、別のドル記号、文字列コンテンツを構成する任意の文字列、ドル記号、このドル引用を開始した同じタグ、およびドル記号で構成されます。 たとえば、ドルの引用を使用して文字列「Dianne's horse」を指定する方法は2つあります。

$$ダイアンの馬 $$
    $SomeTag $ダイアンの马 $SomeTag$ 

ドル相場文字列内では、エスケープする必要なく単一相場を使用できることに注意してください。 実際、ドルで引用された文字列内の文字はエスケープされません。文字列の内容は常に文字通りに書かれています。 バックスラッシュは特別ではなく、開始タグと一致するシーケンスの一部でない限り、ドル記号でもありません。

各ネストレベルで異なるタグを選択することにより、ドル引用文字列定数をネストすることができます。 これは関数定義の記述で最も一般的に使用されます。 設定例:

$function $
    BEGIN
        RETURN ($1 ~ $q$[\t\r\n\v \]$q$);
    END;
    $function$ 

ここで、シーケンス $q$[\t\r\n\v\\]$q$ は、ドル引用リテラル文字列 [\t\r\n\v\\] を表します。 ただし、シーケンスは外側のドル引用区切り文字 $関数 $と一致しないため、外側の文字列に関する限り、定数内のいくつかの文字が追加されます。

ドルで引用された文字列のタグは、もしあれば、ドル記号を含めることができないことを除いて、引用されていない識別子と同じ規則に従う。 タグは大文字と小文字が区別されるため、$tag$String content$tagは正しいですが、$TAG$String content$tag$ は正しくありません。

キーワードまたは識別子に続くドル引用文字列は、空白で区切る必要があります。そうでない場合、ドル引用区切り文字は前の識別子の一部として使用されます。

ドルの引用はSQL標準の一部ではありませんが、標準に準拠した単一引用構文よりも複雑な文字列リテラルを記述する方が便利な方法であることがよくあります。 これは、手続き型関数定義でしばしば必要とされるように、他の定数内の文字列定数を表すときに特に有用である。 単一引用符構文では、上記の例の各バックスラッシュは4つのバックスラッシュとして記述する必要があります。これは、元の文字列定数を解析する際に2つのバックスラッシュに縮小され、関数の実行中に内部文字列定数が再解析されると1つになります。

ビット文字列定数

ビットストリング定数は、例えばB'1001' のように、開始クォートの直前にB (大文字または小文字) を有する正規のストリング定数のように見える。 ビットストリング定数内で許容される唯一の文字は、01である。

あるいは、ビット列定数は、先頭のX (大文字または小文字) 、たとえばX'1FF' を使用して、16進表記で指定することができる。 この表記は、各16進数に対して4つの2進数を有するビット列定数と等価である。

どちらの形式のビットストリング定数も、通常のストリング定数と同じ方法でラインを横切って継続することができます。 ドルの引用は、ビット列定数では使用できません。

数値定数

数値定数は、次の一般的な形式で受け入れられます。

桁
    digits.[digits][e[+-]digits]
    [digits].digits[e[+-]digits]
    digitse[+-] 桁 

ここで、digitsは1つ以上の10進数 (0〜9) です。 1つを使用する場合、小数点の前または後に少なくとも1つの桁が必要です。 指数マーカー (e) が存在する場合、少なくとも1つの数字が続く必要があります。 定数にスペースやその他の文字を埋め込むことはできません。 先頭のプラスまたはマイナスの符号は、実際には定数の一部とは見なされず、定数に適用される演算子であることに注意してください。

有効な数値定数の例をいくつか示します。

42 3.5 4. . 001 5e2 1.925e-3

小数点も指数も含まない数値定数は、最初は型であると推定されます。整数その値が型に収まる場合は整数(32ビット); それ以外の場合はタイプであると推定されますビギントその値が型に収まる場合はビギント(64ビット); それ以外の場合は数値. 小数点および /または指数を含む定数は、最初は常に数値型であると推定されます。

数値定数の最初に割り当てられたデータ型は、型解決アルゴリズムの開始点にすぎません。 ほとんどの場合、定数はコンテキストに応じて自動的に最適なタイプに強制されます。 たとえば、次のように記述することで、数値を強制的にreal型 (float4) として扱うことができます。

REAL '1.23 '-- 文字列スタイル
    1.23::REAL -- PostgreSQL (履歴) スタイル 

これらは実際には、次に説明する一般的なキャスティング表記の特別なケースにすぎません。

他のタイプの定数

任意の型の定数は、次の表記法のいずれかを使用して入力できます。

型 'string'
    'string':: タイプ
    CAST ( 'string' ASタイプ) 

文字列定数のテキストは、typeと呼ばれる型の入力変換ルーチンに渡されます。 結果は、示されたタイプの定数です。 明示的な型キャストは、定数が必要な型に関して曖昧さがない場合 (たとえば、テーブル列に直接割り当てられている場合) には省略できます。この場合、自動的に強制されます。

文字列定数は、通常のSQL表記またはドル引用のいずれかを使用して記述できます。

関数のような構文を使用して型強制を指定することもできます。

typename ( 'string ' )

ただし、すべての型名をこの方法で使用できるわけではありません。

:CAST() 、および関数呼び出し構文を使用して、任意の式のランタイム型変換を指定することもできます。 構文のあいまいさを回避するために、''構文は単純なリテラル定数の型を指定するためにのみ使用できます。 ''構文のもう1つの制限は、配列型では機能しないことです。配列定数の型を指定するには、:: またはCAST() を使用します。

CAST() 構文はSQLに準拠しています。 ''構文は、標準の一般化です。SQLは、この構文をいくつかのデータ型に対してのみ指定し、butPostgreSQLallowesすべての型に対して指定します。 : の構文はhistoricalPostgreSQLusageで、関数呼び出し構文も同様です。

演算子

演算子名は、次のリストから最大NAMEDATALEN -1 (デフォルトでは63) 文字のシーケンスです。

+ - * / < > = ~!@ # % ^ & | '?

ただし、オペレータ名にはいくつかの制限があります。

  • -/* は、コメントの先頭となるため、演算子名のどこにも表示できません。

  • 複数文字の演算子名は、名前にこれらの文字の少なくとも1つが含まれていない限り、+ または-で終わることはできません。

    ~ !@ # % ^ & | '?

    たとえば、@- は許可された演算子名ですが、*- は許可されません。 この制限により、PostgreSQLはトークン間にスペースを必要とせずにSQL準拠のクエリを解析できます。

通常、非SQL標準の演算子名を使用する場合は、あいまいさを避けるために、隣接する演算子をスペースで区切る必要があります。 たとえば、@ という名前のプレフィックス演算子を定義した場合、X * @ Yは記述できません。X * @ Yを記述して、PostgreSQLが1つではなく2つの演算子名として読み取るようにする必要があります。

特殊文字

英数字ではないいくつかの文字は、演算子であることとは異なる特別な意味を有する。 使用に関する詳細は、それぞれのシンタックス要素が記述されている場所で見つけることができる。 このセクションは、これらのキャラクターの存在をアドバイスし、目的を要約するためにのみ存在します。

  • 数字が続くドル記号 ($) は、関数定義または準備されたステートメントの本体の位置パラメーターを表すために使用されます。 他のコンテキストでは、ドル記号は、識別子またはドル引用文字列定数の一部とすることができる。

  • 括弧 (()) は、式をグループ化して優先順位を適用するという通常の意味を持ちます。 場合によっては、特定のSQLコマンドの固定構文の一部として括弧が必要になります。

  • ブラケット ([]) は、配列の要素を選択するために使用されます。

  • コンマ () は、リストの要素を区切るために一部の構文構成で使用されます。

  • セミコロン (;) はSQLコマンドを終了します。 文字列定数または引用符付き識別子以外のコマンド内のどこにも表示できません。

  • コロン (:) は、配列から「スライス」を選択するために使用されます。 特定のSQL方言 (Embedded SQLなど) では、変数名のプレフィックスにコロンが使用されます。

  • アスタリスク (*) は、テーブル行または複合値のすべてのフィールドを示すコンテキストで使用されます。 また、集計関数の引数として使用される場合、つまり、集計が明示的なパラメーターを必要としないという特別な意味もあります。

  • ピリオド (.) は数値定数で使用され、スキーマ、テーブル、および列名を区切ります。

Comments

コメントは、2重のダッシュで始まり、行の最後まで伸びる一連の文字です。例:

-- これは標準SQLコメント
です

または、Cスタイルのブロックコメントを使用できます。

/* 複数行のコメント
     * ネスト付き: /* ネストされたブロックコメント * /
     */

コメントは /* で始まり、一致する */ の出現まで拡張されます。 これらのブロックコメントは、SQL標準で指定されているようにネストされますが、Cとは異なり、既存のブロックコメントを含む可能性のあるより大きなコードブロックをコメントアウトできます。

コメントは、さらなる構文解析の前に入力ストリームから削除され、効果的に空白に置き換えられます。

演算子の優先順位

次の表は、PostgreSQLの演算子の優先順位と結合性を示しています。 ほとんどの演算子は同じ優先順位を持ち、左連想です。 演算子の優先順位と結合性はパーサーに組み込まれています。 複数の演算子を持つ式を、優先順位ルールが意味する以外の方法で解析する場合は、括弧を追加します。

演算子の優先順位 (最高から最低)

演算子 /要素

連想性

説明

.

テーブル /列名セパレータ

::

PostgreSQLスタイルのタイプキャスト

[]

配列要素の選択

+-

unaryプラス、unaryマイナス

^

指数

*/%

乗算、除算、モジュロ

+-

加算、減算

(他の演算子)

他のすべてのネイティブおよびユーザー定義の演算子

の間イン好きILIKE類似

範囲包含、集合メンバーシップ、文字列マッチング

< >=<= >= <>

比較演算子

IS ISNULL NOTNULL

IS TRUEIS FALSEIS NULLIS DISTINCT FROMなど

ではない

論理否定

そして

論理結合

または

論理和

演算子の優先順位ルールは、上記の組み込み演算子と同じ名前のユーザー定義演算子にも適用されることに注意してください。 たとえば、一部のカスタムデータ型に「 + 」演算子を定義すると、自分が何をしても、組み込みの「 + 」演算子と同じ優先順位になります。

スキーマ修飾演算子名がoperator構文で使用されている場合、たとえば次のようになります。

SELECT 3 OPERATOR(pg_catalog.+) 4;

の場合、OPERATORコンストラクトは、「その他の演算子」について上記の表に示すデフォルトの優先順位を持つようになります。 これは、operator () 内にどの特定の演算子が表示されても当てはまります。