Вопрос MySQL — уникальный ключ работает неправильно, или я неправильно понимаю?

StackOverflow https://stackoverflow.com/questions/429805

Вопрос

Я пытаюсь создать отношение, в которое может быть включена любая из четырех разных частей, но любая коллекция одинаковых частей должна обрабатываться как уникальная.

Пример:Задание должно иметь назначенную компанию, а также (при необходимости) может иметь назначенное местоположение, рабочую группу и программу.В задании не может быть рабочей группы без местоположения.

Предположим, у нас есть компании A, B, C;локации X, Y, Z;рабочие группы I, J, K и программы 1, 2, 3.

Таким образом, действительные отношения могут включать A - X - I - 1 А - Я - 2 B - Y C С - 3 В - Я - К

Но недействительные отношения будут включать A - K (Рабочая группа без места нахождения) Y - K - 1 (без компании)

Итак, чтобы создать свою таблицу, я создал

companyID INT NOT NULL,
FOREIGN KEY companyKEY (companyID) REFERENCES company (companyID),
locationID INT,
FOREIGN KEY locationKEY (locationID) REFERENCES location (locationID),
workgroupID INT,
FOREIGN KEY workgroupKEY (workgroupID) REFERENCES workgroup (workgroupID),
programID INT,
FOREIGN KEY programKEY (programID) REFERENCES program (programID),
UNIQUE KEY companyLocationWorkgroupProgramKEY (companyID, locationID, workgroupID, programID)

Я полагаю, что это будет обрабатывать все мои отношения, кроме необходимости задания иметь местоположение, если есть рабочая группа (что, я думаю, я с радостью могу сделать программно или с помощью триггеров)

Однако когда я тестирую эту схему, она позволяет мне ввести следующее...

INSERT INTO test VALUES (1, null, null, null), (1, null, null, null);

...без жалоб.Я предполагаю, что (1, null, null, null) не равно самому себе, потому что включены нули.Если это так, могу ли я как-нибудь справиться с этим отношением?

Любая помощь будет оценена по достоинству!

Это было полезно?

Решение

Это особенность (хотя и не то, чего я ожидал).

Эта тема предлагает сделать ваш ключ первичным ключом, чтобы добиться ожидаемого поведения:

Это функция - значение NULL является неопределенное значение, поэтому два NULL значения не одинаковы.Может быть немного запутанно, но имеет смысл, когда ты думаешь об этом.

Индекс UNIQUE гарантирует, что значения non-NULL уникальны;вы могли бы укажите, что ваш столбец не принимает NULL-значения.

Другие советы

Единственный способ справиться с этим без дополнительных триггеров/программирования - это иметь одно значение «Ничего из вышеперечисленного» в каждой из ссылочных таблиц, чтобы ваш тест выглядел так:

INSERT INTO test VALUES (1, NO_LOCATION, NO_WORKGROUP, NO_PROGRAM),
                        (1, NO_LOCATION, NO_WORKGROUP, NO_PROGRAM)

Где NO_* идентификаторы — это правильный тип/длина для ваших столбцов идентификаторов.Тогда это потерпит неудачу, как и следовало ожидать.

В MySQL NULL != NULL или что-то еще.Так вот что UNIQUE не работает.Вам следует использовать другое значение по умолчанию для пробелов, например ноль.

Я думаю, важно отметить, что существует правильный способ интерпретации и обработки значений NULL, и поведение, демонстрируемое OP, является именно тем, что задумано.Вы можете игнорировать такое поведение и обрабатывать свой запрос так, как захотите, без моих возражений, но, возможно, было бы полезно «Принять» ответ, который описывает некоторую форму передового опыта, а не нестандартное личное предпочтение.

Или, если вы не согласны с общепринятой лучшей практикой, вы можете просто не принимать ни одного ответа.

Это не гонка за получением ответа как можно быстрее.Я думаю, что обсуждение и сотрудничество также должны стать частью этого процесса.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top