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 pour historisation de données


Sujet :

Développement SQL Server

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Octobre 2002
    Messages
    17
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Octobre 2002
    Messages : 17
    Par défaut Trigger pour historisation de données
    Bonjour

    Afin de pouvoir gérer l'historique de ma base à chaque changement, j'ai pensé que des triggers pouvaient m'aider.
    C'est mon premier contact avec ces bestioles là, et autant dire tout de suite que je suis pas une star en T-SQL

    Pour schématiser, voici le mécanisme que j'aimerais mettre en oeuvre :

    2 tables, une parent et une enfant, qui ont chacune une colonne de données (c'est pour simplifier), et l'horodatage.

    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
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    CREATE TABLE dbo.Parent
    	(
    	idParent uniqueidentifier NOT NULL,
    	ValeurParent int NOT NULL,
    	DateDebut datetime NOT NULL,
    	DateFin datetime NULL
    	)  ON [PRIMARY]
    GO
    ALTER TABLE dbo.Parent ADD CONSTRAINT
    	DF_Parent_DateDebut DEFAULT getdate() FOR DateDebut
    GO
    ALTER TABLE dbo.Parent ADD CONSTRAINT
    	PK_Parent PRIMARY KEY CLUSTERED 
    	(
    	idParent
    	) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
     
    GO
    ALTER TABLE dbo.Parent SET (LOCK_ESCALATION = TABLE)
    GO
    CREATE TABLE dbo.Enfant
    	(
    	idEnfant uniqueidentifier NOT NULL,
    	idParent_FK uniqueidentifier NOT NULL,
    	ValeurEnfant int NOT NULL,
    	DateFin datetime NULL,
    	DateDebut datetime NOT NULL
    	)  ON [PRIMARY]
    GO
    ALTER TABLE dbo.Enfant ADD CONSTRAINT
    	DF_Enfant_DateDebut DEFAULT getdate() FOR DateDebut
    GO
    ALTER TABLE dbo.Enfant ADD CONSTRAINT
    	PK_Enfant PRIMARY KEY CLUSTERED 
    	(
    	idEnfant
    	) WITH( STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
     
    GO
    ALTER TABLE dbo.Enfant ADD CONSTRAINT
    	FK_Enfant_Parent FOREIGN KEY
    	(
    	idParent_FK
    	) REFERENCES dbo.Parent
    	(
    	idParent
    	) ON UPDATE  NO ACTION 
    	 ON DELETE  NO ACTION 
     
    GO
    ALTER TABLE dbo.Enfant ADD CONSTRAINT
    	FK_Enfant_PetitEnfant FOREIGN KEY
    	(
    	idEnfant
    	) REFERENCES dbo.PetitEnfant
    	(
    	idPetitEnfant
    	) ON UPDATE  NO ACTION 
    	 ON DELETE  NO ACTION 
     
    GO
    Lorsque ValeurParent change, voici ce que j'ai voulu implémenter dans mon trigger :
    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
    DECLARE @NewID as uniqueidentifier
    SET @NewID = NewID()
     
    -- On remet les anciennes valeurs dans la ligne mise à jour
    UPDATE Parent
    SET DateFin = GETDATE(),
          ValeurParent = Deleted.ValeurParent
    FROM Parent, Deleted
    WHERE Parent.idParent = Deleted.idParent
     
    -- On crée la ligne avec les valeurs à jour
    INSERT INTO Parent
    (idParent, ValeurParent, DateDebut)
    SELECT
    	@NewID, 
    	Inserted.ValeurParent,
    	GETDATE()
    FROM Inserted
     
    -- Et on pousse la mise à jour vers les enfants 
    UPDATE Enfant
    SET idParent_fk = @NewID
    FROM Enfant, Deleted
    WHERE Enfant.idParent_FK = Deleted.idParent
    AND Enfant.DateEnd IS NULL
    Jusque là, tout va bien.
    Mais du coup, comme le parent a changé, il faut changer les enfants aussi.
    Et donc, un autre Trigger, sur la table enfant cette fois.

    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
    DECLARE @NewID as uniqueidentifier
    SET @NewID = NewID()
     
    -- On remet les anciennes valeurs dans la ligne mise à jour
    UPDATE Enfant
    SET DateFin = GETDATE(),
          ValeurEnfant = Deleted.ValeurEnfant,
          idParent_FK = Deleted.idParent_FK
    FROM Enfant, Deleted
    WHERE Enfant.idEnfant = Deleted.idEnfant
     
    -- On crée la ligne avec les valeurs à jour
    INSERT INTO Enfant
    (idEnfant, idParent_FK, ValeurEnfant, DateDebut)
    SELECT
    	@NewID, 
                 Inserted.idParent_FK,
    	Inserted.ValeurParent,
    	GETDATE()
    FROM Inserted
    Et ca marche très bien... Tant qu'il y a qu'un enfant à modifier !
    J'ai lu qu'il fallait traiter les triggers de manière ensembliste, et ne pas utiliser de variable locale dedans.
    Le problème c'est le NewID() de l'enfant, je ne vois pas comment créer un nouveau GUID pour chaque ligne de la table Enfant qui va être recréée depuis le Trigger.

    Merci pour votre aide

  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
    22 009
    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 : 22 009
    Billets dans le blog
    6
    Par défaut
    Inspirez vous de l'article que j'ai écrit à ce sujet : http://blog.developpez.com/sqlpro/p8...n-des-donnees/

    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/ * * * * *

Discussions similaires

  1. Réponses: 0
    Dernier message: 12/01/2013, 17h35
  2. Trigger Ensembliste de Alter table pour historisation.
    Par obarator dans le forum Développement
    Réponses: 8
    Dernier message: 28/10/2011, 12h35
  3. Trigger pour insérer une donnée
    Par Plopcool dans le forum Débuter
    Réponses: 2
    Dernier message: 14/12/2009, 20h08
  4. trigger pour suppression de données éronnées
    Par maysa dans le forum Langage SQL
    Réponses: 3
    Dernier message: 29/06/2007, 12h13
  5. cherche module ou langage pour récupérer des données audio..
    Par Ry_Yo dans le forum Langages de programmation
    Réponses: 5
    Dernier message: 12/05/2003, 18h44

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