構文
このセクションでは、ClickHouse の SQL 構文について説明します。 ClickHouse は SQL をベースにした構文を採用していますが、多くの拡張と最適化を備えています。
クエリのパース
ClickHouse には 2 種類のパーサーがあります。
- フル SQL パーサー(再帰下降パーサー)
- データフォーマットパーサー(高速ストリームパーサー)
INSERT クエリ以外のすべてのクエリではフル SQL パーサーが使用され、INSERT クエリでは両方のパーサーが使用されます。
次のクエリを見てみましょう。
前述のとおり、INSERT クエリは 2 種類のパーサーの両方を使用します。
INSERT INTO t VALUES の部分はフルパーサーで解析され、
データ (1, 'Hello, world'), (2, 'abc'), (3, 'def') はデータフォーマットパーサー、または高速ストリームパーサーで解析されます。
フルパーサーを有効にする
データに対してフルパーサーを有効にするには、
input_format_values_interpret_expressions 設定を使用します。
上記の設定を 1 にすると、
ClickHouse はまず高速ストリームパーサーで値の解析を試みます。
失敗した場合、ClickHouse はデータを SQL の式として扱い、フルパーサーでの解析を試みます。
データのフォーマットは任意です。
クエリを受信すると、サーバーは RAM 上でリクエストの max_query_size バイト分までしか
処理せず(デフォルトでは 1 MB)、残りはストリームとして解析されます。
これは、大きな INSERT クエリで問題が発生するのを回避するためであり、ClickHouse へのデータ挿入方法として推奨されています。
INSERT クエリで Values フォーマットを使用する場合、
SELECT クエリの式と同じようにデータが解析されているように見えるかもしれませんが、実際にはそうではありません。
Values フォーマットははるかに制限されたものです。
このセクションの残りではフルパーサーについて説明します。
フォーマットパーサーの詳細については、Formats セクションを参照してください。
空白
- 構文要素の間(クエリの先頭および末尾も含めて)には、任意の数の空白文字を入れることができます。
- 空白文字には、スペース、タブ、ラインフィード、CR、フォームフィードが含まれます。
コメント
ClickHouse は、SQL スタイルおよび C スタイルの両方のコメントをサポートしています。
- SQL スタイルのコメントは
--、#!または#で始まり、その行末までがコメントになります。--および#!の後のスペースは省略可能です。 - C スタイルのコメントは
/*から*/までの範囲がコメントとなり、複数行にわたることもあります。スペースも不要です。
キーワード
ClickHouse のキーワードは、コンテキストに応じて 大文字小文字を区別する 場合と 区別しない 場合があります。
次の場合、キーワードは 大文字小文字を区別しません:
- SQL 標準に従う場合。たとえば
SELECT、select、SeLeCtはすべて有効です。 - 一般的な一部の DBMS(MySQL や Postgres)での実装に従う場合。たとえば
DateTimeはdatetimeと同じです。
データ型名が大文字小文字を区別するかどうかは、system.data_type_families テーブルで確認できます。
標準 SQL とは対照的に、その他すべてのキーワード(関数名を含む)は 大文字小文字を区別します。
さらに、キーワードは予約語ではありません。 対応するコンテキスト内でのみ、そのように扱われます。 キーワードと同じ名前の識別子を使用する場合は、ダブルクォートまたはバッククォートで囲んでください。
たとえば、テーブル table_name に "FROM" という名前のカラムがある場合、次のクエリは有効です:
識別子
識別子とは次のものを指します。
識別子は、クォート付きでもクォートなしでもかまいませんが、後者が推奨されます。
クォートなしの識別子は、正規表現 ^[a-zA-Z_][0-9a-zA-Z_]*$ に一致し、かつキーワードと同一であってはなりません。
有効および無効な識別子の例については、以下の表を参照してください。
| 有効な識別子 | 無効な識別子 |
|---|---|
xyz, _internal, Id_with_underscores_123_ | 1x, [email protected], äußerst_schön |
識別子としてキーワードと同じ名前を使用する場合や、識別子内でそれ以外の記号を使用する場合は、ダブルクォートまたはバッククォートで囲んでください。例: "id"、`id`。
クォート付き識別子におけるエスケープのルールは、文字列リテラルにも同様に適用されます。詳細は 文字列 を参照してください。
リテラル
ClickHouse において、リテラルとはクエリ内に直接記述される値のことです。 言い換えると、クエリの実行中に変化しない固定の値です。
リテラルには次の種類があります:
以下のセクションで、それぞれについてより詳しく見ていきます。
文字列
文字列リテラルは必ずシングルクォートで囲む必要があります。ダブルクォートはサポートされていません。
エスケープは次のいずれかの方法で行います。
- 直前にシングルクォートを付ける方法。この場合、シングルクォート文字
'(この文字のみ)は''としてエスケープできます。 - 直前にバックスラッシュを付ける方法。以下の表に示すサポートされているエスケープシーケンスを使用します。
バックスラッシュは、下記に列挙されていない文字の前に置かれた場合、その特別な意味を失い、リテラル文字として解釈されます。
| サポートされるエスケープ | 説明 |
|---|---|
\xHH | 8 ビット文字の指定で、その後に任意個数の 16 進数字 (H) が続きます。 |
\N | 予約されていますが、何もしません(例: SELECT 'a\Nb' は ab を返します) |
\a | ベル |
\b | バックスペース |
\e | エスケープ文字 |
\f | フォームフィード |
\n | ラインフィード |
\r | キャリッジリターン |
\t | 水平タブ |
\v | 垂直タブ |
\0 | ヌル文字 |
\\ | バックスラッシュ |
\' (または '') | シングルクォート |
\" | ダブルクォート |
` | バッククォート |
\/ | スラッシュ |
\= | 等号 |
| ASCII 制御文字 (c <= 31). |
文字列リテラルでは、少なくとも ' と \ を、エスケープコード \'(または '')および \\ を用いてエスケープする必要があります。
Numeric
数値リテラルは次のようにパースされます。
- リテラルがマイナス記号
-で前置されている場合、そのトークンはスキップされ、パース後に結果が負になります。 - 数値リテラルはまず strtoull 関数を用いて 64 ビット符号なし整数としてパースされます。
- 値が
0bまたは0x/0Xで前置されている場合、それぞれ 2 進数または 16 進数としてパースされます。 - 値が負であり、その絶対値が 263 を超える場合はエラーが返されます。
- 値が
- それに失敗した場合、次に strtod 関数を用いて浮動小数点数としてパースされます。
- それ以外の場合はエラーが返されます。
リテラル値は、その値が収まる最も小さい型にキャストされます。 例:
1はUInt8としてパースされます256はUInt16としてパースされます。
64 ビットより幅の広い整数値 (UInt128, Int128, UInt256, Int256) を正しくパースするには、より大きな型にキャストする必要があります。
これは上記のアルゴリズムを回避し、任意精度をサポートするルーチンで整数として解析します。
それ以外の場合、リテラルは浮動小数点数として解析されるため、切り捨てによる精度損失の影響を受けます。
詳細については、Data types を参照してください。
数値リテラル内のアンダースコア _ は無視され、可読性向上のために使用できます。
次の数値リテラルがサポートされています。
| 数値リテラル | 例 |
|---|---|
| 整数 | 1, 10_000_000, 18446744073709551615, 01 |
| 小数 | 0.1 |
| 指数表記 | 1e100, -1e-100 |
| 浮動小数点数 | 123.456, inf, nan |
| 16 進数 | 0xc0fe |
| SQL 標準互換 16 進文字列 | x'c0fe' |
| 2 進数 | 0b1101 |
| SQL 標準互換 2 進文字列 | b'1101' |
解釈時の偶発的なエラーを避けるため、8 進数リテラルはサポートされていません。
複合リテラル
配列は [1, 2, 3] のように角かっこで表記します。タプルは (1, 'Hello, world!', 2) のように丸かっこで表記します。
厳密には、これらはリテラルではなく、それぞれ配列生成演算子およびタプル生成演算子を用いた式です。
配列は少なくとも 1 つの要素を含む必要があり、タプルは少なくとも 2 つの要素を持つ必要があります。
SELECT クエリの IN 句にタプルが現れる場合は、別のケースとして扱われます。
クエリ結果にはタプルを含めることができますが、タプルは(Memory エンジンを使用するテーブルを除き)データベースに保存できません。
NULL
NULL は、値が存在しないことを示すために使用されます。
テーブルのカラムに NULL を保存するには、そのカラムが Nullable 型である必要があります。
NULL については、次の点に注意してください:
- データ形式(入力または出力)によっては、
NULLの表現が異なる場合があります。詳細については、data formats を参照してください。 NULLの処理には注意が必要です。たとえば、比較演算の引数の少なくとも一方がNULLの場合、その演算の結果もNULLになります。乗算、加算、その他の演算についても同様です。各演算のドキュメントを参照することを推奨します。- クエリ内では、
IS NULLおよびIS NOT NULL演算子と、関連する関数isNullおよびisNotNullを使用してNULLかどうかを判定できます。
ヒアドキュメント
heredoc は、元の書式を保ったまま文字列(多くの場合は複数行)を定義するための方法です。
heredoc は、2つの $ 記号の間に置かれたカスタム文字列リテラルとして定義されます。
例:
- 2 つのヒアドキュメントの間にある値は、そのままの文字列として処理されます。
- ヒアドキュメントを使って、SQL、HTML、XML などのコードスニペットを埋め込むことができます。
クエリパラメータの定義と使用
クエリパラメータを使用すると、具体的な識別子の代わりに抽象的なプレースホルダーを含む汎用的なクエリを記述できます。
クエリパラメータを含むクエリが実行されると、すべてのプレースホルダーが解釈され、実際のクエリパラメータ値に置き換えられます。
クエリパラメータを定義する方法は 2 通りあります:
SET param_<name>=<value>--param_<name>='<value>'
2 つ目の形式を使用する場合は、コマンドラインで clickhouse-client に渡す引数として指定します。このとき:
<name>はクエリパラメータの名前です。<value>はその値です。
クエリパラメータは、クエリ内で {<name>: <datatype>} という形式で参照できます。ここで <name> はクエリパラメータ名、<datatype> はその値が変換されるデータ型です。
SET コマンドの例
たとえば、次の SQL は a、b、c、d という名前のパラメータを定義しており、それぞれ異なるデータ型を持ちます:
clickhouse-client を用いた例
clickhouse-client を使用する場合、パラメータは --param_name=value という形式で指定します。たとえば、次のパラメータは名前が message であり、String として取得されます:
クエリパラメータがデータベース、テーブル、関数などの識別子名を表す場合は、その型として Identifier を使用します。たとえば、次のクエリは uk_price_paid という名前のテーブルから行を返します:
クエリパラメータは、任意の SQL クエリの任意の場所で使用できる汎用的なテキスト置換ではありません。
主に、識別子やリテラルの代わりとして SELECT 文内で使用されることを想定して設計されています。
関数
関数呼び出しは、識別子に続けて、丸括弧で囲まれた引数リスト(空でも可)を記述します。 標準 SQL とは異なり、引数リストが空の場合でも括弧は必須です。 たとえば、次のように記述します。
また、次のものもあります。
一部の集計関数は、括弧内に 2 つの引数リストを指定できます。例:
これらの集約関数は「パラメトリック関数」と呼ばれ、 最初のリスト内の引数は「パラメータ」と呼ばれます。
パラメータを持たない集約関数の構文は、通常の関数と同じです。
演算子
演算子は、優先順位と結合性を考慮して、クエリの構文解析時に対応する関数に変換されます。
たとえば、次の式は
に変換されます
データ型とデータベーステーブルエンジン
CREATE クエリにおけるデータ型とテーブルエンジンは、識別子や関数と同じように記述します。
言い換えると、丸括弧による引数リストを伴う場合もあれば、伴わない場合もあります。
詳細については、次のセクションを参照してください。
Expressions
式 (expression) は次のいずれかです。
- 関数
- 識別子
- リテラル
- 演算子の適用
- 括弧で囲まれた式
- サブクエリ
- アスタリスク
また、エイリアス を含むこともできます。
式のリストは、カンマで区切られた 1 つ以上の式からなります。 関数および演算子も、その引数として式を受け取ることができます。
定数式は、その結果がクエリ解析中、すなわち実行前に既知である式です。 たとえば、リテラルのみからなる式は定数式です。
式のエイリアス
エイリアスは、クエリ内の式に対してユーザーが定義する名前です。
上記の構文要素について、以下で説明します。
| 構文要素 | 説明 | 例 | 補足 |
|---|---|---|---|
AS | エイリアスを定義するためのキーワードです。SELECT 句では、テーブル名やカラム名のエイリアスを、AS キーワードを使わずに定義することもできます。 | SELECT table_name_alias.column_name FROM table_name table_name_alias | CAST 関数では、AS キーワードには別の意味があります。関数の説明を参照してください。 |
expr | ClickHouse がサポートする任意の式です。 | SELECT column_name * 2 AS double FROM some_table | |
alias | expr に付ける名前です。エイリアスは identifiers の構文に従う必要があります。 | SELECT "table t".column_name FROM table_name AS "table t" |
使用上の注意
- エイリアスはクエリまたはサブクエリ内でグローバルに有効であり、任意の式に対してクエリ中のどの位置でも定義できます。例えば:
- エイリアスはサブクエリ内およびサブクエリ間では使用できません。たとえば、次のクエリを実行すると、ClickHouse は
Unknown identifier: numという例外をスローします。
- サブクエリの
SELECT句で結果列にエイリアスが定義されている場合、これらの列は外側のクエリで参照できます。例えば次の例のようになります。
- 列名やテーブル名と同じエイリアスを定義する場合には注意してください。次の例を見てみましょう。
前の例では、列 b を持つテーブル t を宣言しました。
その後、データを選択する際に、sum(b) AS b というエイリアスを定義しました。
エイリアスはグローバルに扱われるため、
ClickHouse は式 argMax(a, b) 内のリテラル b を式 sum(b) に置き換えました。
この置き換えにより、例外が発生しました。
prefer_column_name_to_alias を 1 に設定することで、このデフォルトの動作を変更できます。
Asterisk
SELECT クエリでは、アスタリスク(*)を式の代わりに使用できます。
詳細は、SELECT セクションを参照してください。