MySQLのsql_modeにあるORACLEとは
これはJPOUG Advent Calendar 2016の16日目の記事です。
最初に言っておきますが、この記事はなんも役に立ちません!
では始めます。
MySQLのsql_modeにはいろいろとsqlの動作の設定ができるんですが、
ここにORACLE
というのが選択できます。
たぶんOracle databaseっぽく動作するんでしょうけど、設定したらどうなるか確認しました。
MySQLのバージョンは5.6.34です。
設定
mysql > select @@sql_mode; +------------------------+ | @@sql_mode | +------------------------+ | NO_ENGINE_SUBSTITUTION | +------------------------+ 1 row in set (0.00 sec) mysql> set global sql_mode=ORACLE; Query OK, 0 rows affected (0.00 sec)
sql_modeのデフォルトはNO_ENGINE_SUBSTITUTION
で
set globalでORACLEを設定します。で、sql_modeを確認すると、
mysql > select @@sql_mode; +----------------------------------------------------------------------------------------------------------------------+ | @@sql_mode | +----------------------------------------------------------------------------------------------------------------------+ | PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ORACLE,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER | +----------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.00 sec)
いっぱい表示されました。
MySQL :: MySQL 5.6 リファレンスマニュアル :: 5.1.7 サーバー SQL モード
マニュアルを見ると、いろんなsql_modeの組み合わせてOracle databaseの動作っぽくしてるみたいです。
他にもMSSQL
やPOSTGRESQL
など選択できるようです。
動作の確認
sql_modeに追加された各モードの動作を確認してみます。
PIPES_AS_CONCAT
これは||
を文字列結合に変更されます。従来ではORのシノニムです。
- sql_mode:デフォルト
mysql> select 0 || 1 ; +--------+ | 0 || 1 | +--------+ | 1 | +--------+ 1 row in set (0.00 sec)
mysql> select 0 || 1 ; +--------+ | 0 || 1 | +--------+ | 01 | +--------+ 1 row in set (0.00 sec)
これはOracleっぽくなりますね。ちなみにMySQLはSELECT文にFROM DUAL
つけなくでも実行できます。
ANSI_QUOTES
二重引用符を使用してリテラル文字列を引用できなくなります。
- sql_mode:デフォルト
mysql> select "aaa" ; +-----+ | aaa | +-----+ | aaa | +-----+ 1 row in set (0.00 sec)
mysql> select "aaa" ; ERROR 1054 (42S22): Unknown column 'aaa' in 'field list'
IGNORE_SPACE
関数名と 「(」 文字の間にスペースを許可します。
- sql_mode:デフォルト
mysql> select count (*) from ENGINES; 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 '*) from ENGINES' at line 1
mysql> select count (*) from ENGINES; +-----------+ | count (*) | +-----------+ | 9 | +-----------+ 1 row in set (0.00 sec)
ORACLE
NO_KEY_OPTIONS
SHOW CREATE TABLE の出力で MySQL 固有のインデックスオプションを出力しません。このモードはポータビリティモードで mysqldump によって使用されます。
NO_TABLE_OPTIONS
SHOW CREATE TABLE の出力で MySQL 固有のテーブルオプション (ENGINE など) を出力しません。このモードはポータビリティモードで mysqldump によって使用されます。
NO_FIELD_OPTIONS
SHOW CREATE TABLE の出力に MySQL 固有のカラムオプションを出力しません。このモードはポータビリティモードで mysqldump によって使用されます。
この3つはまとめて紹介します。 以下のようなテーブルを作成します。
CREATE TABLE t1( id int primary key auto_increment, id2 varchar(10) character set 'utf8' collate 'utf8_bin' , id3 int, key id2_hash(id2) using hash, key id3_withcomment(id3) comment 'test' );
SHOW CREATE TABLE
で出力の違いを確認します。
- sql_mode:デフォルト
mysql> show create table t1\G *************************** 1. row *************************** Table: t1 Create Table: CREATE TABLE `t1` ( `id` int(11) NOT NULL AUTO_INCREMENT, `id2` varchar(10) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, `id3` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `id2_hash` (`id2`) USING HASH, KEY `id3_withcomment` (`id3`) COMMENT 'test' ) ENGINE=InnoDB DEFAULT CHARSET=latin1 1 row in set (0.00 sec)
mysql> show create table t1\G *************************** 1. row *************************** Table: t1 Create Table: CREATE TABLE `t1` ( `id` int(11) NOT NULL, `id2` varchar(10) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL, `id3` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `id2_hash` (`id2`), KEY `id3_withcomment` (`id3`) ) 1 row in set (0.00 sec)
NO_KEY_OPTIONS
でキー(セカンダリインデックス)に付属する情報の隠す。(USING HASHやCOMMENT 'test'のところ)
NO_TABLE_OPTIONS
でMySQL特有のテーブル構文を隠す。(ENGINE=InnoDB DEFAULT CHARSET=latin1のところ)
NO_FIELD_OPTIONS
でMySQL特有のカラム構文を隠す。(AUTO_INCREMENTのところ)
CHARACTER SET utf8 COLLATE utf8_bin
これも特有じゃないのかなと思いつつも。
NO_AUTO_CREATE_USER
認証情報が指定される場合を除き、ほかの方法で実行される場合は、GRANT ステートメントで新規ユーザーを自動的に作成しません。ステートメントは IDENTIFIED BY を使用した空以外のパスワードを指定するか、IDENTIFIED WITH を使用した認証プラグインを指定する必要があります。
これはMySQL5.7からsql_modeのデフォルト値に含まれていて、
OFFであればGrant文でユーザが作成されますが、ONであるとユーザを先に作成していないエラーになります。
- sql_mode:デフォルト
mysql> GRANT SELECT ON *.* TO 'test'@'192.168.1.1'; Query OK, 0 rows affected (0.00 sec)
mysql> GRANT SELECT ON *.* TO 'test'@'192.168.1.1'; ERROR 1133 (42000): Can't find any matching row in the user table
結論はMySQLを使用するならsql_modeをORACLE
にする理由はどこにもないです。
特にSHOW CREATE TABLE
で大事な情報が隠れちゃうのはつらい。
明日は@discus_hamburgさんです!
確か去年も@discus_hamburgさんの前だった気がする。