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

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

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

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

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

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

4 ответов


Это функция (хотя и не то, что я ожидал).

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

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

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


единственный способ, которым я могу думать об обработке этого без дополнительных триггеров / программирования, - это иметь одно значение "None of the Above" в каждой из ссылочных таблиц, чтобы ваш тест выглядел как

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

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


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


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

или если вы не согласны с консенсусом рекомендуется может просто не принять никакого ответа.

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