メインコンテンツへスキップ
メインコンテンツへスキップ

構文

このセクションでは、ClickHouse の SQL 構文について説明します。 ClickHouse は SQL をベースにした構文を採用していますが、多くの拡張と最適化を備えています。

クエリのパース

ClickHouse には 2 種類のパーサーがあります。

  • フル SQL パーサー(再帰下降パーサー)
  • データフォーマットパーサー(高速ストリームパーサー)

INSERT クエリ以外のすべてのクエリではフル SQL パーサーが使用され、INSERT クエリでは両方のパーサーが使用されます。

次のクエリを見てみましょう。

INSERT INTO t VALUES (1, 'Hello, world'), (2, 'abc'), (3, 'def')

前述のとおり、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 標準に従う場合。たとえば SELECTselectSeLeCt はすべて有効です。
  • 一般的な一部の DBMS(MySQL や Postgres)での実装に従う場合。たとえば DateTimedatetime と同じです。
注記

データ型名が大文字小文字を区別するかどうかは、system.data_type_families テーブルで確認できます。

標準 SQL とは対照的に、その他すべてのキーワード(関数名を含む)は 大文字小文字を区別します

さらに、キーワードは予約語ではありません。 対応するコンテキスト内でのみ、そのように扱われます。 キーワードと同じ名前の識別子を使用する場合は、ダブルクォートまたはバッククォートで囲んでください。

たとえば、テーブル table_name"FROM" という名前のカラムがある場合、次のクエリは有効です:

SELECT "FROM" FROM table_name

識別子

識別子とは次のものを指します。

識別子は、クォート付きでもクォートなしでもかまいませんが、後者が推奨されます。

クォートなしの識別子は、正規表現 ^[a-zA-Z_][0-9a-zA-Z_]*$ に一致し、かつキーワードと同一であってはなりません。 有効および無効な識別子の例については、以下の表を参照してください。

有効な識別子無効な識別子
xyz, _internal, Id_with_underscores_123_1x, [email protected], äußerst_schön

識別子としてキーワードと同じ名前を使用する場合や、識別子内でそれ以外の記号を使用する場合は、ダブルクォートまたはバッククォートで囲んでください。例: "id"`id`

注記

クォート付き識別子におけるエスケープのルールは、文字列リテラルにも同様に適用されます。詳細は 文字列 を参照してください。

リテラル

ClickHouse において、リテラルとはクエリ内に直接記述される値のことです。 言い換えると、クエリの実行中に変化しない固定の値です。

リテラルには次の種類があります:

以下のセクションで、それぞれについてより詳しく見ていきます。

文字列

文字列リテラルは必ずシングルクォートで囲む必要があります。ダブルクォートはサポートされていません。

エスケープは次のいずれかの方法で行います。

  • 直前にシングルクォートを付ける方法。この場合、シングルクォート文字 '(この文字のみ)は '' としてエスケープできます。
  • 直前にバックスラッシュを付ける方法。以下の表に示すサポートされているエスケープシーケンスを使用します。
注記

バックスラッシュは、下記に列挙されていない文字の前に置かれた場合、その特別な意味を失い、リテラル文字として解釈されます。

サポートされるエスケープ説明
\xHH8 ビット文字の指定で、その後に任意個数の 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 関数を用いて浮動小数点数としてパースされます。
  • それ以外の場合はエラーが返されます。

リテラル値は、その値が収まる最も小さい型にキャストされます。 例:

  • 1UInt8 としてパースされます
  • 256UInt16 としてパースされます。
Important

64 ビットより幅の広い整数値 (UInt128, Int128, UInt256, Int256) を正しくパースするには、より大きな型にキャストする必要があります。

-170141183460469231731687303715884105728::Int128
340282366920938463463374607431768211455::UInt128
-57896044618658097711785492504343953926634992332820282019728792003956564819968::Int256
115792089237316195423570985008687907853269984665640564039457584007913129639935::UInt256

これは上記のアルゴリズムを回避し、任意精度をサポートするルーチンで整数として解析します。

それ以外の場合、リテラルは浮動小数点数として解析されるため、切り捨てによる精度損失の影響を受けます。

詳細については、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つの $ 記号の間に置かれたカスタム文字列リテラルとして定義されます。

例:

SELECT $heredoc$SHOW CREATE VIEW my_view$heredoc$;

┌─'SHOW CREATE VIEW my_view'─┐
│ SHOW CREATE VIEW my_view   │
└────────────────────────────┘
注記
  • 2 つのヒアドキュメントの間にある値は、そのままの文字列として処理されます。
ヒント
  • ヒアドキュメントを使って、SQL、HTML、XML などのコードスニペットを埋め込むことができます。

クエリパラメータの定義と使用

クエリパラメータを使用すると、具体的な識別子の代わりに抽象的なプレースホルダーを含む汎用的なクエリを記述できます。
クエリパラメータを含むクエリが実行されると、すべてのプレースホルダーが解釈され、実際のクエリパラメータ値に置き換えられます。

クエリパラメータを定義する方法は 2 通りあります:

  • SET param_<name>=<value>
  • --param_<name>='<value>'

2 つ目の形式を使用する場合は、コマンドラインで clickhouse-client に渡す引数として指定します。このとき:

  • <name> はクエリパラメータの名前です。
  • <value> はその値です。

クエリパラメータは、クエリ内で {<name>: <datatype>} という形式で参照できます。ここで <name> はクエリパラメータ名、<datatype> はその値が変換されるデータ型です。

