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 :

Boucle imbriquée while


Sujet :

Développement SQL Server

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Futur Membre du Club
    Inscrit en
    Avril 2007
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 4
    Par défaut Boucle imbriquée while
    Bonjour à tous,
    Je suis novice sous sql server. Apres de longue heure d'acharnement je n'arrive pas à résoudre mon problème. Si l'un d'entre vous peut m'aider
    J'ai 2 boucles while imbriquée mais lorsque j'insere une ligne la variable @k ne s'incrémente pas pourquoi? je suis perplexe car ma variable @l s'incrémente tres bien.
    En fait j'ai l'impression que c'est les conversions qui posent problemes mais je comprend pas pourquoi.
    Merci d'avance,
    Vincent

    ci joint une partie de mon code:

    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
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
     
    delete from workinghours;
    declare @nomdesignation varchar(50);
    declare @valeur float;
    declare @id_tab int;
    declare @finparcour int;
    declare @finparcourenr int;
    declare @i int;
    declare @j int;
    SELECT @finparcour= (SELECT MAX(id_correspondance) FROM correspondance)
    SELECT @finparcourenr= (SELECT MAX(id_enr) FROM enregistrement)
     
    declare @unite int;
    declare @moisval int;
    declare @anneeval int;
    declare @nom_tab nvarchar(50);
    declare @table as nvarchar(50)
    declare @SQL nvarchar(4000)
    declare @SQL2 nvarchar(4000)
    declare @SQL3 nvarchar(4000)
    declare @SQL4 nvarchar(4000)
    declare @SQL5 nvarchar(4000)
    declare @SQL6 nvarchar(4000)
    declare @SQL7 nvarchar(4000)
    declare @SQL8 nvarchar(4000)
    declare @SQL9 nvarchar(4000)
    declare @SQL10 nvarchar(4000)
    declare @SQL11 nvarchar(4000)
    declare @SQL12 nvarchar(4000)
    declare @SQL13 nvarchar(4000)
    declare @pTableName nvarchar(4000);
     
    declare @champ nvarchar(4000);
    DECLARE @Para NVARCHAR(500)
    SET @Para = N' @RESU nvarchar(4000) OUTPUT'
    declare @presu nvarchar(4000);
    SET  @presu = ''
     
     
     
     
    select @i = 1;
    SELECT @j= (SELECT min(id_enr) FROM enregistrement)
     
    WHILE (@i <=@finparcour) 
    BEGIN
     
      	SELECT @nomdesignation=(SELECT designation FROM correspondance WHERE id_correspondance=@i)
    	SELECT @id_tab=(SELECT id_tableau FROM correspondance WHERE id_correspondance=@i)
    	SET @nom_tab=(SELECT nomtableau FROM tableau WHERE id_tableau=@id_tab)
    	SELECT @unite=(SELECT id_unite FROM correspondance WHERE id_correspondance=@i)
    	declare @k nvarchar(50);
    	SET @pTableName=@nom_tab;
    	select @k=convert(int,@i);
    		WHILE @j<=@finparcourenr 
    		BEGIN
    			declare @anneeval1 nvarchar(50)
    			declare @moisval1 nvarchar(50)
    			declare @valeur1 nvarchar (50)
    			declare @l nvarchar(50)
    			select @l=convert(int,@j)
    			SET  @pRESU = ''
    			SET @SQL = N'SELECT '+ @nomdesignation + ' FROM enregistrement WHERE id_enr=' + @l +''
    			exec sp_executesql @SQL, @PARA,
    			@RESU = @pRESU OUTPUT
    			select @valeur=@pRESU
    			select @valeur1=convert(nvarchar,@valeur)
    			SELECT @moisval= (
                              SELECT     mois
                               FROM         enregistrement
                               WHERE     (id_enr = @j))
    			SELECT @anneeval=(SELECT annee FROM enregistrement WHERE (id_enr=@j) )
    			select @moisval1=convert(nvarchar,@moisval)
    			select @anneeval1=convert(nvarchar,@anneeval)
    			If @anneeval IS NOT NULL
    				BEGIN
    					IF ( @id_tab = 1)
    						BEGIN	
    							SET  @pRESU = ''
    							SET @SQL9 = N'SELECT id_ent FROM '+ @pTableName + ' WHERE id_ent= ' + @k + ' AND  mois= ' + @moisval1 + ' AND annee= ' + @anneeval1 +''
    							exec sp_executesql @SQL9, @PARA,
    							@RESU = @pRESU OUTPUT
    							select @k=convert(int,@i);
    							SET @SQL10='INSERT INTO workinghours ( id_ent , montant , annee , mois ) VALUES ('+@k+', 3 , '+@l+' , 9 )'
    							exec sp_executesql @SQL10	
    						END	
     
    				END
    		SET @j = @j + 1;
    		END;
    SET @i = @i + 1;
    END;

  2. #2
    Membre averti
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    61
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 61
    Par défaut
    Oulala!!!

    Ce que tu devrais faire avant tout c'est mettre toutes tes variables que tu veux declarer dans un seul bloc declare au debut de ton code comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Declare @variable1 typevariable1, @variable2 typevariable2...
    Essai de faire ca au moins ca sera plus clair et voit si ca change quelquechose...

  3. #3
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Août 2005
    Messages
    1 240
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 1 240
    Par défaut
    tu es sur que SELECT @finparcour= (SELECT MAX(id_correspondance) FROM correspondance)
    ne te renvoie pas 1?

  4. #4
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    22 002
    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 002
    Billets dans le blog
    6
    Par défaut
    Ayez la politesse d'indenter votre code.

    voici quelques corrections et ajouts. teestez cela.

    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
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    delete from workinghours;
    declare @nomdesignation varchar(50);
    declare @valeur float;
    declare @id_tab int;
    declare @finparcour int;
    declare @finparcourenr int;
    declare @i int;
    declare @j int;
     
    -- correction
    SELECT @finparcour = MAX(id_correspondance)
    FROM correspondance
     
    SELECT @finparcourenr = MAX(id_enr)
    FROM enregistrement
    -- fin correction
     
    declare @unite int;
    declare @moisval int;
    declare @anneeval int;
    declare @nom_tab nvarchar(50);
    declare @table as nvarchar(50)
    declare @SQL nvarchar(4000)
    declare @SQL2 nvarchar(4000)
    declare @SQL3 nvarchar(4000)
    declare @SQL4 nvarchar(4000)
    declare @SQL5 nvarchar(4000)
    declare @SQL6 nvarchar(4000)
    declare @SQL7 nvarchar(4000)
    declare @SQL8 nvarchar(4000)
    declare @SQL9 nvarchar(4000)
    declare @SQL10 nvarchar(4000)
    declare @SQL11 nvarchar(4000)
    declare @SQL12 nvarchar(4000)
    declare @SQL13 nvarchar(4000)
    declare @pTableName nvarchar(4000);
     
    declare @champ nvarchar(4000);
    DECLARE @Para NVARCHAR(500)
    SET @Para = N' @RESU nvarchar(4000) OUTPUT'
    declare @presu nvarchar(4000);
    SET @presu = ''
     
     
    select @i = 1;
    SELECT @j= (SELECT min(id_enr) FROM enregistrement)
     
    -- ajout
    IF @j IS NULL
    BEGIN
       PRINT 'J NULL'
       RETURN
    END
    -- fin ajout
     
    -- correction
    WHILE @i <= @finparcour
    -- fin correction
    BEGIN
     
    	-- correction
    	SELECT @nomdesignation = designation 
    	FROM correspondance 
    	WHERE id_correspondance=@i
     
    	SELECT @id_tab=id_tableau 
    	FROM correspondance 
    	WHERE id_correspondance=@i
     
    	SELECT @nom_tab=nomtableau 
    	FROM tableau 
    	WHERE id_tableau=@id_tab
     
    	SELECT @unite=id_unite 
    	FROM correspondance 
    	WHERE id_correspondance=@i
    	-- fin correction
     
    	declare @k nvarchar(50);
    	SET @pTableName=@nom_tab;
    	select @k=convert(int,@i);
     
    	WHILE @j<=@finparcourenr
    	BEGIN
    		declare @anneeval1 nvarchar(50)
    		declare @moisval1 nvarchar(50)
    		declare @valeur1 nvarchar (50)
    		declare @l nvarchar(50)
     
                 	-- correction
    		select @l = CAST(@j AS int)
     		-- fin correction
     
    		SET @pRESU = ''
    		SET @SQL = N'SELECT '+ @nomdesignation + ' FROM enregistrement WHERE id_enr=' + @l +''
    		exec sp_executesql @SQL, @PARA,	@RESU = @pRESU OUTPUT
    		select @valeur=@pRESU
     
    		-- correction
    		select @valeur1= CAST(@valeur AS nvarcha)
    		SELECT @moisval=mois FROM enregistrement WHERE id_enr = @j
    		SELECT @anneeval=annee FROM enregistrement WHERE id_enr=@j
    		select @moisval1=CAST(@moisval AS nvarchar)
    		select @anneeval1=CAST(@anneeval AS nvarchar)
     		-- fin correction
     
    		If @anneeval IS NOT NULL
    		BEGIN
    		   IF @id_tab = 1
    		   BEGIN
    		      SET @pRESU = ''
    		      SET @SQL9 = N'SELECT id_ent FROM '+ @pTableName + ' WHERE id_ent= ' + @k + ' AND mois= ' + @moisval1 + ' AND annee= ' + @anneeval1 +''
    		      exec sp_executesql @SQL9, @PARA,
    		      @RESU = @pRESU OUTPUT
    		      select @k=CAST(@i, int)
    		      SET @SQL10='INSERT INTO workinghours ( id_ent , montant , annee , mois ) VALUES ('+@k+', 3 , '+@l+' , 9 )'
    		      exec sp_executesql @SQL10
    		   END
    		END
    		SET @j = @j + 1;
    	END;
    	SET @i = @i + 1;
    END;
    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/ * * * * *

  5. #5
    Futur Membre du Club
    Inscrit en
    Avril 2007
    Messages
    4
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 4
    Par défaut
    Merci pour vos réponse!
    rattlehead: tu es sur que SELECT @finparcour= (SELECT MAX(id_correspondance) FROM correspondance)
    ne te renvoie pas 1?
    >>Oui j'en suis sur j'ai testé la requete et il me renvois bien la bonne valeur sois 148

    SQLpro: Ayez la politesse d'indenter votre code.
    >>Désolé je travail sur serveur distant et je n'ai pas fait attention mais le copier/coller entre le serveur et mon poste n'a pas garder l'indentation.

    J'ai essayé votre correction et malheureusement elle ne fonctionne pas.
    J'ai aussi remplacer ma boucle while (@i<@finparcour) par un curseur
    et la cela fonctionne sauf que j'ai découvert de nouvelles erreurs que je n'avais pas avant. Visiblement mes champs designation contiennent des valeurs
    du genre:WH_U_o.o_r.d ou encore WH_U_o_sales/mark
    et j'obtient les erreurs suivantes:

    Nom de colonne non valide : 'WH_U_o_sales'.
    Msg 207, Niveau 16, État 1, Ligne 1
    Nom de colonne non valide : 'mark'.
    OU
    L'identificateur en plusieurs parties 'WH_U_o.o_train' ne peut pas être lié.
    Msg 4104, Niveau 16, État 1, Ligne 1

    Donc il n'arrive pas a faire la comparaison quand les valeurs de designation contiennent les caracteres '/' ou '.' ???

    Est ce que ca peut etre ce probleme de caractere speciaux qui faisait "planter" ma boucle while (@i<@finparcour)

    Est ce qu'il y a une possibilité de faire des point d'arret sur sql server?

    Merci et excusé moi encore pour le code non indenté

  6. #6
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Août 2005
    Messages
    1 240
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 1 240
    Par défaut
    tu peux faire des prints à la place des points d'arrêt.

  7. #7
    Membre confirmé
    Inscrit en
    Avril 2008
    Messages
    59
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Avril 2008
    Messages : 59
    Par défaut
    Bonjour, je continue actuellement le projet précédemment débuté par noax86. Je suis cependant confronté à des difficultés de compréhension du code, je ne possède que les bases concernant SQL et PL-SQL et je débute depuis quelques semaines seulement le T-SQL.

    Ma première question concerne le code ci-dessous. Je ne comprends pas la synthaxe : Pourquoi @RESU n'a pas été déclaré au dessus ? comment se fait-il qu'il soit "déclaré" dans une affectation.

    Ensuite j'aimerais que l'on m'explique la deuxième ligne. J'ai appris que le N permet de spécifier que la chaîne subséquente est codée en Unicode, cependant dans mon exemple N est suivi d'une affectation de la variable @RESU dont l'origine m'est inconnue.

    Je vous remercie de l'attention que vous prêtez à mon problème.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
        SET @Para = N' @RESU nvarchar(4000) OUTPUT'
        SET @SQL = N'set @RESU = (SELECT '+ @nomdesignation + ' FROM dbo.enregistrement WHERE id_enr=' + @l +') ';
    Edité:
    Merci pour cette réponse rapide.
    Je continue cependant à me demander si l'instruction DECLARE est facultative, il me semble que se soit le cas à la vue de la première ligne de mon exemple. Qu'en est-il véritablement ?

  8. #8
    Membre extrêmement actif
    Profil pro
    Inscrit en
    Août 2005
    Messages
    1 240
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 1 240
    Par défaut
    en c'est la construction d'une requete dynamique.
    @resu est une variable qui sera renvoyé par la procédure stockée qui utilisera cette requete.
    @resu est bien déclaré c'est un nvarchar(4000).
    apres @resu est initialisé dans la ligne suivante.

    c'est juste qu'il faudrait que tu donnes plus de code pour comprendre ce que fait ton T-SQL.

  9. #9
    Membre confirmé
    Inscrit en
    Avril 2008
    Messages
    59
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Avril 2008
    Messages : 59
    Par défaut Déclaration de variables dans une boucle
    Je continue toujours mon travail de refonte de l'ancienne application et je me demande à présent si l'algorithme ne souffre pas de lourdeurs dans sa programmation.
    Tout d'abord je m'interroge quant aux déclarations de variables à l'intérieur de boucle While, ce procédé n'est-il pas trop gourmand en ressources processeur et mémoire ? Dans le code ci-dessous vous pouvez constater que les variables sont initialisées dans la boucle while, ma question est : est-il préférable de conserver l'organisation actuelle ou au contraire dois-je externaliser les déclarations ?

    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
    -- Variable contenant au format unicode, l'identifiant de la table enregistrement
        DECLARE @k nvarchar(50)
     
        SELECT @idMaxCorresp = MAX(id_correspondance)    -- finparcour
        FROM dbo.correspondance
     
        SELECT @idMaxEnreg = MAX(id_enr)        -- finparcourenr
        FROM dbo.enregistrement
     
        SELECT @idMinEnreg = MIN(id_enr) 
        FROM enregistrement
     
        SELECT @nomTab = nomtableau            -- nom_tab
        FROM tableau
        WHERE (id_tableau = @id_tab)
     
        -- Le N permet de spécifier que la chaîne subséquente est codée en Unicode
        -- OUTPUT indique que la variable est un paramètre de sortie
        SET @Para = N' @RESU nvarchar(4000) OUTPUT'
        SET @presu = ''
        SET @pTableName = @nomTab
     
        -- Boucle autant de fois qu'il y a d'enregistrements
        WHILE @idMinEnreg <= @idMaxEnreg
     
        BEGIN
            -- Déclaration des variables pour les libellés de la nomenclature
            DECLARE @libNiv1 nvarchar(200)            -- lib1
            DECLARE @libNiv2 nvarchar(200)            -- lib2
            DECLARE @libNiv3 nvarchar(200)            -- lib3
     
            DECLARE @anneeval1 nvarchar(50)
            DECLARE @moisval1 nvarchar(50)
            DECLARE @valeur1 nvarchar (50)
     
            -- Variable contenant au format unicode, le plus petit identifiant de la table enregistrement 
            DECLARE @nIdEnreg nvarchar(50)
     
            SET @nIdEnreg = convert(int, @idMinEnreg)
            SET @pRESU = ''
            SET @k = convert(int, @idCorresp)
    La variable @k est initialisée en dehors de la boucle contrairement à la variable @nIdEnreg, laquelle de ses deux déclarations vous paraît le plus évident ?
    P.S : Je suis ouvert à toutes remarques constructives concernant mon code, merci.

    Edité : Je continue mon apprentissage du T-SQL et je découvre peu à peu des erreurs dont le sens m'échappe. Précédemment je me suis interrogé sur la déclaration de la variable @RESU et je continue d'ignorer le principe de fonctionnement de T-SQL concernant la déclaration.
    Concrètement le code suivant fonctionne correctement contrairement au second qui génère une erreur.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    -- Version qui fonctionne
    SET @SQL = N'set @RESU = (SELECT '+ @nomdesignation + ' FROM dbo.enregistrement WHERE id_enr=' + @nIdEnreg +') '
    exec sp_executesql @SQL, @PARA
     
    -- Version incorrecte
    SET @RESU = (SELECT '+ @nomdesignation + ' FROM dbo.enregistrement WHERE id_enr=' + @nIdEnreg +')
    SET @SQL = N'@RESU'
    exec sp_executesql @SQL, @PARA
     
    -- erreur générée
    Msg*137, Niveau*15, État*1, Ligne*95
    La variable scalaire "@RESU" doit être déclarée.
    Dans les deux cas, la variable @RESU n'est jamais déclarée (pas d'instruction DECLARE), pourquoi seule la deuxième version du code génère-t-elle une erreur ?

Discussions similaires

  1. Problème avec deux boucles do whiles imbriquées
    Par breizh297 dans le forum Fortran
    Réponses: 1
    Dernier message: 15/11/2010, 08h37
  2. boucles do - while imbriquées
    Par Vakarm dans le forum ASP
    Réponses: 1
    Dernier message: 30/05/2008, 22h19
  3. Boucle imbriquée avec for each et while
    Par guen dans le forum Access
    Réponses: 7
    Dernier message: 01/03/2007, 17h36
  4. probleme de recordset dans une boucle do while
    Par Shoryu dans le forum ASP
    Réponses: 18
    Dernier message: 05/07/2004, 15h30
  5. Appel recurssif et boucle Do...While
    Par zsoh dans le forum Langage
    Réponses: 6
    Dernier message: 31/05/2004, 18h01

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