MySQL でテーブル名またはカラム名に予約語を使用した場合の構文エラー

mysql reserved-words


以下のような簡単なMySQLクエリを実行しようとしています。

INSERT INTO user_details (username, location, key)
VALUES ('Tim', 'Florida', 42)

しかし、以下のようなエラーが出てしまいます。

エラー1064(42000):SQL構文にエラーがあります。MySQLサーバーのバージョンに対応するマニュアルで、 'key) VALUES ('Tim', 'Florida', 42)' 近くで使用する正しい構文について、1行目で確認してください

どうすれば問題を解決できますか?




Answer 1 Amal Murali


問題点

MySQLでは、 SELECTINSERTDELETE などの特定の単語は予約語です。それらは特別な意味を持っているので、MySQLはそれらをテーブル名、カラム名、または他の種類の識別子として使用するときはいつでも、構文エラーとして扱います-識別子をバッククォートで囲まない限り。

公式ドキュメントに記載されているように、セクション10.2スキーマオブジェクト名(強調が追加されています):

MySQL内の特定のオブジェクト(データベース、テーブル、インデックス、列、エイリアス、ビュー、ストアドプロシージャ、パーティション、テーブルスペース、その他のオブジェクト名など)は、識別子と呼ばれます

...

識別子に特殊文字が含まれている場合、または予約語である場合は、参照するときは常に引用符で囲む必要あります。

...

識別子の引用文字はバックティック( " ` ")です。

キーワードと予約語の完全なリストは、セクション10.3キーワードと予約語にあります。このページでは、「(R)」が後に続く単語は予約語です。この問題の原因となる可能性がある多くの予約語を含め、いくつかの予約語を以下に示します。

  • ADD
  • AND
  • BEFORE
  • BY
  • CALL
  • CASE
  • CONDITION
  • DELETE
  • DESC
  • DESCRIBE
  • FROM
  • GROUP
  • IN
  • INDEX
  • INSERT
  • INTERVAL
  • IS
  • KEY
  • LIKE
  • LIMIT
  • LONG
  • MATCH
  • NOT
  • OPTION
  • OR
  • ORDER
  • PARTITION
  • REFERENCES
  • SELECT
  • TABLE
  • TO
  • UPDATE
  • WHERE

解決策

2つの選択肢があります。

1.予約語を識別子として使わない

最も単純な解決策は、単に予約語を識別子として使用しないことです。おそらく、予約語以外の適切なカラム名を見つけることができるでしょう。

これを行うことには、いくつかの利点があります。

  • これにより、あなたやデータベースを使用している他の開発者が、特定の識別子が予約語であることを忘れてしまったり、知らなかったりして、誤って構文エラーを書いてしまう可能性を排除します。MySQLには多くの予約語があり、ほとんどの開発者はそのすべてを知っているとは思えません。そもそもこれらの単語を使用しないことで、自分自身や将来の開発者にトラップを残さないようにすることができます。

  • 識別子を引用する方法は、SQL方言によって異なります。MySQLはデフォルトで識別子の引用にバッククォートを使用しますが、ANSI準拠のSQL(そして実際には、ここで説明するように、ANSI SQLモードのMySQL )は識別子の引用に二重引用符を使用します。そのため、バッククォートで識別子を引用するクエリは、他のSQL方言への移植性が低くなります。

将来の間違いのリスクを減らすためには、通常は識別子を引用するよりも賢明な行動です。

2.バックタックを使用する

テーブルまたは列の名前を変更できない場合は、10.2スキーマオブジェクト名からの以前の引用で説明されているように、問題のある識別子をバッククォート( ` )で囲みます。

使用法を示す例(10.3キーワードと予約語から取得):

mysql> CREATE TABLE interval (begin INT, end INT);
ERROR 1064 (42000): You have an error in your SQL syntax.
near 'interval (begin INT, end INT)'

mysql> CREATE TABLE `interval` (begin INT, end INT);
Query OK, 0 rows affected (0.01 sec)

同様に、質問のクエリは、以下に示すように、キーワード key をバッククォートで囲むことで修正できます。

INSERT INTO user_details (username, location, `key`)
VALUES ('Tim', 'Florida', 42)";               ^   ^