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 :

conversion improbable SQLserver 2000


Sujet :

Développement SQL Server

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Invité
    Invité(e)
    Par défaut conversion improbable SQLserver 2000
    Bonjour à tous

    Voilà, je travaille sur MS SQL Server 2000, et j'ai un souci sur un trigger. Il se déclenche sur l'insertion d'une salle. Le contexte grosso modo, c'est que, à la création de cette salle, et si cette salle n'est pas en travaux (booléen enTravaux), ce trigger doit également lui affecter des équipements particuliers (tables, chaises...). Pour cela, j'ai créé une table AFFECTER, qui définit quels équipements vont dans quelles types de salle, et en quelle quantité, et la table INSTALLER, qui donne, pour chaque salle, les équipements installés.

    Voici le trigger :

    Code SQL : 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
    CREATE TRIGGER affect_mat
    ON SALLE
    FOR INSERT
    AS
    DECLARE
    	@noSalle int,
    	@typeSalle int,
    	@nbPlaces int,
    	@enTravaux bit,
    	@nbTypesMat int,
     
    	/*Variables pour le curseur*/
    	@codeMat int,
    	@nbDefault varchar(10)
    BEGIN
    	SELECT @noSalle = noSalle, @typeSalle = typeSalle, @nbPlaces = nbPlaces, @enTravaux = enTravaux FROM inserted;
    	IF(@enTravaux = 0)		/*On vérifie que la salle est prête à l'emploi*/
    	BEGIN
    		/*On déclare un curseur pour parcourir l'ensemble des matériels à installer*/
    		DECLARE curs_matAffect CURSOR FOR
    		SELECT codeMat, nbDefault FROM AFFECTER WHERE codeType = @typeSalle;
    		OPEN curs_matAffect
    		FETCH NEXT FROM curs_matAffect INTO @codeMat, @nbDefault
    		WHILE(@@FETCH_STATUS = 0)
    		BEGIN
    			IF(@nbDefault = 'nbPlaces')
    			BEGIN
    				INSERT INTO INSTALLER VALUES(@codeMat, @noSalle, @nbPlaces);
    			END
    			ELSE IF(@nbDefault = 'nbPlaces/2')
    			BEGIN
    				INSERT INTO INSTALLER VALUES(@codeMat, @noSalle, @nbPlaces / 2);
    			END
    			ELSE
    			BEGIN
    				INSERT INTO INSTALLER VALUES(@codeMat, @noSalle, CONVERT(int, @nbDefault));
    			END
    			FETCH NEXT FROM curs_matAffect INTO @codeMat, @nbDefault
    		END
    		CLOSE curs_matAffect
    		DEALLOCATE curs_matAffect
    		INSERT INTO EVENEMENT VALUES (getdate(), 'INSTALLER', 'Installation de matériel dans la salle ' + @noSalle);
    	END
    	/*Insertion dans l'historique*/
    	INSERT INTO EVENEMENT VALUES(getdate(), 'SALLE', 'Création de la salle ' + @noSalle);
    END

    Et lors de la création d'une salle, il me marque l'erreur suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Erreur de syntaxe lors de la conversion de la valeur varchar 'Installation du matériel' vers une colonne de type de données int.
    Or, j'ai pu déterminer que l'erreur ne vient pas de l'insertion dans la table EVENEMENT(id, heure, table, message), mais des insertions dans la table INSTALLER(noSalle, codeMat, nbMatInstalles). De plus, j'ai bien vérifié mes types de données, je n'utilise que des int dans la fameuse insertion.

    Voilà, j'espère avoir été assez précis sur l'erreur et le contexte, et que vous pourrez m'aider.

    Merci d'avance

  2. #2
    Membre chevronné Avatar de agemis31
    Profil pro
    DBA
    Inscrit en
    Octobre 2007
    Messages
    399
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : DBA

    Informations forums :
    Inscription : Octobre 2007
    Messages : 399
    Par défaut Pas de cast implicite
    Bonsoir,

    C'est normal,

    Combien font 1 pomme + 2 poires ?

    Il faut convertir explicitement @noSalle en varchar.

    DECLARE @tb TABLE (dt DATETIME, szAction VARCHAR(50), szComment VARCHAR(255))
    DECLARE @noSalle INT
    SET @noSalle = 1
    --Oups !
    --INSERT INTO @tb VALUES (getdate(), 'INSTALLER', 'Installation de matériel dans la salle ' + @noSalle);
    INSERT INTO @tb VALUES (getdate(), 'INSTALLER', 'Installation de matériel dans la salle ' + CAST(@noSalle as VARCHAR));
    SELECT * FROM @tb

  3. #3
    Invité
    Invité(e)
    Par défaut
    Bonsoir,

    En effet, c'est ce que j'ai tout de suite supposé, surtout qu'ayant un peu travaillé sur SQL Server, j'avais l'impression qu'il était très exigeant sur le typage des variables. J'avais donc testé avec CONVERT, ce qui revient au même.
    De plus, il me semblait avoir trouvé au cours de mes maintes et vaines recherches que convertir de int en varchar demandait une conversion implicite.

    En tout cas, après re-test, le problème ne vient pas de là. Il se situe au niveau des insertions dans la table INSTALLER. J'ai fait des tests avec des raiserrors juste après les différents IF sur le contenu de nbDefault, et ça plante dès la première tentative d'insertion dans la table. D'où ma perplexité, vu que le message d'erreur ne semble pas indiquer le bon endroit...

    Merci en tout cas pour ta sollicitude

  4. #4
    Membre chevronné Avatar de agemis31
    Profil pro
    DBA
    Inscrit en
    Octobre 2007
    Messages
    399
    Détails du profil
    Informations personnelles :
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : DBA

    Informations forums :
    Inscription : Octobre 2007
    Messages : 399
    Par défaut Effet de bord ?
    Si tes variables sont bien typées et valuées avant l'insertion dans INSTALLER
    c'est que le problème vient d'ailleurs.

    Y a t'il des triggers sur la table INSTALLER ?

    Rq: Ce serait mieux de faire un jointure entre inserted et AFFECTER pour ajouter les lignes dans INSTALLER et d'utiliser directement inserted pour insérer
    dans EVENEMENT. Sinon tu risque d'avoir des surprises en insérant plusieurs lignes à la fois dans SALLE.

    @+

  5. #5
    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 : 44
    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
    Par défaut
    Bonjour,

    Exact, ce trigger ne traitera que la première ligne de l'ensemble de données, parce qu'il n'est pas ensembliste.
    Les triggers étant gourmands en ressources, et devant s'exécuter très rapidement puisqu'ils font partie de la transaction qui a généré leur déclenchement, mieux vaut ne pas utiliser de curseurs...

    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
    CREATE TRIGGER TR_A_I_SALLE_affect_mat
    	ON dbo.SALLE
    FOR INSERT
    AS
    BEGIN
    	DECLARE @now DATETIME SET @now = GETDATE()
     
    	INSERT INTO dbo.INSTALLER
    	(
    		listeDesColonnes
    	)
    	SELECT A.codeMat,
    			I.noSalle,
    			CASE A.nbDefault
    				WHEN 'nbPlaces' THEN I.nbPlaces
    				WHEN 'nbPlaces/2' THEN (I.nbPlaces / 2)
    				ELSE CAST(A.nbDefault AS INT)
    			END
    	FROM INSERTED AS I 
    	JOIN AFFECTER AS A ON I.typeSalle = A.codeType
    	WHERE I.enTravaux = 0
     
    	-- Concaténation de la liste des numéros de salle en travaux
    	DECLARE @listeSalles VARCHAR(50)
    	SELECT @listeSalles = ISNULL(@listeSalles, '') + I.noSalle + ' '
    	FROM INSERTED
    	WHERE enTravaux = 0
     
    	INSERT INTO dbo.EVENEMENT VALUES (@now, 'INSTALLER', 'Installation de matériel dans la salle ' + @listeSalles)
     
    	-- Insertion dans l'historique
    	INSERT INTO dbo.EVENEMENT VALUES(@now, 'SALLE', 'Création de la salle ' + @listeSalles)
    END
    @++

  6. #6
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par agemis31
    Y a t'il des triggers sur la table INSTALLER ?
    Voilà, le problème était là : il y a un trigger sur l'évènement INSTEAD OF INSERT de INSTALLER, et je n'avais pas fait de conversion explicite lors de l'ajout dans l'historique. Et comme le message de l'évènement est le même sur les deux triggers, je n'ai pas fait le rapprochement.

    Merci beaucoup

    Citation Envoyé par elsuket
    Exact, ce trigger ne traitera que la première ligne de l'ensemble de données, parce qu'il n'est pas ensembliste.
    Les triggers étant gourmands en ressources, et devant s'exécuter très rapidement puisqu'ils font partie de la transaction qui a généré leur déclenchement, mieux vaut ne pas utiliser de curseurs...
    Je vais quand même tester ce bout de code, ça ne pourra pas faire de mal.

    Merci pour vos réponses.

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

Discussions similaires

  1. Réponses: 4
    Dernier message: 22/09/2005, 23h57
  2. Réponses: 1
    Dernier message: 15/09/2005, 10h14
  3. Optimisation SQLServer 2000
    Par Débéa dans le forum MS SQL Server
    Réponses: 1
    Dernier message: 14/07/2005, 16h15
  4. SQLSERVER 2000 CE
    Par royrremi dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 28/10/2004, 19h19

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