読者です 読者をやめる 読者になる 読者になる

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);

だけでいけたかもしれない。