Принудительно использовать уникальные строки в MySQL

У меня есть таблица в MySQL с 3 полями, и я хочу обеспечить уникальность двух полей. Вот таблица DDL:

CREATE TABLE `CLIENT_NAMES` (
`ID` int(11) NOT NULL auto_increment,
`CLIENT_NAME` varchar(500) NOT NULL,
`OWNER_ID` int(11) NOT NULL,
PRIMARY KEY  (`ID`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Поле ID является суррогатным ключом (эта таблица загружается с помощью ETL). CLIENT_NAME — это поле, содержащее имена клиентов. OWNER_ID — это идентификатор, указывающий на владельца клиента.

Я думал, что смогу применить это с помощью уникального индекса для CLIENT_NAME и OWNER_ID,

ALTER TABLE `DW`.`CLIENT_NAMES` 
ADD UNIQUE INDEX enforce_unique_idx(`CLIENT_NAME`, `OWNER_ID`);

но MySQL дает мне ошибку:

Ошибка выполнения команд SQL для обновления таблицы. Указанный ключ слишком длинный; максимальная длина ключа 765 байт (ошибка 1071)

У кого-то еще есть идеи?


person Mike Farmer    schedule 18.09.2008    source источник


Ответы (4)


MySQL не может обеспечить уникальность ключей длиннее 765 байт (и, по-видимому, 500 символов UTF8 могут превысить этот предел).

  1. Действительно ли CLIENT_NAME должен иметь длину 500 символов? Кажется немного чрезмерным.
  2. Добавьте новый (более короткий) столбец с хэшем (CLIENT_NAME). Вместо этого заставьте MySQL обеспечить уникальность этого хэша.
person Gili    schedule 18.09.2008
comment
Юникод — это кодировка переменной длины. Символы могут иметь размер от одного до четырех байтов, и только исходные 128 символов ASCII кодируются одним байтом. - person Joe Mahoney; 18.09.2008

Вы смотрели на ОГРАНИЧЕНИЕ ... УНИКАЛЬНОСТЬ?

person J D OConal    schedule 18.09.2008

Что-то кажется немного странным в этой таблице; Я бы на самом деле подумал о рефакторинге. На что ссылаются ID и OWNER_ID и какова связь между ними?

Имеет ли смысл иметь

CREATE TABLE `CLIENTS` (
`ID` int(11) NOT NULL auto_increment,
`CLIENT_NAME` varchar(500) NOT NULL,
# other client fields - address, phone, whatever
PRIMARY KEY  (`ID`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE `CLIENTS_OWNERS` (
`CLIENT_ID` int(11) NOT NULL,
`OWNER_ID` int(11) NOT NULL,
PRIMARY KEY  (`CLIENT_ID`,`OWNER_ID`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Я бы действительно не стал добавлять такой уникальный ключ в строку из 500 символов. Гораздо эффективнее обеспечить уникальность двух целых чисел, плюс идентификатор в таблице должен действительно ссылаться на то, что нуждается в идентификаторе; в вашей версии поле ID, по-видимому, идентифицирует только отношения клиент/владелец, которым действительно не нужен отдельный идентификатор, поскольку это просто сопоставление.

person Aeon    schedule 18.09.2008

Здесь. Для набора символов UTF8 MySQL может использовать до 3 байтов на символ. CLIENT_NAME составляет 3 x 500 = 1500 байт. Сократите CLIENT_NAME до 250.

позже: +1 к созданию хэша имени и использованию его в качестве ключа.

person Terry G Lorber    schedule 18.09.2008
comment
Говорить, что UTF-8 использует 3 байта/символ, неверно. Как указано на странице, она может принимать ДО этого значения, и что делает невозможным ее использование в MySQL, так это пессимистический подход. - person André Chalella; 18.09.2008