MySQL で後からユニークインデックスを追加するには
フィールドを Unique にする方法
mysql> alter table 対象テーブル add unique (対象フィールド);
作業ログ(フィールドサイズが 999 バイトを超えていたら)
今回 support テーブルの uri フィールドをユニーク化しようとしたが、
mysql> alter table support add unique (uri); ERROR 1071 (42000): Specified key was too long; max key length is 999 bytes
となってしまった。定義を調べると、
mysql> show fields from support; +---------+---------------+------+-----+-------------------+----------------+ | Field | Type | Null | Key | Default | Extra | +---------+---------------+------+-----+-------------------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | uri | varchar(512) | NO | MUL | | | | title | varchar(1024) | NO | MUL | | | | content | mediumtext | YES | | NULL | | | updated | timestamp | NO | | CURRENT_TIMESTAMP | | +---------+---------------+------+-----+-------------------+----------------+
512だが、UTF-8なので超えてしまっているのだろう。
実際には数文字しか入っていないので別のフィールド uri2 を作って、そこに値をコピーしてからユニーク化して、元の列を削除してリネームすることにした。
127なら4倍しても999バイトには届かないので、varchar(127) で定義する。
mysql> alter table support add column uri2 varchar(127); Query OK, 20799 rows affected (1 min 0.37 sec) Records: 20799 Duplicates: 0 Warnings: 0
uri フィールドから uri2 フィールドに値をコピーする。
mysql> update support set uri2 = uri; Query OK, 20799 rows affected (6 min 30.64 sec) Rows matched: 20799 Changed: 20799 Warnings: 0
uri フィールドを削除する。
mysql> alter table support drop uri; Query OK, 20799 rows affected (1 min 0.60 sec) Records: 20799 Duplicates: 0 Warnings: 0
uri2 フィールドをユニークにする。
mysql> alter table support add unique (uri2); Query OK, 20799 rows affected (1 min 1.66 sec) Records: 20799 Duplicates: 0 Warnings: 0
uri2 から uri フィールド名を変更する(id フィールドの後ろに移す)。
mysql> alter table support change column `uri2` `uri` varchar(127) after id; Query OK, 20799 rows affected (1 min 0.41 sec) Records: 20799 Duplicates: 0 Warnings: 0 mysql> show fields from support; +---------+---------------+------+-----+-------------------+----------------+ | Field | Type | Null | Key | Default | Extra | +---------+---------------+------+-----+-------------------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | uri | varchar(127) | YES | UNI | NULL | | | title | varchar(1024) | NO | MUL | | | | content | mediumtext | YES | | NULL | | | updated | timestamp | NO | | CURRENT_TIMESTAMP | | +---------+---------------+------+-----+-------------------+----------------+ 5 rows in set (0.00 sec)
実は列名を変更するときに定義も変更できる(というか指定する)ことに気づいた。
ということで本当は、
mysql> alter table support change column `uri` `uri` varchar(127); mysql> alter table support add unique (uri);
だけでいけたかもしれない。