今日はなにの日。

気になったこと勉強になったことのメモ。

今日は、MySQLでオブジェクト名にハイフンはエラーになるの日。

目次

とある日

たまたま、会社でMySQLにつながらないという人を見つけ、色々と調べるとユーザ名が不適切だったことが原因らしいが、不適切だった理由について調べた内容です。

色々と調べるとユーザ名とデータベース名では細かい違いがあるので、この記事ではデータベース名などのスキーマオブジェクト名の注意点について記述します。

スキーマオブジェクト名の注意点

スキーマオブジェクト名とは?

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

MySQL :: MySQL8.0リファレンスマニュアル:: 9.2スキーマオブジェクト名

CREATE文で作られるものを基本的にオブジェクトと認識して問題ないです。

注意点:許可されない識別子

MySQLでは、オブジェクトの識別子で使える文字には制限があります。

例えば、データベース名に"-"を使うとエラーになります。

mysql> create database hyphen-test;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-test' at line 1

解決策

解決策は簡単で、引用符で囲むだけです。

mysql> create database `hyphen-test`;
Query OK, 1 row affected (0.01 sec)

識別子の引用符はバッククォート(`)です。

ここまでは、Googleで「MySQL ハイフン エラー」とかで調べると出てきます。

ですが、なぜだめなのかについて書かれていなかったので気になって調べたので下記に記述します。

ハイフンがなぜエラーなるのか

結論としてはMySQLではハイフンはいわゆる特殊文字扱いだからです。

MySQLの識別子に使える文字は大きく分けると2つあります。

  • 引用符で囲まれていない識別子で許可される文字
  • 引用符で囲まれた識別子で許可される文字

例外はあります。

ASCII NUL(U + 0000)および補足文字(U + 10000以降)は、引用符で囲まれた識別子または引用符で囲まれていない識別子では使用できません。

MySQL ::MySQL8.0リファレンスマニュアル::9.2スキーマオブジェクト名

引用符で囲まれていない識別子で許可される文字

基本的に何も考えることなく使える文字列たちです。

  • ASCII:[0-9、az、AZ $ _](基本ラテン文字、数字0-9、ドル、アンダースコア)
  • 拡張:U + 0080 .. U + FFFF ..
mysql> create database hyphen;
Query OK, 1 row affected (0.01 sec)

アルファベットが引用符で囲わなくても使えるのは引用符で囲まれていなくても許可されている文字だからです。

引用符で囲まれた識別子で許可される文字

こっちに該当するものは、いわゆる特殊文字予約語が含まれます。

U +0000を除く完全なUnicodeBasic Multilingual Plane(BMP)が含まれます。

  • ASCII:U + 0001 .. U + 007F
  • 拡張:U + 0080 .. U + FFFF ..
mysql> create database hyphen-test;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-test' at line 1

ハイフンはこっちに属します。

そのため引用符で囲う必要があります。

他にも、予約語を使用している場合も同様です。

(予約語MySQLで特別な振る舞いをする単語)

mysql> create database select;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'select' at line 1
mysql> create database `select`;
Query OK, 1 row affected (0.00 sec)

予約語の一覧については下記をご覧ください。

MySQL :: MySQL 8.0 Reference Manual :: 9.3 Keywords and Reserved Words

予約語問題だとMySQL8.0でRANKが追加されて問題になってましたね)

RANK (R); 追加されたバージョン: 8.0.2 (reserved)

なぜ許可されていない文字列なのか

SQL標準で規定されているから。(おそらく)

データベースやテーブル、列といった名前に使える文字は、以下に限られます。

  • 半角のアルファベット
  • 半角の数字
  • アンダーバー(_)

標準SQLとは | 標準SQL徹底入門

どの文字が特殊文字に該当するかは、RDBMSで異なるみたいなのでお気をつけください。

どうするのが適切なのか

SQL標準に従って命名する。

基本的にアンダーバーを使用することです。

CREATE TABLE parents (
  parent_id int(10)  primary key AUTO_INCREMENT,
  parent_idx_col int(10)  NOT NULL
);

根本的なユーザについての話は調べるとユーザはまた別で扱いが異なるらしいのでそれは別の記事にします。

奥が深そうです。

他にも、識別子は文字コードによっても異なるそうです。

文字コードは闇が深いので今回はここまでとします。

よくよく考えると、ずっと当たり前にアンダーバーを使っていたので、なぜハイフンがだめなのか忘れてたので記録用として作成しました。

参考資料

MySQL ::MySQL8.0リファレンスマニュアル::9.2スキーマオブジェクト名

MySQL :: MySQL 5.6 リファレンスマニュアル :: 9.1.1 文字列リテラル

データベース名にハイフン(-)入れたらSQL文でエラーになった 【特殊文字】 - Qiita