J'ai une question liée aux déclencheurs de base de données dans T-SQL. P>
Je veux créer un déclencheur qui permet uniquement des mots spécifiques (disponibles, non disponibles) à une colonne Comment cela pourrait être fait? P>
Je comprends ce que la gâchette est, mais perdue dans la séquence de commandes - que devraient venir après quoi. P> Avalability code>. P>
4 Réponses :
Je ne sais pas qu'un déclencheur est vraiment nécessaire ici. Une autre solution serait de créer une contrainte code> cocher code> sur la colonne concernée, comme: Démo sur DB Fiddle Strong>: P> CREATE TABLE TableName (availability VARCHAR(20) );
ALTER TABLE TableName
ADD CONSTRAINT availability_check CHECK (availability IN ('available', 'not available'));
INSERT INTO TableName(availability) VALUES('foo');
-- Error
Msg 547 Level 16 State 0 Line 1
The INSERT statement conflicted with the CHECK constraint "availability_check". The conflict occurred in database "fiddle_325b8b256056466caf52aa4bb7467fd7", table "dbo.TableName", column 'availability'.
Msg 3621 Level 0 State 0 Line 1
The statement has been terminated.
Il y a deux approches du problème.
CREATE TRIGGER [dbo].[tr_availability_update] ON [dbo].[Table1] INSTEAD OF UPDATE AS BEGIN BEGIN TRY BEGIN TRANSACTION SET NOCOUNT ON; IF (inserted.Availability IN ('available', 'not available')) BEGIN UPDATE Table1 SET Availability = inserted.Availability WHERE Table1.Id = inserted.Id; END COMMIT; END TRY BEGIN CATCH IF @@TRANCOUNT > 0 ROLLBACK RETURN; END CATCH
Il est possible de faire avec un déclencheur, mais: 1. Vous devrez écrire du code similaire pour le moment où un utilisateur tente de mettre à jour la colonne. 2. Vous devrez fournir des instructions d'insertion / mise à jour pour toutes les colonnes de la table dans vos déclencheurs. Ce n'est pas un problème terrible, mais c'est quelque chose qui facilite la maintenance de la base de données plus difficile.
@Zoharpeled, d'accord avec vous. Je viens de fournir le code afin qu'il puisse comprendre la quantité de travail impliquée. J'ai également mentionné que, à nouveau, il doit écrire au lieu de la mise à jour de la gâchette. Je recommande moi-même que vous ne recommandez que le contrainte.
@Zoharpeled, j'ai mis à jour ma réponse pour clarifier la quantité d'effort nécessaire
si (inséré.Vailabilité dans ("disponible", "non disponible") code> a des parenthèses déséquilibrées et ce n'est pas clair comment il vérifie toutes les lignes dans
insérées code>.
Mise à jour de la table1 (disponibilité) Définir la disponibilité = inséré.Vailability code> est également un peu mystérieux quant à la manière dont il sélectionne les données à partir de
insérées code>, mais au moins il met à jour toutes les lignes i> dans le tableau car il n'y a pas de
où code> clause.
@Habo, merci d'avoir attrapé le problème. corrigé-les. Je voulais juste mentionner la complexité de l'effort. OP n'a pas fourni de schéma de table et tout. Vient de mentionner l'effort.
Vous pouvez Notez que cela lancera une erreur s'il y a Certaines données déjà insérées dans la table et ne correspondent pas et contrairement à la contrainte Si vous ne code> Créez-vous encore votre table, Ensuite, vous pouvez utiliser P> alter code> votre table et ajouter une contrainte de coche code> directement sous
Vérifiez code>. p>
CREATE TABLE YourTableName(
Availability VARCHAR(20) NOT NULL
CONSTRAINT CHK_Avalability CHECK(Availability IN('Available', 'Not Available'))
);
Une contrainte de contrôle est la façon dont j'irais. Une autre approche consiste à utiliser des contraintes référentielles, alias les clés primaire et étrangère. Si "disponible" et "non disponible" sont utilisés dans plusieurs endroits, cela sera meilleur qu'une contrainte de contrôle, car vous pouvez appliquer les mêmes règles sur plusieurs tables. De cette façon, vous pouvez appliquer la cohérence et éviter d'avoir des tables avec les autres valeurs telles que "disponibles" et "indisponible".
-- Lookup table for all possible "Availability" values CREATE TABLE dbo.LU_Availability ( AvailabilityPK VARCHAR(14) NOT NULL, CONSTRAINT pk_LU_Availability PRIMARY KEY CLUSTERED(AvailabilityPK) ); INSERT dbo.LU_Availability (AvailabilityPK) VALUES ('Available'),('Not Available'); -- Table with the allowable values enforced via foriegn key constraint CREATE TABLE dbo.YourTable ( someId INT IDENTITY, someValue CHAR(10), [Availability] VARCHAR(14) NOT NULL, CONSTRAINT fk_AvailabilityTxt FOREIGN KEY([Availability]) REFERENCES dbo.LU_Availability(AvailabilityPK) ); INSERT dbo.YourTable ([Availability]) VALUES ('Available'); -- Succeeds INSERT dbo.YourTable ([Availability]) VALUES ('NOT Available'); -- Succeeds INSERT dbo.YourTable ([Availability]) VALUES ('Perhaps'); -- Fails
Dupliqué possible de SQL Server - avant insérer le déclencheur
Vous ne savez pas que vous avez vraiment besoin d'une gâchette, pourquoi ne pas créer une contrainte code> cocher code> sur la colonne concernée?
Vous avez besoin d'un
avant d'insérer code> déclencheur. Il y a beaucoup d'exemples via Google. Ou ce que @gmb suggère.
Cela sonne définitivement comme si vous décrivez
Vérifier la contrainte code> pas un
déclencheur code>.
Un déclencheur est absolument le mauvais outil de ce travail. Utilisez une contrainte de chèque.