MySQL: <Problem nicht kompakt zusammenfassbar>
Peter Thomassen
- datenbank
Hallo Forum,
ich habe eine Tabelle folgenden Aufbaus:
id | replaces_id | created | ...
----+-------------+------------+- - -
1 | NULL | 2005-03-04 |
2 | NULL | 2003-08-22 |
3 | 2 | 2006-05-05 |
4 | 2 | 2006-05-05 |
5 | 2 | 2006-06-06 | <unzulässig!>
Ich möchte auf Datenbankebene (InnoDB) erreichen, dass die Einträge 1..4 erlaubt sind, 5 aber nicht, also dass:
- replaces_id IS NULL beliege Werte für created zulässt,
- replaces_id IS NOT NULL nur einen einzigen Wert für created zulässt.
Any ideas?
Danke!
Peter
Hallo nochmal,
id | replaces_id | created | ...
----+-------------+------------+- - -
1 | NULL | 2005-03-04 |
2 | NULL | 2003-08-22 |
3 | 2 | 2006-05-05 |
4 | 2 | 2006-05-05 |
5 | 2 | 2006-06-06 | <unzulässig!>[...]
- replaces_id IS NOT NULL nur einen einzigen Wert für created zulässt.
Das war unpräzise. Erweiterung der Tabelle:
id | replaces_id | created | ...
----+-------------+------------+- - -
1 | NULL | 2005-03-04 |
2 | NULL | 2003-08-22 |
3 | 2 | 2006-05-05 |
4 | 2 | 2006-05-05 |
5 | 2 | 2006-06-06 | <unzulässig!>
6 | 3 | 2006-06-06 |
replaces_id soll also created bedingen, aber mehrere Werte von replaces_id sollen schon je einen anderen Wert von created zulassen.
Danke,
Peter
Hallo Peter,
id | replaces_id | created | ...
----+-------------+------------+- - -
1 | NULL | 2005-03-04 |
2 | NULL | 2003-08-22 |
3 | 2 | 2006-05-05 |
4 | 2 | 2006-05-05 |
5 | 2 | 2006-06-06 | <unzulässig!>
6 | 3 | 2006-06-06 |replaces_id soll also created bedingen, aber mehrere Werte von replaces_id sollen schon je einen anderen Wert von created zulassen.
Deine Tabellenstruktur scheint mir ungünstig gewählt, dies bedingt Dein Problem. Du solltest vielleicht genauer erläutern, welche Bedeutung die Spalte created hat, mir entzieht sich diese. Wenn replaces_id nicht NULL ist, so hängt created direkt von replaces_id ab, deswegen solltest Du dies in einer eigenen Tabelle aufführen.
Mein Vorschlag wären zwei Tabellen:
id replaces_id created
---------------------------
1 NULL 2005-03-04
2 NULL 2003-08-22
3 2 NULL
4 2 NULL
5 2 NULL
6 3 NULL
replaces_id created
-----------------------
2 2006-05-05
3 2006-06-06
SELECT
id
t1.replaces_id
COALESCE(t1.created, t2.created) AS created
FROM Tabelle1 t1
LEFT JOIN Tabelle2 t2
ON t1.replaces_id = t2.replaces_id
liefert Dir Deine Ausgangstabelle mit korrektem created-Wert für id=5.
Wenn Du MySQL 5.0 und höher verwendest, so kannst Du aus meiner Abfrage einen View erstellen, der genau das Aussehen Deiner Ausgangstabelle hat.
Da Du InnoDB verwendest, kannst Du mit einem FOREIGN KEY-Constraint Deine Bedingung durchsetzen, die CHECK-Klausel wird von MySQL derzeit noch komplett ignoriert ...
Freundliche Grüße
Vinzenz
Tag!
id | replaces_id | created | ...
----+-------------+------------+- - -
1 | NULL | 2005-03-04 |
2 | NULL | 2003-08-22 |
3 | 2 | 2006-05-05 |
4 | 2 | 2006-05-05 |
5 | 2 | 2006-06-06 | <unzulässig!>
6 | 3 | 2006-06-06 |replaces_id soll also created bedingen, aber mehrere Werte von replaces_id sollen schon je einen anderen Wert von created zulassen.
Deine Tabellenstruktur scheint mir ungünstig gewählt, dies bedingt Dein Problem. Du solltest vielleicht genauer erläutern, welche Bedeutung die Spalte created hat, mir entzieht sich diese. Wenn replaces_id nicht NULL ist, so hängt created direkt von replaces_id ab, deswegen solltest Du dies in einer eigenen Tabelle aufführen.
Es handelt sich um eine Vetragstabelle; für die Vetragsdatensätze ist replaces_id standardmäßig NULL. created ist das Vertragsabschlussdatum. Gibt es jetzt aber beispielsweise eine Preisänderung oder einen Tarifwechsel, der bedingt, dass nach der Änderung die Mindestvertragslaufzeit noch des alten Vertrages gilt, so wird im neuen Vetrag mit replaces_id angegeben, welcher Vertrag ersetzt wurde (um dessen Mindestvertragslaufzeit verwenden zu können). Es kann auch sein, dass ein Vertrag durch mehrere andere ersetzt wird, für diesen Fall können die Ersatzverträge aber nur zum selben Zeitpunkt, daher muss created für einen gegebenen Wert von replaces_id konstant sein.
Mein Vorschlag wären zwei Tabellen:
[...]
SELECT
id
t1.replaces_id
COALESCE(t1.created, t2.created) AS created
FROM Tabelle1 t1
LEFT JOIN Tabelle2 t2
ON t1.replaces_id = t2.replaces_id
>
> liefert Dir Deine Ausgangstabelle mit korrektem created-Wert für id=5.
Das ist süß. :-) COALESCE() kannte ich nicht, macht aber auch für andere Gelegenheiten einen praktischen Eindruck. Was mich an deinem Tabellendesign aber stört, ist, dass created nun auf zwei Tabellen verteilt ist. Um es komplett auszulagern, müsste man für replaces\_id IS NULL noch die Vertrags-ID in der zweiten Tabellen referenzieren, dann hätte man da wieder zwei Spalten, die wechselweise NULL sind ... irgendwie nicht schön.
> Wenn Du MySQL 5.0 und höher verwendest, so kannst Du aus meiner Abfrage einen View erstellen, der genau das Aussehen Deiner Ausgangstabelle hat.
Ich verwende zwar MySQL 5.0, habe bisher aber keine Views gebraucht und mich deswegen nicht damit beschäftigt. Wo ich sie jetzt mal brauchen könnte, hab ich natürlich nicht mehr dran gedacht ;-) Danke, ich schau's mir mal an.
> Da Du InnoDB verwendest, kannst Du mit einem [FOREIGN KEY-Constraint](http://dev.mysql.com/doc/refman/5.0/en/innodb-foreign-key-constraints.html) Deine Bedingung durchsetzen, die [CHECK-Klausel](http://dev.mysql.com/doc/refman/5.0/en/create-table.html) wird von MySQL derzeit noch komplett ignoriert ...
Foreign-Key-Contraints verwende ich ausführlich für die Standardzwecke, aber wie soll man denn eine eigene Bedingung durchsetzen, wenn ja die CHECK-Klausel gerade ignoriert wird? \*verwirrt\*
Danke für deine Hilfe,
Peter
yo,
Um es komplett auszulagern, müsste man für replaces_id IS NULL noch die Vertrags-ID in der zweiten Tabellen referenzieren, dann hätte man da wieder zwei Spalten, die wechselweise NULL sind ... irgendwie nicht schön.
ich habe den beitrag nur überflogen, aber es scheint sich um eine n:m beziehung zu handel, also zwei entitätstabellen verbunden durch eine beziehungstabelle.
Ilja