SET コマンドの例

たとえば、次の SQL は abcd という名前のパラメータを定義しており、それぞれ異なるデータ型を持ちます:

SET param_a = 13;
SET param_b = 'str';
SET param_c = '2022-08-04 18:30:53';
SET param_d = {'10': [11, 12], '13': [14, 15]};

SELECT
   {a: UInt32},
   {b: String},
   {c: DateTime},
   {d: Map(String, Array(UInt8))};

13    str    2022-08-04 18:30:53    {'10':[11,12],'13':[14,15]}
clickhouse-client を用いた例

clickhouse-client を使用する場合、パラメータは --param_name=value という形式で指定します。たとえば、次のパラメータは名前が message であり、String として取得されます:

clickhouse-client --param_message='hello' --query="SELECT {message: String}"

hello

クエリパラメータがデータベース、テーブル、関数などの識別子名を表す場合は、その型として Identifier を使用します。たとえば、次のクエリは uk_price_paid という名前のテーブルから行を返します:

SET param_mytablename = "uk_price_paid";
SELECT * FROM {mytablename:Identifier};
注記

クエリパラメータは、任意の SQL クエリの任意の場所で使用できる汎用的なテキスト置換ではありません。
主に、識別子やリテラルの代わりとして SELECT 文内で使用されることを想定して設計されています。

関数

関数呼び出しは、識別子に続けて、丸括弧で囲まれた引数リスト(空でも可)を記述します。 標準 SQL とは異なり、引数リストが空の場合でも括弧は必須です。 たとえば、次のように記述します。

now()

また、次のものもあります。

一部の集計関数は、括弧内に 2 つの引数リストを指定できます。例:

quantile (0.9)(x) 

これらの集約関数は「パラメトリック関数」と呼ばれ、 最初のリスト内の引数は「パラメータ」と呼ばれます。

注記

パラメータを持たない集約関数の構文は、通常の関数と同じです。

演算子

演算子は、優先順位と結合性を考慮して、クエリの構文解析時に対応する関数に変換されます。

たとえば、次の式は

1 + 2 * 3 + 4

に変換されます

plus(plus(1, multiply(2, 3)), 4)`

データ型とデータベーステーブルエンジン

CREATE クエリにおけるデータ型とテーブルエンジンは、識別子や関数と同じように記述します。 言い換えると、丸括弧による引数リストを伴う場合もあれば、伴わない場合もあります。

詳細については、次のセクションを参照してください。

Expressions

式 (expression) は次のいずれかです。

  • 関数
  • 識別子
  • リテラル
  • 演算子の適用
  • 括弧で囲まれた式
  • サブクエリ
  • アスタリスク

また、エイリアス を含むこともできます。

式のリストは、カンマで区切られた 1 つ以上の式からなります。 関数および演算子も、その引数として式を受け取ることができます。

定数式は、その結果がクエリ解析中、すなわち実行前に既知である式です。 たとえば、リテラルのみからなる式は定数式です。

式のエイリアス

エイリアスは、クエリ内のに対してユーザーが定義する名前です。

expr AS alias

上記の構文要素について、以下で説明します。

構文要素説明補足
ASエイリアスを定義するためのキーワードです。SELECT 句では、テーブル名やカラム名のエイリアスを、AS キーワードを使わずに定義することもできます。SELECT table_name_alias.column_name FROM table_name table_name_aliasCAST 関数では、AS キーワードには別の意味があります。関数の説明を参照してください。
exprClickHouse がサポートする任意の式です。SELECT column_name * 2 AS double FROM some_table
aliasexpr に付ける名前です。エイリアスは identifiers の構文に従う必要があります。SELECT "table t".column_name FROM table_name AS "table t"

使用上の注意

  • エイリアスはクエリまたはサブクエリ内でグローバルに有効であり、任意の式に対してクエリ中のどの位置でも定義できます。例えば:
SELECT (1 AS n) + 2, n`.
  • エイリアスはサブクエリ内およびサブクエリ間では使用できません。たとえば、次のクエリを実行すると、ClickHouse は Unknown identifier: num という例外をスローします。
`SELECT (SELECT sum(b.a) + num FROM b) - a.a AS num FROM a`
  • サブクエリの SELECT 句で結果列にエイリアスが定義されている場合、これらの列は外側のクエリで参照できます。例えば次の例のようになります。
SELECT n + m FROM (SELECT 1 AS n, 2 AS m)`.
  • 列名やテーブル名と同じエイリアスを定義する場合には注意してください。次の例を見てみましょう。
CREATE TABLE t
(
    a Int,
    b Int
)
ENGINE = TinyLog();

SELECT
    argMax(a, b),
    sum(b) AS b
FROM t;

サーバーから例外を受信しました (バージョン 18.14.17):
Code: 184. DB::Exception: Received from localhost:9000, 127.0.0.1. DB::Exception: クエリ内で集約関数 sum(b) が別の集約関数の内部に見つかりました。

前の例では、列 b を持つテーブル t を宣言しました。 その後、データを選択する際に、sum(b) AS b というエイリアスを定義しました。 エイリアスはグローバルに扱われるため、 ClickHouse は式 argMax(a, b) 内のリテラル b を式 sum(b) に置き換えました。 この置き換えにより、例外が発生しました。

注記

prefer_column_name_to_alias1 に設定することで、このデフォルトの動作を変更できます。

Asterisk

SELECT クエリでは、アスタリスク(*)を式の代わりに使用できます。 詳細は、SELECT セクションを参照してください。