Sql Conditionnelle Contrainte Not Null
Je suis curieux de savoir s'il est possible de créer une contrainte conditionnelle et non nulle en sql? En d'autres mots, est-il possible de créer une contrainte telle qu'une colonne B puisse être nulle tant que la colonne A contient des "nouvelles", mais si le contenu de la colonne a change en quelque chose d'autre alors la colonne B n'est plus autorisée à être nulle?
Et pour étendre sur cela, il est alors possible de le faire de sorte que la colonne B doit être nulle ou vide aussi longtemps que la colonne a dit "Nouveau"?
Merci À Tous: D
4 réponses
c'est parfaitement correct pour le contrôle de contrainte. Faites simplement ceci:
exigence:
est-il possible de créer une contrainte telle qu'une colonne B puisse être nulle comme longue colonne A contient permet de dire "nouveau", mais si le contenu de la colonne Un des changements à autre chose ensuite la colonne B n'est plus autorisé à être null?
notez la phrase: colonne B null
Solution:
create table tbl
(
A varchar(10) not null,
B varchar(10),
constraint uk_tbl check
(
A = 'NEW' -- B can be null or not null: no need to add AND here
OR (A <> 'NEW' AND B IS NOT NULL)
)
);
Vous pouvez simplifier encore plus loin:
create table tbl
(
A varchar(10) not null,
B varchar(10),
constraint uk_tbl check
(
A = 'NEW'
OR B IS NOT NULL
)
);
exigence mutuellement incompatible avec l'exigence ci-dessus:
et pour étendre sur cela, il est alors possible de faire en sorte que la colonne B doit-il être nul ou vide tant que la colonne A dit "nouveau"?
notez la phrase: colonne B null
create table tbl
(
A varchar(10) not null,
B varchar(10),
constraint uk_tbl check
(
(A = 'NEW' AND B IS NULL)
OR A <> 'NEW'
)
);
pourrait être simplifié avec ceci, plus simple mais pourrait ne pas être aussi lisible que ci-dessus cependant:
create table tbl
(
A varchar(10) not null,
B varchar(10),
constraint uk_tbl check
(
A <> 'NEW'
OR B IS NULL
)
);
je pense que votre premier stipule:
IF ( B IS NULL ) THEN ( A = 'NEW' )
Appliquer l'implication de la règle de réécriture:
IF ( X ) THEN ( Y ) <=> ( NOT ( X ) OR ( Y ) )
dans votre cas;
( NOT ( B IS NULL ) OR ( A = 'NEW' ) )
réécriture mineure pour profiter de la syntaxe SQL:
( B IS NOT NULL OR A = 'NEW' )
votre deuxième exigence énoncée ("étendre"):
IF ( A = 'NEW' ) THEN ( B IS NULL )
Appliquer la règle de réécriture:
( NOT ( A = 'NEW' ) OR ( B IS NULL ) )
Mineur de réécriture:
( A <> 'NEW' OR B IS NULL )
Edit: comme mentionné dans les autres réponses, une vérification est la meilleure méthode, pas le déclencheur que j'ai suggéré à l'origine. Texte Original suit:
comme le suggère dbaseman,déclencheurs sont la voie à suivre (pas si). Essayez quelque chose comme ceci (non testé):
CREATE OR REPLACE TRIGGER test
BEFORE UPDATE ON table1
FOR EACH ROW
WHEN (new.A = 'NEW' and new.B IS NOT NULL)
RAISE_APPLICATION_ERROR (
num=> -20001,
msg=> 'B must be NULL for new rows (A = NEW)'
);
Par onedaywhen, cette réponse est criminellement fausse, et une abomination. Vous pouvez utiliser un CHECK contrainte. http://msdn.microsoft.com/en-us/library/ms188258.aspx
il n'y a pas moyen de faire des contraintes conditionnelles. Vous devriez cependant être capable de faire le travail à l'aide d'un déclencheur. C'est ce qu'ils sont pour.
http://msdn.microsoft.com/en-us/library/ms189799.aspx
CREATE TRIGGER MyTable.ConditionalNullConstraint ON MyTable.ColumnB
AFTER INSERT
AS
IF EXISTS (SELECT *
FROM inserted
WHERE A <> 'NEW' AND B IS NULL
)
BEGIN
RAISERROR ('if A is ''NEW'' then B cannot be NULL', 16, 1);
ROLLBACK TRANSACTION;
END;
GO
notez que dans la requête vous voudrez faire référence à inséré qui est un objet spécial qui se comporte comme un tableau, et vous permet de référencer les ligne(s) qui a provoqué le déclenchement.
bien sûr, dans cet exemple, vous auriez besoin pour gérer APRÈS LA MISE À JOUR aussi, pour faire respecter la contrainte, mais c'est l'idée générale.