2010-12-08 3 views
1

Ich versuche, eine Einschränkung (in Oracle) hinzuzufügen, die den Benutzer daran hindert, einen Eintrag zu erstellen, der 'smth', 'etw sonst' oder 'noch eine Sache' in einem Feld bereits existiert. Grundsätzlich würde ich es so schreiben:Verschachtelte Abfragen in der Überprüfung SQL-Anweisung

ALTER TABLE sometable 
ADD CONSTRAINT sometable_text_chk 
CHECK (
    caption IN ( 
     SELECT caption 
     FROM sometable 
     WHERE text NOT IN ('smth', 'smth else', 'one more thing') 
    ) 
) 

Leider scheint es nicht erlaubt zu sein, Abfragen für diesen Anlass zu schachteln. Gibt es vielleicht einen Workaround?

+0

Das ist nicht so klar - was ist die Beziehung zwischen den Feldern 'text' und' caption'? Was meinst du damit, wenn du sagst, dass der Benutzer keine Einträge erstellen darf?in einem Feld bereits vorhanden? (Sprechen Sie darüber, dass Sie im Feld 'caption' eindeutige Werte haben wollen) – Unreason

Antwort

2

Grundsätzlich versuchen Sie eine Art generelle Kontrolle der Daten in einer Tabelle zu haben, basierend auf den Daten in einer anderen Tabelle (ACHTUNG: eigentlich wahrscheinlich nicht, warten auf die Klärung der Frage durch das OP).

Umgehung entweder:

  • für den allgemeinen Fall - Sie tun können, eine ganze Menge im Inneren löst im Hinblick auf die komplexen Datenvalidierung (einschließlich Ihrer Datenbank zum Erliegen selbst für die einfachsten Aktualisierungsabfragen zu bringen, so verwenden mit Vorsicht)
  • für einen etwas spezifischeren Fall, Sie versuchen, einige dynamische Validierung zu erreichen (ein repräsentativer Beispiel wäre nützlich gewesen) - Sie können die CHECK-Einschränkung dynamisch mit einem 'Snapshot' Ihrer Validierung (das kocht bis auf eine Kopie der referenzierten Tabelle in der Check-Anweisung zu halten, so ist es ziemlich hässlich)
  • vielleicht können Sie einen Fremdschlüssel überprüfen. Normalerweise entwerfen Sie Datenbanken nicht, aber wenn Sie es semantisch betrachten, behaupten Sie (mit Ihrer CHECK), dass es eine Beziehung zwischen dieser Tabelle und einer anderen Entität gibt. Nun, wenn diese Entität nicht als separate Tabelle realisiert wurde, hätte es vielleicht auch sein sollen? (Diese Art von Problemen sind manchmal Indikatoren für schlechtes Design)
0

Sie können nicht so CHECK-Einschränkung hinzufügen, müssen Sie buchstäblich ganze Liste der möglichen Werte liefern:

CHECK (caption IN (Word1, Word2, Word3 ...)) 

auch immer Sie in anderen Art und Weise tun können:

CHECK (Caption <> 'smth' and caption <> 'smth else' and caption <> 'one more thing') 

Aber Sie verloren Kontrollen aus irgendwie.

1
ALTER TABLE sometable 
ADD CONSTRAINT sometable_text_chk 
CHECK (text not in ('smth', 'smth else', 'one more thing')) 
/

Grüße, Rob.

+0

Das dachte ich zuerst, aber die Anforderung ist etwas komplexer ... Sie müssen den Wert in einer Nachschlagetabelle finden, nicht in der Schlüssel selbst –

+0

Aber Alex erwähnt zweimal "etwas". Und ohne ein spezifiziertes Schema kann das nur dieselbe Tabelle sein. Vielleicht hast du recht, aber dann bin ich beeindruckt, wie du zwischen den Zeilen lesen kannst :-). –

0

Ich gebe zu, das zu viel des Guten kann. Wenn Sie ein schnell aktualisierbare erstellen, aktualisieren-on-commit materialisierte Ansicht mit einer Definition, die die Anzahl der schlechten Werte in der Tabelle zählen würde, (vielleicht so etwas wie unten):

select count(*) as rows_with_errors 
    from data_table a 
    join lookup_table b on(a.caption = b.caption); 

Die Abfrage sollte eine Rück count of zero, weil Werte in data_table NICHT die Werte in der lookup_table enthalten dürfen. Dann erstellen Sie eine Prüfbedingung für die materialisierte Ansicht selbst, CHECK (rows_with_errors = 0).

Immer wenn ein Update oder eine Einfügung in data_table festgeschrieben wird, wird die materialisierte Ansicht aktualisiert. Aber (und hier ist die Sache), wenn Sie einen Wert in data_table in Lookup_table eingegeben haben, gibt der count (*) einen Wert ungleich null zurück, der dazu führt, dass die Checkbeschränkung für die materialisierte Ansicht fehlschlägt, also die gesamte Insert/Update-Anweisung wird fehlschlagen/Rollback. Voila!

Verwandte Themen