Ist es möglich zu begrenzen, welche Werte in einer Spalte basierend auf anderen Werten in der Zeile zulässig sind?
Zum Beispiel meine Tabelle:
ID Test_mode Active
-- --------- ------
1 1 Null
2 0 1
3 1 0
Gibt es eine Möglichkeit, den Wert von Test_mode
in zu ändern , 0
wenn a 1
in eingefügt wird?Active
ODER
Wenn Test_mode
1 nicht das Einfügen / Aktualisieren von erlaubt istActive
ODER
Wirf einen Fehler aus, wenn Test_mode
1 ist und ein Einfügen / Aktualisieren von Active
versucht wird.
Active
kann nur NULL, 1, 0 UND nur 1 mit Test_mode
als 0 sein.
Ich hoffe, das macht Sinn, wenn nicht, lass es mich wissen und ich werde die Frage aktualisieren.
sql-server
sql-server-2008-r2
constraint
Erzengel33
quelle
quelle
Antworten:
Zunächst einmal Willkommen bei dba.stackexchange.com und vielen Dank für Ihren Beitrag!
Ist es möglich zu begrenzen, welche Werte in einer Spalte basierend auf anderen Werten in der Zeile zulässig sind?
Ja, mit CHECK CONSTRAINTS wie hier beschrieben
Beispiel:
Wenn
Test_mode
1 nicht das Einfügen / Aktualisieren von Active --OR-- zulässt, wird ein Fehler ausgegeben, wenn Test_mode 1 ist und versucht wird, Active einzufügen / zu aktualisieren.Verwenden Sie TRY / CATCH wie hier beschrieben
quelle
Update myTable Set Active = 1
undtest_mode
auch aktualisiert werden. Wenn dies jedoch der einzige Weg ist, dann soll es so sein! Vielen Dank :)Active int [...] CHECK (active IS NULL OR active IN (1, 0))
- Dies scheint ein sinnlos schlechtes Design zu sein, da es bedeutet: "Bitte emulieren Sie einen Booleschenbit
Wert, aber speichern Sie ihn in einem weniger effizienten Typ. Ich muss mich daran erinnern, dass ich seine zulässigen Werte manuell einschränken muss."Die erste Verteidigungslinie, die verhindert, dass ungültige Daten in Ihre Tabellen gelangen, sind die Datentypen der Spalten.
Wenn ein Prozess versucht, eine Spalte auf einen Wert einzufügen oder zu aktualisieren, der außerhalb des Bereichs des Datentyps liegt (oder
NULL
wenn die SpalteNULL
s nicht zulässt ), schlägt der Vorgang sofort fehl, ohne dass Sie zusätzliche Arbeit leisten müssen.Die Auswahl des Datentyps ist einer der wichtigsten Aspekte des Tabellendesigns.
Da Sie kein Schema veröffentlicht haben, werde ich eines basierend auf den von Ihnen angegebenen Informationen erstellen:
Basierend auf diesem Design sind die verfügbaren Kombinationen bereits auf Folgendes beschränkt:
Alles andere führt dazu, dass ein Fehler ausgelöst wird. (Was gut ist.)
Sie haben 4 verschiedene Möglichkeiten angegeben, um zu der zulässigen Wertekombination zu gelangen ( na ja , irgendwie). Dies sind sehr unterschiedliche Strategien mit sehr unterschiedlichen Implementierungsverhalten.
Ich bevorzuge die Verwendung von sogenannten deklarativen Einschränkungen. Mit anderen Worten, das Tabellenschema und die zugehörigen Objekte begrenzen die zulässigen Werte, indem explizit angegeben wird , was zulässig ist (oder manchmal, was nicht zulässig ist). Tatsächlich sind die Spaltendatentypen selbst eine Art deklarative Einschränkung. Je näher die Werte an den Tabellendaten liegen, desto einfacher und zuverlässiger können sie eingeschränkt werden. (Im Gegensatz dazu würde eine nicht deklarative oder aktive Einschränkung implementiert, indem ein Teil von T-SQL geschrieben wird, normalerweise entweder ein Tabellenauslöser oder ein Teil einer gespeicherten Prozedur.)
Die ersten drei Optionen können nur mit nicht deklarativen Mitteln implementiert werden. Der letzte ist jedoch deklarativ, also konzentrieren wir uns darauf:
Dies definiert, was Sie tatsächlich wollen, dh die zulässigen Wertekombinationen in der Tabelle. Beachten Sie, dass die gültigen Kombinationen nur von Spaltenwerten in derselben Zeile abhängen . Dies ist wichtig, da hiermit festgelegt wird, mit welchen Mechanismen die Einschränkung implementiert werden kann.
In diesem Fall können wir eine
CHECK
Einschränkung verwenden , bei der es sich um einen True / False-Test handelt, der anhand der Spaltenwerte 1 einer Zeile feststellt, ob eine Zeile gültig oder ungültig ist . Wenn der Test fehlschlägt, schlägt der Vorgang, bei dem versucht wurde, die Zeile zu ändern, mit einem Fehler fehl.Sie werden feststellen, dass ich das Prädikat so konstruiert habe, dass es auch dann weiter funktioniert, wenn
Test_mode
es sich tatsächlich um einen (nicht nullbaren) Ganzzahltyp handelt. DasIS NOT NULL
Teil ist erforderlich, daCHECK
Einschränkungen Zeilen zulassen, in denen das Prädikat ausgewertet wirdundefined
.1 Sie können verwendet werden, um außerhalb der aktuellen Zeile zu prüfen, aber dies ist eine schlechte Praxis, und darauf werde ich hier nicht näher eingehen. Verwenden Sie stattdessen einen Auslöser.
quelle
Check Constraint
scheint die am besten geeignete Lösung zu sein. Werden Einschränkungen nach einer Update-Anweisung überprüft? Was ich meine ist, wird einUPDATE
LikeUPDATE [dbo].[Tests] SET Active=1,test_mode=0 WHERE test_mode=1
eine Einschränkung nicht bestehen oder wird der Status der Zeile erst nachUPDATE
Abschluss überprüft . Ich werde einige Tests durchführen, um sicherzugehen, aber ich habe das Gefühl, dass dies funktionieren wird.UPDATE
Ihnen erwähnte Aussage wird erfolgreich sein, da der Endzustand zulässig ist. Wenn Sie diese Statusänderung nicht zulassen möchten, müssen Sie dazu einen Trigger verwenden. (Ihre anfänglichen Anforderungen waren etwas unklar.) Hinweis: Ich würde empfehlen, sowohl eine Prüfbedingung als auch einen Auslöser zu verwenden, wenn dies Ihre Anforderungen sind.UPDATE
das funktionieren wird. Ich dachte, dass es beim Übergang vom aktuellen in den gewünschten Zustand zu einem ungültigen Zustand kommen könnte.quelle
Status
alles andere alsA
oder istD
, dannColumn
müsste es nicht eindeutig sein.