Yuuri
Fleet Admiral
- Registriert
- Okt. 2010
- Beiträge
- 13.928
Hallo zusammen,
bin vorhin auf ein Problem gestoßen und weiß noch nicht so recht, wie ich da rangehen soll.
Gegeben ist eine Baumstruktur, spezieller eine Kategoriestruktur, mit Kategorie ID und Parent ID. Beide IDs referenzieren auf die eigentliche Kategorie. Zusätzlich sind Kategorie und Parent ID mit einem Unique Index versehen, sodass keine Dopplungen auftreten können. Die Parent ID kann allerdings NULL sein, denn die oberste Ebene besitzt ja sozusagen keinen Parent bzw. einen Parent "0".
Hierbei fiel mir auf, dass MySQL NULL-Werte nicht eindeutig definiert. Konkret: Ich kann mehrere Datensätze mit den Werten (5,NULL) erzeugen, wobei ich davon ausgegangen bin, dass (5,NULL) eindeutig ist und hierbei der Unique Index greift, sodass ich beim INSERT ON DUPLICATE KEY UPDATE keine doppelten Datensätze erhalte. Falsch gedacht, denn bei MySQL (und auch im SQL-Standard, so wie ich quer gelesen habe) gilt (NULL != NULL) = (NULL = NULL) = false. Ergo gilt der Unique Constraint nicht, sobald NULL Werte in einer Spalte auftreten, selbst wenn die restlichen Werte übereinstimmen.
Preisfrage hierbei: Wie löse ich den Fall bzw. wie löst man diesen Fall generell, sodass auch die Referenzen gewahrt bleiben? NULL nicht zulassen und stattdessen Dummy Datensätze in Tabellen mit einer 0er ID eintragen? Mit Triggern hantieren wollte ich eigentlich nicht. Lässt sich vielleicht die Tabelle so erstellen, dass NULL eindeutig definiert wird/ist? Was ist hierbei Best Practice?
LG
Zur Veranschaulichung:
bin vorhin auf ein Problem gestoßen und weiß noch nicht so recht, wie ich da rangehen soll.
Gegeben ist eine Baumstruktur, spezieller eine Kategoriestruktur, mit Kategorie ID und Parent ID. Beide IDs referenzieren auf die eigentliche Kategorie. Zusätzlich sind Kategorie und Parent ID mit einem Unique Index versehen, sodass keine Dopplungen auftreten können. Die Parent ID kann allerdings NULL sein, denn die oberste Ebene besitzt ja sozusagen keinen Parent bzw. einen Parent "0".
Hierbei fiel mir auf, dass MySQL NULL-Werte nicht eindeutig definiert. Konkret: Ich kann mehrere Datensätze mit den Werten (5,NULL) erzeugen, wobei ich davon ausgegangen bin, dass (5,NULL) eindeutig ist und hierbei der Unique Index greift, sodass ich beim INSERT ON DUPLICATE KEY UPDATE keine doppelten Datensätze erhalte. Falsch gedacht, denn bei MySQL (und auch im SQL-Standard, so wie ich quer gelesen habe) gilt (NULL != NULL) = (NULL = NULL) = false. Ergo gilt der Unique Constraint nicht, sobald NULL Werte in einer Spalte auftreten, selbst wenn die restlichen Werte übereinstimmen.
Preisfrage hierbei: Wie löse ich den Fall bzw. wie löst man diesen Fall generell, sodass auch die Referenzen gewahrt bleiben? NULL nicht zulassen und stattdessen Dummy Datensätze in Tabellen mit einer 0er ID eintragen? Mit Triggern hantieren wollte ich eigentlich nicht. Lässt sich vielleicht die Tabelle so erstellen, dass NULL eindeutig definiert wird/ist? Was ist hierbei Best Practice?
LG
Zur Veranschaulichung:
Code:
SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE IF EXISTS `categories`;
CREATE TABLE `categories` (
`id` INT(11) PRIMARY KEY AUTO_INCREMENT
) ENGINE = InnoDB DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
DROP TABLE IF EXISTS `cat`;
CREATE TABLE `cat` (
`id` INT(11) PRIMARY KEY AUTO_INCREMENT,
`cat` INT(11) NOT NULL,
`par` INT(11),
UNIQUE KEY `cat_par`(`cat`,`par`),
FOREIGN KEY (`cat`) REFERENCES `categories`(`id`)
ON UPDATE NO ACTION
ON DELETE NO ACTION,
FOREIGN KEY (`par`) REFERENCES `categories`(`id`)
ON UPDATE NO ACTION
ON DELETE NO ACTION
) ENGINE = InnoDB DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_general_ci;
SET FOREIGN_KEY_CHECKS = 1;
INSERT INTO `categories` VALUES (NULL),(NULL),(NULL),(NULL),(NULL);
INSERT INTO `cat` (`cat`,`par`) VALUES (2,1); -- ok
INSERT INTO `cat` (`cat`,`par`) VALUES (3,1); -- ok
INSERT INTO `cat` (`cat`,`par`) VALUES (4,1); -- ok
INSERT INTO `cat` (`cat`,`par`) VALUES (2,1); -- fehler
INSERT INTO `cat` (`cat`,`par`) VALUES (3,1); -- fehler
INSERT INTO `cat` (`cat`,`par`) VALUES (1,NULL); -- ok
INSERT INTO `cat` (`cat`,`par`) VALUES (2,NULL); -- ok
INSERT INTO `cat` (`cat`,`par`) VALUES (1,NULL); -- ok?!
INSERT INTO `cat` (`cat`,`par`) VALUES (2,NULL); -- ok?!