HHeLiBeXの日記 正道編

日々の記憶の記録とメモ‥

識別子の大文字と小文字の違い(2)

あの頃(何時)はまだMySQLに関する知識がなかった‥

で、MySQLでは、列名などの識別子はバッククォートで括るらしい(ということを、「show create table hoge」を実行して気づいたらしい)。
ということで、以前に実施した検証のMySQL版。
今回、以下のバージョンで検証。

MySQL版では、テーブル定義は次のようになる(ダブルクォートをバッククォートに置き換えて、BINARYオプションをつけただけ)。

-- 大文字・小文字、バッククォートで括る・括らない
CREATE TABLE hoge(
    id VARCHAR(8) BINARY,
    val1 INT,
    VAL2 INT,
    `val3` INT,
    `VAL4` INT
) ;
-- 試行する列名指定のパターン
INSERT INTO hoge(id) VALUES ('val1') ;
INSERT INTO hoge(id) VALUES ('val2') ;
INSERT INTO hoge(id) VALUES ('val3') ;
INSERT INTO hoge(id) VALUES ('val4') ;
INSERT INTO hoge(id) VALUES ('VAL1') ;
INSERT INTO hoge(id) VALUES ('VAL2') ;
INSERT INTO hoge(id) VALUES ('VAL3') ;
INSERT INTO hoge(id) VALUES ('VAL4') ;
INSERT INTO hoge(id) VALUES ('`val1`') ;
INSERT INTO hoge(id) VALUES ('`val2`') ;
INSERT INTO hoge(id) VALUES ('`val3`') ;
INSERT INTO hoge(id) VALUES ('`val4`') ;
INSERT INTO hoge(id) VALUES ('`VAL1`') ;
INSERT INTO hoge(id) VALUES ('`VAL2`') ;
INSERT INTO hoge(id) VALUES ('`VAL3`') ;
INSERT INTO hoge(id) VALUES ('`VAL4`') ;

で、試行(こちらも、ダブルクォートをバッククォートに置き換えて、BINARYオプションをつけたもの。さらに「my_log」という名前にした。MySQL 4.1で「CREATE TABLE log‥」がエラーになったための措置(「CREATE TABLE `log`‥」は通るので、何かのキーワードなのだろうな(保留(謎))))。

-- 試行結果の記録。
-- 指定した列が存在したら、テーブル my_log に列名指定のパターンが記録される。
CREATE TABLE my_log(id VARCHAR(8) BINARY, val INT) ;
INSERT INTO my_log(id, val) SELECT id, val1   FROM hoge WHERE id = 'val1' ;
INSERT INTO my_log(id, val) SELECT id, VAL1   FROM hoge WHERE id = 'VAL1' ;
INSERT INTO my_log(id, val) SELECT id, `val1` FROM hoge WHERE id = '`val1`' ;
INSERT INTO my_log(id, val) SELECT id, `VAL1` FROM hoge WHERE id = '`VAL1`' ;
INSERT INTO my_log(id, val) SELECT id, val2   FROM hoge WHERE id = 'val2' ;
INSERT INTO my_log(id, val) SELECT id, VAL2   FROM hoge WHERE id = 'VAL2' ;
INSERT INTO my_log(id, val) SELECT id, `val2` FROM hoge WHERE id = '`val2`' ;
INSERT INTO my_log(id, val) SELECT id, `VAL2` FROM hoge WHERE id = '`VAL2`' ;
INSERT INTO my_log(id, val) SELECT id, val3   FROM hoge WHERE id = 'val3' ;
INSERT INTO my_log(id, val) SELECT id, VAL3   FROM hoge WHERE id = 'VAL3' ;
INSERT INTO my_log(id, val) SELECT id, `val3` FROM hoge WHERE id = '`val3`' ;
INSERT INTO my_log(id, val) SELECT id, `VAL3` FROM hoge WHERE id = '`VAL3`' ;
INSERT INTO my_log(id, val) SELECT id, val4   FROM hoge WHERE id = 'val4' ;
INSERT INTO my_log(id, val) SELECT id, VAL4   FROM hoge WHERE id = 'VAL4' ;
INSERT INTO my_log(id, val) SELECT id, `val4` FROM hoge WHERE id = '`val4`' ;
INSERT INTO my_log(id, val) SELECT id, `VAL4` FROM hoge WHERE id = '`VAL4`' ;

-- テーブル my_log にあれば'O'、なければ'X'
SELECT hoge.id, 'O' AS result
    FROM hoge
    WHERE hoge.id IN (SELECT id FROM my_log)
UNION
SELECT hoge.id, 'X' AS result
    FROM hoge
    WHERE hoge.id NOT IN (SELECT id FROM my_log)
;

で、実行結果なのだが、全部'O'だけど一応ちゃんと表にしておく。

対象列 列名指定 MySQL 4.1 MySQL 5.5
val1 val1 O O
val2 O O
val3 O O
val4 O O
VAL2 VAL1 O O
VAL2 O O
VAL3 O O
VAL4 O O
`val3` `val1` O O
`val2` O O
`val3` O O
`val4` O O
`VAL4` `VAL1` O O
`VAL2` O O
`VAL3` O O
`VAL4` O O

さて、「show create table hoge」をしてみると、以下のような結果が返ってくる。(2者の違いは、単にデフォルトの文字エンコーディングが'utf8'か'utf8mb4'かだけ)

CREATE TABLE `hoge` (
  `id` varchar(8) character set utf8 collate utf8_bin default NULL,
  `val1` int(11) default NULL,
  `VAL2` int(11) default NULL,
  `val3` int(11) default NULL,
  `VAL4` int(11) default NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
CREATE TABLE `hoge` (
  `id` varchar(8) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL,
  `val1` int(11) DEFAULT NULL,
  `VAL2` int(11) DEFAULT NULL,
  `val3` int(11) DEFAULT NULL,
  `VAL4` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

また、MySQL 5.xでは、情報スキーマから列名一覧を取得できる。

SELECT TABLE_NAME, COLUMN_NAME
    FROM INFORMATION_SCHEMA.COLUMNS
    WHERE TABLE_NAME = 'hoge' ;

結果はこんな感じ。

TABLE_NAME COLUMN_NAME
1 hoge id
2 hoge val1
3 hoge VAL2
4 hoge val3
5 hoge VAL4

と、以前検証したとおりの結果。(情報スキーマ-列名の取得 - HHeLiBeXの日記 正道編)
そこで、「show create table INFORMATION_SCHEMA.COLUMNS」してみる。

CREATE TEMPORARY TABLE `COLUMNS` (
  `TABLE_CATALOG` varchar(512) NOT NULL DEFAULT '',
  `TABLE_SCHEMA` varchar(64) NOT NULL DEFAULT '',
  `TABLE_NAME` varchar(64) NOT NULL DEFAULT '',
  `COLUMN_NAME` varchar(64) NOT NULL DEFAULT '',
      :
  (以下略)

COLUMN_NAME列などにBINARYオプションがついていないということは、やはり大文字小文字の区別をつけることは、MySQLではできそうにない。(実際、「CREATE TABLE foo(`val1` INT, `VAL1` INT)」するとエラーになる)
まぁ、大文字小文字だけが違う列が定義できても混乱の元になるだけなんだけど。