
事象
BigQuery で 標準 SQL を実行しようとした際に以下のエラーが発生した。
エラーメッセージで示された該当箇所は、テーブル名の指定であり、一見しておかしなところは見当たらない。
実行しようとした SQL
INSERT my-project.mydataset.mytable (id, name, subject, score) VALUES ("1111", "John Doe", "Math", 90), ("2222", "Jane Doe", "Math", 95)
エラーメッセージ
Syntax error: Expecting VALUES list or query at [2:7]
※ 末尾の大括弧内の数字はエラー構文の位置を示すため改行やインデント等により異なる

原因
当事象の原因は、プロジェクト ID にダッシュ記号 (別名ハイフン : - ) が使われているのにも関わらず、テーブル指定をバッククォート ( ` ) で囲わなかったことです。
BigQuery では INSERT 句のテーブル識別子がバッククォートで囲まれていない場合、プロジェクト ID にダッシュ記号が使われていると構文エラーとなります。
解説
SQL における BigQuery のテーブル名の指定
BigQuery で標準 SQL を使う際、以下のように、テーブル指定をバッククォート (英語では backquote または backtick) 記号で囲むのが原則です。
SELECT * FROM `my-project.mydataset.mytable`
BigQuery のテーブル識別子は、以下のような構成です。
`(プロジェクト ID).(データセット名).(テーブル名)`
bq コマンドやコンソールからの SQL 投入時等、プロジェクト名が自明の場合は省略することもできます。
またバッククォートは 場合により 省略することができます。しかし 場合により バッククォートで囲まないとエラーとなる場合があります。
バッククォートの要否
ドキュメント「 語彙の構造と構文 」の「テーブル名」の項を確認します。
引用符で囲まれていない識別子は、
FROM句またはTABLE句で参照される場合にダッシュをサポートします。テーブルパスの最初の識別子(プロジェクト ID またはテーブル名)のみがダッシュを使用できます。ダッシュはデータセットではサポートされていません。
プロジェクト名等にダッシュ記号 (ハイフン記号) が使われている場合でかつバッククォートで囲まれていない場合、 FROM 句や TABLE 句の場合は問題なく使えますが、 当記事冒頭で示したような INSERT 句の後ではエラーになってしまうのです。
なおエラーとならない場合として FROM 句や TABLE 句 の他に UPDATE 等もあります。
エラーにならない
SELECT * FROM my-project.mydataset.mytable
CREATE OR REPLACE TABLE my-project.mydataset.mytable ( id STRING, name STRING, subject STRING, score INT64 )
UPDATE my-project.mydataset.mytable SET score = 100 WHERE id = "1111"
エラーになる
INSERT my-project.mydataset.mytable (id, name, subject, score) VALUES ("1111", "John Doe", "Math", 90), ("2222", "Jane Doe", "Math", 95)
対策
対症療法
以下のように SQL を修正すると、構文エラーは発生しません。
バッククォートで囲む
INSERT `my-project.mydataset.mytable` (id, name, subject, score) VALUES ("1111", "John Doe", "Math", 90), ("2222", "Jane Doe", "Math", 95)
バッククォートで囲む (プロジェクト名のみでも可)
INSERT `my-project`.mydataset.mytable (id, name, subject, score) VALUES ("1111", "John Doe", "Math", 90), ("2222", "Jane Doe", "Math", 95)
INTO をつける
INSERT INTO my-project.mydataset.mytable (id, name, subject, score) VALUES ("1111", "John Doe", "Math", 90), ("2222", "Jane Doe", "Math", 95)
原則
コーディング規則として、テーブル識別子はバッククォートで囲むこととするのが望ましいと言えます。
ただし Bash (Linux) 等で bq コマンドを実行する際はバッククォートが別の意味を持つため、適切にエスケープする必要があります。
Bash ではバッククォートは「コマンドの展開」の意味となってしまいますので、バックスラッシュ記号 ( \ ) でバッククォートをエスケープします。
エラーとなるケース
$ bq query --use_legacy_sql=false "SELECT * FROM `my-project.mydataset.mytable`" -bash: my-project.mydataset.mytable: command not found Error in query string: Error processing job 'my-project:bqjob_abcde_0000012345_1': Syntax error: Unexpected end of script at [1:14]
問題ないケース
$ bq query --use_legacy_sql=false "SELECT * FROM \`my-project.mydataset.mytable\`" +------+----------+---------+-------+ | id | name | subject | score | +------+----------+---------+-------+ | 1111 | John Doe | Math | 90 | | 2222 | Jane Doe | Math | 95 | +------+----------+---------+-------+
杉村 勇馬 (記事一覧)
執行役員 CTO
元警察官という経歴を持つ IT エンジニア。クラウド管理・運用やネットワークに知見。AWS 認定資格および Google Cloud 認定資格はすべて取得。X(旧 Twitter)では Google Cloud や Google Workspace のアップデート情報をつぶやいています。
Follow @y_sugi_it