Search code examples
mysqlkeyunique

Can't set unique key to avoid inserting duplicated rows?


I want to avoid inserting duplicated rows, so set UNIQUE KEY with all these fields:

CREATE TABLE `tag` (
    `id` int(8) NOT NULL AUTO_INCREMENT,
    `tag` varchar(256) DEFAULT NULL,
    `version` varchar(20) DEFAULT NULL,
    `custom` tinyint(1) DEFAULT NULL,
    `abstract` tinyint(1) DEFAULT NULL,
    `datatype` varchar(20) DEFAULT NULL,
    `iord` char(1) DEFAULT NULL,
    `crdr` char(1) DEFAULT NULL,
    `tlabel` varchar(512) DEFAULT NULL,
    PRIMARY KEY(`id`),
    UNIQUE KEY(`tag`,`version`,`custom`,`abstract`,`datatype`,`iord`,`crdr`,`tlabel`)
);

It encounter error:

ERROR 1071 (42000): Specified key was too long; max key length is 3072 bytes

Two issues confused me: Issue 1:

 8+256+20+1+1+20+1+1+512 = 820 < 3072

All fields total length is smaller than 3072.

Issue 2:

UNIQUE KEY(`tag`,`version`,`custom`,`abstract`,`datatype`,`iord`,`crdr`,`tlabel`)

It can't work, how to avoid inserting duplicated rows then?


Solution

  • From this GitHub bug post, it seems that perhaps your default database character set is UTF-8, which would require (up to) 4 bytes per character, and therefore would actually exceed the 3027 limit which appears in your current error message. One option would be to create your table with a character set for which one character is just one byte:

    CREATE TABLE tag (
        id int(8) NOT NULL AUTO_INCREMENT,
        tag varchar(256) DEFAULT NULL,
        version varchar(20) DEFAULT NULL,
        custom tinyint(1) DEFAULT NULL,
        abstract tinyint(1) DEFAULT NULL,
        datatype varchar(20) DEFAULT NULL,
        iord char(1) DEFAULT NULL,
        crdr char(1) DEFAULT NULL,
        tlabel varchar(512) DEFAULT NULL,
        PRIMARY KEY(id),
        UNIQUE KEY(tag, version, custom, abstract, datatype, iord, crdr, tlabel)
    ) DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci;
    

    This is the default character set and collation used by MySQL. It should be suitable provided you only intend to store Latin compatible text (and not things like Chinese, which would require UTF-8 support).