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 :

Pb : requete avec nom de champ variable renvoie le nom du champ


Sujet :

Développement SQL Server

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 3
    Points : 2
    Points
    2
    Par défaut Pb : requete avec nom de champ variable renvoie le nom du champ
    Bonjour,

    Je souhaite réaliser un trigger qui lors d'un modification d'une table archive les données des champs sous forme d'une chaine de caractères XML.
    Pour ce faire j'utilise un curseur qui liste les champs de ma table, puis pour chaque champ je fait une requete me renvoyant la valeur du champ grace à l'instruction :
    SELECT @value = @champ FROM DELETED;
    Le problème est que la variable @value contient le nom du champ et non pas ça valeur.

    Pourriez vous m'aider à résoudre ce problème?
    Merci d'avance

    Le trigger est :
    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
     
    ALTER TRIGGER [dbo].[tr_ArchiveDataOnUpdate]
    ON [dbo].[Individual_Obj]
    AFTER UPDATE
    AS 
    BEGIN
        SET NOCOUNT ON;
        DECLARE @id int, @xml nvarchar(MAX), @sqlval nvarchar(500), @Str_Para nvarchar(500);
        select @id = inserted.Individual_Obj_Pk from inserted
     
        DECLARE @champ nvarchar(250), @value nvarchar(250), @sql nvarchar(1000);
        DECLARE i CURSOR FOR SELECT syscolumns.name FROM sysobjects , syscolumns WHERE ( sysobjects.id = syscolumns.id) And (sysobjects.xtype = 'U') AND sysobjects.name = 'Individual_Obj';
     
        SET @xml = '<Object>'+ CHAR(13);
        SET @xml = @xml+ '<pk>'+CAST(@id AS nvarchar(250))+'</pk>'+ CHAR(13);
        SET @xml = @xml+ '<attibutes>'+ CHAR(13);
        OPEN i
        FETCH i INTO @champ
            WHILE @@FETCH_STATUS = 0
            BEGIN
                SET @xml = @xml+ '<attibute>';
                SET @xml = @xml+ '<name>'+@champ+'</name>';
                SELECT @value = @champ FROM DELETED; 
                IF NOT @value IS NULL
                BEGIN
                    SET @xml = @xml + '<value>'+@value+'</value>';
                END        
                SET @xml = @xml+ '</attibute>'+ CHAR(13) ;
            FETCH i INTO @champ
            END
        CLOSE i
        DEALLOCATE i     
        SET @xml = @xml+ '</attibutes>'+ CHAR(13);
    SET @xml = @xml+ '</Object>'+ CHAR(13);
        print (@xml);
        SELECT * from DELETED;
        INSERT INTO dbo.LogObjects (object_type,fk_object, update_date, obj_archive ) VALUES ('Individual', @id , CURRENT_TIMESTAMP, @xml);
     
    END
    Lorsque je faire un update la variable @xml correspond à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    <Object>
    <pk>90</pk>
    <attibutes>
    <attibute><name>Individual_Obj_Pk</name><value>Individual_Obj_Pk</value></attibute>
    <attibute><name>creation_date</name><value>creation_date</value></attibute>
    <attibute><name>end_date</name><value>end_date</value></attibute>
    <attibute><name>available</name><value>available</value></attibute>
    <attibute><name>TCaracThes_Sex</name><value>TCaracThes_Sex</value></attibute>
    <attibute><name>birth_date</name><value>birth_date</value></attibute>
    <attibute><name>death_date</name><value>death_date</value></attibute>
    <attibute><name>comments</name><value>comments</value></attibute>
    </attibutes>
    </Object>

  2. #2
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    Bonjour,

    Votre trigger n'est pas ensembliste.
    Donc si vous mettez à jour par exemple 4000 lignes de votre table, que va-t-il se passer ?
    Seule la première valeur rencontrée dans la colonne est affectée à vos variables, et les autres passeront à la trappe
    Regardez les problèmes que cela pose dans le billet que j'ai écrit à ce sujet.

    Bannissez aussi l'utilisation de curseur, surtout dans les triggers, qui doivent s'exécuter rapidement.
    Vous connaissez déjà les colonnes de votre table, c'est dommage d'utiliser un curseur lent et moche.
    Au pire si vous enlevez ou supprimez une colonne de votre table, il vous faudra maintenir un peu votre trigger

    Voici donc le code que je vous propose :

    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
    ALTER TRIGGER dbo.tr_ArchiveDataOnUpdate
    	ON dbo.Individual_Obj
    AFTER UPDATE
    AS 
    BEGIN
    	SET NOCOUNT ON;
     
    	DECLARE @xml NVARCHAR(MAX);
     
    	SELECT @xml = ISNULL(@xml, '') +
    				'<Object>' + CHAR(13) + 
    					'<pk>'+ CAST(id AS VARCHAR) + '</pk>' + CHAR(13) +
    					'<attibutes>' + CHAR(13) +
    						'<attibute><name>colonneDeTypeNumerique</name><value>' + CAST(colonneDeTypeNumerique AS VARCHAR) + '</value></attibute>' + CHAR(13) +
    						'<attibute><name>colonneDeTypeChaîne</name><value>' + colonneDeTypeChaîne + '</value></attibute>' + CHAR(13) +
    						'<attibute><name>colonneDeTypeDate</name><value>' + CONVERT(CHAR(10), colonneDeTypeDate, 103) + '</value></attibute>' + CHAR(13) +
    					'</attibutes>' + CHAR(13) +
    				'<Object>'
    	FROM DELETED;
     
    	INSERT INTO dbo.LogObjects
    	(
    		object_type,
    		update_date,
    		obj_archive
    	)
    	VALUES
    	(
    		'Individual',
    		CURRENT_TIMESTAMP,
    		@xml
    	);
    END;
    Ici vous concaténez toutes les valeurs d'un trait, en ne vous servant que de la table virtuelle DELETED.

    La colonne dbo.LogObjects est-elle de type XML ? Sinon, c'est dommage, d'autant que vous pouvez valider la chaîne construite avec un schéma XSD (CREATE XML SCHEMA COLLECTION monSchemaXML AS, et CREATE TABLE maTable (maColonne XML (monSchemaXML))

    Vous pouvez utiliser la fonction CURRENT_TIMESTAMP, mais préférez lui GETDATE(), qui est ANSI.

    @++

  3. #3
    Candidat au Club
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    3
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 3
    Points : 2
    Points
    2
    Par défaut
    Merci pour la réponse. Je vais revoir mon trigger de façon à ne pas faire appel a un curseur. Pour ce qui est de faire un trigger ensembliste ce n'est théoriquement pas très important car les modifications (réalisées au travers d'une interface) n'implique qu'un seul enregistrement.

    Par contre je ne comprend toujours pas le comportement de mon "ancien" trigger. Pourquoi me renvoie t-il la valeur de la variable @champ et non pas le résultat du SELECT?

    a+

  4. #4
    Modérateur

    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Janvier 2005
    Messages
    5 826
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2005
    Messages : 5 826
    Points : 12 371
    Points
    12 371
    Par défaut
    Bonjour,

    A cause de cette ligne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT @value = @champ FROM DELETED;
    @++

Discussions similaires

  1. insérer une variable dans le nom d'une variable
    Par leninelenine dans le forum Général Python
    Réponses: 11
    Dernier message: 28/05/2015, 08h25
  2. [AC-2013] Requete avec comme parametre des variables.
    Par NenciariniL dans le forum Requêtes et SQL.
    Réponses: 4
    Dernier message: 24/05/2015, 11h28
  3. [PowerShell] Acces variable dont le nom est une variable
    Par marion782 dans le forum Scripts/Batch
    Réponses: 1
    Dernier message: 12/09/2011, 11h16
  4. DOS - Variable contenant le nom d'une variable
    Par brolon dans le forum Scripts/Batch
    Réponses: 2
    Dernier message: 09/03/2009, 09h27
  5. Requete - Etats avec un champs variable
    Par oops1980 dans le forum Access
    Réponses: 1
    Dernier message: 19/07/2007, 17h36

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