MySQL вопрос - уникальный ключ не работает правильно, или я неправильно понимаю? - PullRequest
14 голосов
/ 10 января 2009

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

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

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

Итак, действительные отношения могут включать A - X - I - 1 A - Z - 2 ОТ С С - 3 B - Z - K

Но недействительные отношения будут включать 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, ноль, ноль, ноль) не равно себе, потому что нули включены. Если это так, могу ли я справиться с этим отношением?

Буду признателен за любую помощь!

Ответы [ 4 ]

17 голосов
/ 10 января 2009

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

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

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

УНИКАЛЬНЫЙ индекс гарантирует, что ненулевые значения являются уникальными; вы могли бы указать, что ваш столбец не принимает NULL значения.

3 голосов
/ 10 января 2009

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

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

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

0 голосов
/ 10 января 2009

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

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

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

0 голосов
/ 10 января 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...