1 aus 3 Feldern muss gefüllt werden
Jan K.
- datenbank
0 ms880 Vinzenz Mai0 Tom1 Encoder0 Vinzenz Mai0 dedlfix
MySQL 5.1.41
Hallo Forum,
kommen wir gleich zur Sache:
CREATE TABLE file (
fileid INT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
filename_upload varchar(255) NOT NULL,
filename_system varchar(255) NOT NULL,
extid INT UNSIGNED,
frontuseid INT UNSIGNED,
userid INT UNSIGNED DEFAULT NULL,
betriebid INT UNSIGNED DEFAULT NULL,
unternid INT UNSIGNED DEFAULT NULL,
CHECK ( (userid!=NULL AND betriebid=NULL AND unternid=NULL) OR
(userid=NULL AND betriebid!=NULL AND unternid=NULL) OR
(userid=NULL AND betriebid=NULL AND unternid!=NULL) )
) ENGINE = InnoDB;
INSERT INTO fileid VALUES(DEFAULT,"filename_upload.dat","mussichmirnochueberlegen",1,1,DEFAULT,DEFAULT,DEFAULT);
Ich möchte erreichen, dass ein INSERT oder UPDATE auf die Tabelle file nur unter 3 Bedingungen ausgeführt wird.
Und zwar:
userid=INT betriebid=NULL unternid=NULL
ODER
userid=NULL betriebid=INT unternid=NULL
ODER
userid=NULL betriebid=NULL unternid=INT
Im die obrige Tabelle kann ich aber reinstecken was ich mag :), das check() greift nicht (scheinbar bei MySQL generell nicht nach meinen Recherchen).
Hat jemand von euch eine gescheite Idee wie ich das anstellen kann?
Grüße aus Berlin,
Jan
Entweder du löst es auf programmiertechnischer Seite bevor du Query ausführst oder du schreibst nen Trigger.
http://dev.mysql.com/doc/refman/5.1/de/create-trigger.html
Besten Dank für die Hilfe!
Hallo Forum,
wie Tom vorgeschlagen hat, habe ich die Aufgabe mit einem Trigger gelöst.
Verbesserungsvorschläge sind erwünscht!
DROP TABLE IF EXISTS file;
CREATE TABLE file (
fileid INT UNSIGNED AUTO_INCREMENT PRIMARY KEY NOT NULL,
filename_upload varchar(255) NOT NULL COMMENT 'NTFS max. filename length=255 UTF8 chars',
filename_system varchar(255) NOT NULL COMMENT 'Konflikte mit filenames andere user vermeidenNOW()',
extid INT UNSIGNED,
frontuseid INT UNSIGNED,
userid INT UNSIGNED DEFAULT NULL,
betriebid INT UNSIGNED DEFAULT NULL,
unternid INT UNSIGNED DEFAULT NULL,
FOREIGN KEY (userid) REFERENCES user(userid)
) ENGINE = InnoDB;
DROP TRIGGER IF EXISTS files_insert_nur1PK_aus3PK;
DELIMITER $$
CREATE TRIGGER files_insert_nur1PK_aus3PK BEFORE INSERT ON file
FOR EACH ROW BEGIN
IF (NEW.userid IS NULL AND NEW.betriebid IS NULL AND NEW.unternid IS NULL) OR
(NEW.userid IS NULL AND NEW.betriebid>0 AND NEW.unternid>0) OR
(NEW.userid>0 AND NEW.betriebid IS NULL AND NEW.unternid>0) OR
(NEW.userid>0 AND NEW.betriebid>0 AND NEW.unternid IS NULL) OR
(NEW.userid>0 AND NEW.betriebid>0 AND NEW.unternid>0)
THEN
/* Fehlerbedingung=TRUE -> Fehler provozieren um weitere Abarbeitung zu verhindern */
INSERT INTO Es_darf_nur_1_aus_3_ID_FK_insertet_werden VALUES(NULL);
END IF;
END$$
DELIMITER ;
#Folgendes INSERT muss funktionieren
INSERT INTO file VALUES(DEFAULT,"filenameupload.dat","filenameupload.dat",1,1,DEFAULT,8,DEFAULT);
#Folgendes INSERT muss einen Fehler provozieren
INSERT INTO file VALUES(DEFAULT,"filenameupload.dat","filenameupload.dat",1,1,2,8,9);
Hallo,
MySQL 5.1.41
CREATE TABLE file (
-- [...]
CHECK ( (userid!=NULL AND betriebid=NULL AND unternid=NULL) OR
(userid=NULL AND betriebid!=NULL AND unternid=NULL) OR
(userid=NULL AND betriebid=NULL AND unternid!=NULL) )
) ENGINE = InnoDB;
[...] check() greift nicht (scheinbar bei MySQL generell nicht nach meinen Recherchen).
nicht nur scheinbar. Das Verhalten ist im Handbuch dokumentiert:
<zitat>
The CHECK clause is parsed but ignored by all storage engines.
</zitat>
Das gilt übrigens auch für MySQL 5.5 und 5.6.
Freundliche Grüße
Vinzenz
Hello Jan,
benutze stattdessen eine Stored Routine oder einen Tigger für OnInsert.
Diese kannst Du dann gezielt aussteigen lassen.
Damit Du einen Fehlerwert bekommst, der auswertbar ist, müsstest Du beim Trigger (noch) einen schmutzigen Trick anwenden und im Fehlerfalle eine nicht vorhandene Spalte ansprechen.
Den sauberen Weg mit einer gezielten User-defined Exception kann MySQL mWn immer noch nicht.
Liebe Grüße aus dem schönen Oberharz
Tom vom Berg
Mal davon abgesehen dass der CHECK nicht aktiv wird.
Den Vergleich mit NULL mache ich mit IS NULL, ich weiß nicht was bei = passiert und ob das so richtig funktioniert.
Hallo,
Mal davon abgesehen dass der CHECK nicht aktiv wird.
Den Vergleich mit NULL mache ich mit IS NULL, ich weiß nicht was bei = passiert und ob das so richtig funktioniert.
Nö. Hab' ich übersehen :-(
mysql> SELECT NULL=NULL AS test;
+------+
| test |
+------+
| NULL |
+------+
1 row in set (0.00 sec)
mysql> SELECT NULL!=NULL AS test;
+------+
| test |
+------+
| NULL |
+------+
1 row in set (0.00 sec)
mysql> SELECT ('Test' != NULL) AS test;
+------+
| test |
+------+
| NULL |
+------+
1 row in set (0.00 sec)
Freundliche Grüße
Vinzenz
Tach!
Mal davon abgesehen dass der CHECK nicht aktiv wird.
Den Vergleich mit NULL mache ich mit IS NULL, ich weiß nicht was bei = passiert und ob das so richtig funktioniert.
Wann immer NULL als Operand auftritt ist das Ergebnis NULL. Also auch ein NULL mit NULL verglichen ergibt nicht true sondern NULL, was im booleschen Kontext zu false wird. Lediglich die speziell auf NULL ausgerichteten Operatoren (IS NULL etc.) können NULL "richtig" auswerten.
dedlfix.