Question

J'essaie d'écrire un déclencheur sur une table pour éviter l'insertion de deux noms qui ne sont pas marqués comme IsDeleted. Mais la première partie de la sélection contient celle qui a été insérée et la condition est donc toujours vraie. Je pensais qu'en utilisant le mot-clé FOR, le déclencheur s'exécutait avant l'INSERTION, mais dans ce cas, la ligne insérée est déjà dans la table. Est-ce que je me trompe ou que c'est ainsi que fonctionnent tous les déclencheurs POUR?

ALTER TRIGGER TriggerName
ON MyTable
FOR INSERT, UPDATE
AS
BEGIN 
    If exist (select [Name] From MyTable WHERE IsDeleted = 0 AND [Name] in (SELECT [Name] FROM INSERTED)
    BEGIN
    RAISERROR ('ERROR Description', 16, 1);
    Rollback;
    END  
END
Était-ce utile?

La solution

FOR s'exécute après la modification des données. INSTEAD OF est ce que je pense que vous recherchez.

EDIT: comme d'autres l'ont indiqué, INSTEAD OF est exécuté à la place des données que vous modifiez. Vous devez donc insérer les données si elles sont valides, plutôt que d'arrêter l'insertion si elles sont invalides.

Lisez cette question pour une explication beaucoup plus détaillée des types de déclencheurs.

SQL Server " AFTER INSERT " le déclencheur ne voit pas la ligne qui vient d'être insérée

Autres conseils

FOR est identique à APRÈS. si vous voulez "simuler" AVANT le déclenchement, utilisez INSTEAD OF, caveat, ce n’est pas exactement ce que vous attendez du bon déclencheur, c’est-à-dire que si vous ne fournissez pas l’action INSTEAD nécessaire, vos données insérées / mises à jour pourraient être perdues / ignorées.

MSSQL n’a pas de déclencheur AVANT.

Pour SQL Server, FOR s'exécute APRÈS le SQL qui l'a déclenché.

De: http://msdn.microsoft.com/en-us/library/ms189799. aspx

  

POUR | APRÈS

     

APRES indique que le déclencheur DML   est renvoyé uniquement lorsque toutes les opérations   spécifié dans le SQL de déclenchement   déclaration ont été exécutés avec succès.   Toutes les actions en cascade référentielles et   les contrôles de contrainte doivent également réussir   avant que ce déclencheur ne se déclenche.

     

APRES est la valeur par défaut lorsque FOR est le   seul mot clé spécifié.

     

APRES des déclencheurs   ne peut pas être défini dans les vues.

En fait, j’ai rencontré un problème similaire récemment et j’ai trouvé un moyen intéressant de le gérer. J'avais une table qui pouvait avoir plusieurs lignes pour un même identifiant, mais une seule d'entre elles pouvait être marquée comme primaire.

Dans SQL Server 2008, vous pourrez créer un index unique partiel, comme suit:

create unique index IX on MyTable(name) where isDeleted = 0;

Cependant, vous pouvez accomplir cela avec un peu plus de travail dans SQL Server 2005. L'astuce consiste à créer une vue affichant uniquement les lignes non supprimées, puis à créer un index en cluster unique:

 create view MyTableNotDeleted_vw
 with schema_binding /* Must be schema bound to create an indexed view */
 as
 select name 
 from dbo.MyTable /* Have to use dbo. for schema bound views */
 where isDeleted = 0;

 GO

 create unique clustered index IX on MyTableNotDeleted_vw ( name );

Ceci créera effectivement une contrainte unique affectant uniquement les lignes qui n'ont pas encore été supprimées et fonctionnera probablement mieux qu'un déclencheur personnalisé!

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top