IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Développement SQL Server Discussion :

Trigger : Before insert


Sujet :

Développement SQL Server

  1. #1
    Nouveau membre du Club
    Développeur informatique
    Inscrit en
    Mai 2007
    Messages
    38
    Détails du profil
    Informations personnelles :
    Âge : 44

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2007
    Messages : 38
    Points : 37
    Points
    37
    Par défaut Trigger : Before insert
    Hello tout le monde.

    J'ai une table de ce genre qui me permet de gérer l'historique de prêt d'un objet (dans mon cas un PC) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    PC_ID	| DAT_DEB			| DAT_FIN
    --------------------------------------------------------
    1	| 2001-01-04 00:00:00.000	| NULL
    2	| 2001-01-05 00:00:00.000	| NULL
    3	| 2001-01-06 00:00:00.000	| 2002-01-06 00:00:00.000
    5	| 2001-01-01 00:00:00.000	| NULL
    6	| 2001-01-02 00:00:00.000	| NULL
    7	| 2001-01-03 00:00:00.000	| NULL
    J'ai l'identifiant de l'objet avec une date de début de prêt et une date de fin, s'il y a lieu.

    J'aimerais créer un trigger qui vérifierait qu'à l'insertion d'une ligne la date de début à insérer ne soit pas antérieure à la dernière date de fin de l'objet concerné.

    Pour l'instant j'ai ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    CREATE TRIGGER TRG_PC_HISTO
    	   ON PC_HISTO
    	   FOR INSERT
    AS
    BEGIN
    	DECLARE
    		@errno    INTEGER,
    		@errmsg   VARCHAR(255),
    		@dt1 datetime,
    		@dt2 datetime
     
    	SET @errno  = 0
     
    	/* L'historique doit être cohérent. */
    	set @dt1 = (SELECT MAX(dat_fin) FROM pc_histo WHERE PC_ID IN (SELECT PC_ID FROM INSERTED))
    	set @dt2 = (SELECT DAT_DEB FROM INSERTED)
    	IF @dt1 > @dt2
    	BEGIN
    		SET @errno  = 666004
    		SET @errmsg = 'Erreur sur les dates, historique non-cohérent. MAX(dat_fin) (' + cast(@dt1 as varchar(50)) + ') DAT_DEB(' + CAST(@dt2 as varchar(50)) + ')'
    	END
     
    	/*  Gestion d'erreurs  */
    	IF (@errno <> 0)
    	BEGIN 
    		RAISERROR @errno @errmsg
    		ROLLBACK TRANSACTION
    	END
     
    	RETURN
    END
    J'exécute la requête suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    insert into pc_histo (pc_id, dat_deb, dat_fin) values (3, CAST('06/01/2002' as datetime), CAST('07/01/2003' as datetime))
    Et j'obtiens l'erreur suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Msg 666004, Niveau 16, État 1, Procédure TRG_PC_USR, Ligne 63
    Erreur sur les dates, historique non-cohérent. MAX(dat_fin) (janv  7 2003 12:00AM) DAT_DEB(janv  6 2002 12:00AM)
    J'en conclut que l'insertion a lieu avant l'éxécution du trigger, puisque ma date de fin maximum est celle de ma requête d'insertion qui n'apparaît pas dans la table au début.

    Quelqu'un a-t-il une solution pour que je puisse tester les valeurs de ma table avant que l'insertion ne soit faite ?

  2. #2
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 772
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 772
    Points : 52 737
    Points
    52 737
    Billets dans le blog
    5
    Par défaut
    Inutile de prévoir un trigger. Supprimez l'une des dates et passez par une vue.

    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  3. #3
    Nouveau membre du Club
    Développeur informatique
    Inscrit en
    Mai 2007
    Messages
    38
    Détails du profil
    Informations personnelles :
    Âge : 44

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2007
    Messages : 38
    Points : 37
    Points
    37
    Par défaut
    C'est possible d'avoir un peu plus de précisions ? Parce qu'en l'état j'ai rien compris. En fait je ne comprends pas ce que tu veux dire par effacer une date, en quoi une vue me serait utile ici ou comment me passer d'un trigger.

  4. #4
    Expert confirmé
    Avatar de rudib
    Homme Profil pro
    Fakir SQL Server & NoSQL
    Inscrit en
    Mai 2006
    Messages
    2 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Fakir SQL Server & NoSQL

    Informations forums :
    Inscription : Mai 2006
    Messages : 2 573
    Points : 4 043
    Points
    4 043
    Par défaut
    Bonjour,

    J'ai fais ceci rapidement en guise d'exemple. A tester :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    CREATE TRIGGER TRG_PC_HISTO
    	   ON PC_HISTO
    	   FOR INSERT
    AS
    BEGIN
    	SET NOCOUNT ON
    	IF @@ROWCOUNT = 0 RETURN
     
    	IF EXISTS (
    		SELECT * 
    		FROM INSERTED i
    		JOIN dbo.pc_histo h ON i.PC_ID = h.PC_ID AND i.DAT_DEB <> h.DAT_DEB 
    		WHERE ISNULL(h.dat_fin, DATEADD(day, 1, getdate()) > i.DAT_DEB
    	) BEGIN
    		RAISERROR 'Erreur sur les dates', 666004, 10
    		ROLLBACK TRANSACTION
    	END
     
    END
    Rudi Bruchez
    Rudi Bruchez EIRL, solutions MS SQL Server et NoSQL
    LinkedIn - [Outil libre de diagnostic SQL Server : Sql Trismegiste]
    LIVRES : Optimiser SQL Server -
    Microsoft SQL Server 2012 Security Cookbook
    - les bases de données NoSQL

    e-learning : LinkedIn Learning - Pluralsight

  5. #5
    Nouveau membre du Club
    Développeur informatique
    Inscrit en
    Mai 2007
    Messages
    38
    Détails du profil
    Informations personnelles :
    Âge : 44

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2007
    Messages : 38
    Points : 37
    Points
    37
    Par défaut
    Il manque une parenthèse fermante avant le "> i.DAT_DEB", mais sinon je viens de tester et ça marche.

    Me reste plus qu'à comprendre comment, mais avant c'est l'heure de manger !

    Donc bravo, merci et bon app.

  6. #6
    Membre éprouvé
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Août 2006
    Messages
    730
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2006
    Messages : 730
    Points : 923
    Points
    923
    Par défaut
    rudib:

    quel est l'intérêt de
    IF @@ROWCOUNT = 0 RETURN
    car pour moi si @@ROWCOUNT = 0 c'est qu'il n'y a pas d'insertion

    c'est une ruse de sioux ?
    Errare humanum est, perseverare diabolicum (Sénèque)

  7. #7
    Expert confirmé
    Avatar de rudib
    Homme Profil pro
    Fakir SQL Server & NoSQL
    Inscrit en
    Mai 2006
    Messages
    2 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Fakir SQL Server & NoSQL

    Informations forums :
    Inscription : Mai 2006
    Messages : 2 573
    Points : 4 043
    Points
    4 043
    Par défaut
    Hello,

    Malheureusement pas aussi simple.
    Si tu fais qqch comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    INSERT INTO matable (...)
    SELECT ... FROM uneautretable WHERE 1 = 2
    Il n'y aura pas d'insertion réelle, puisque le résultat du SELECT ne retourne aucune ligne. Par contre le trigger se déclenchera tout de même. Inutile donc de lui faire exécuter le reste de son code, en pure perte.
    Rudi Bruchez
    Rudi Bruchez EIRL, solutions MS SQL Server et NoSQL
    LinkedIn - [Outil libre de diagnostic SQL Server : Sql Trismegiste]
    LIVRES : Optimiser SQL Server -
    Microsoft SQL Server 2012 Security Cookbook
    - les bases de données NoSQL

    e-learning : LinkedIn Learning - Pluralsight

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. TRIGGER before insert
    Par sara07 dans le forum SQL Procédural
    Réponses: 1
    Dernier message: 23/08/2008, 01h50
  2. [10g] Trigger before insert
    Par Lung dans le forum Oracle
    Réponses: 6
    Dernier message: 21/12/2007, 16h22
  3. Trigger Before Insert et Before Update
    Par NicoNours dans le forum SQL Procédural
    Réponses: 4
    Dernier message: 14/08/2007, 10h20
  4. Trigger Before Insert
    Par Fred_ET dans le forum Administration
    Réponses: 7
    Dernier message: 22/11/2006, 00h29
  5. Créer un trigger "before insert" avec SQL Server
    Par bubi dans le forum Développement
    Réponses: 2
    Dernier message: 14/11/2005, 10h12

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo