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

MS SQL Server Discussion :

Requête comment faire un Update avec une concaténation


Sujet :

MS SQL Server

  1. #1
    Membre à l'essai
    Homme Profil pro
    Analyste d'exploitation
    Inscrit en
    Septembre 2012
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Analyste d'exploitation
    Secteur : Services de proximité

    Informations forums :
    Inscription : Septembre 2012
    Messages : 10
    Points : 11
    Points
    11
    Par défaut Requête comment faire un Update avec une concaténation
    Bonjour,

    J'ai besoin d'aide en sql 2005 et je fais appel aux membres du forum.

    Je vous remercie à l'avance de prendre un peu de temps.

    J'ai une table :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    CREATE TABLE [dbo].[non_dispo](
        [ikNon_dispo] [int] NULL,
        [ikType_non_dispo_ref] [int] NULL,
        [ikVisite] [int] NULL,
        [ddt_debut] [datetime] NULL,
        [ddt_fin] [datetime] NULL,
        [debut10]  AS (CONVERT([varchar](10),[ddt_debut],(120)) collate French_CI_AS) PERSISTED,
        [fin10]  AS (CONVERT([varchar](10),[ddt_fin],(120)) collate French_CI_AS) PERSISTED,
        [HistoriqueNonDispo] [varchar](2000) NULL
    ) ON [PRIMARY]
    Plusieurs ikvisite ont le même numéro et certains sont uniques.
    J'ai besoin de regrouper les champs HistoriqueNonDispo dans le premier enregistrement du ikvisite, lorsqu'il y en a plus d'un.

    J'ai essayer avec un Update. C'est refusé parce qu'il y a plus d'une possibilité.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    update dbo.non_dispo
    set HistoriqueNonDispo = debut10 + ' - ' + fin10 + ' - ' + tr.cType_non_dispo_ref 
         from dbo.non_dispo
         inner join  BD.dbo.Type_Non_Dispo_Ref tr 
         on dbo.non_dispo.ikType_non_disponibilite_ref = tr.ikType_non_disponibilite_ref
    exemple de la table non_dispo :


    100 1 aaaaaaaaaaa
    101 1 bbbbbbbbbbb
    102 1 ccccccccccc
    103 2 aaaa
    104 3 aaaa
    Résultat attendu :
    100 1 aaaaaaaaaaabbbbbbbbbbbccccccccccc
    101 1 bbbbbbbbbbb
    102 1 ccccccccccc
    103 2 aaaa
    104 3 aaaa
    Il me manque quelques notions pour faire ce genre de script.

    Merci!

  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 766
    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 766
    Points : 52 563
    Points
    52 563
    Billets dans le blog
    5
    Par défaut
    Faites une CTE de mise à jour :
    1) select récursif comme indiqué préalablement
    2) mise à jour avec jointure du SELECT de la CTE.
    http://sqlpro.developpez.com/cours/s...ursives/#LIV-D

    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
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Points : 13 092
    Points
    13 092
    Par défaut
    et une solution à base d'XML :

    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
     
    UPDATE C
    	SET description =( SELECT 
    						REPLACE(
    							REPLACE(
    								(	SELECT description 
    									FROM UneTable 
    									WHERE ikvisite = C.ikvisite
    									ORDER BY iktable
    									FOR XML RAW
    								)
    								, '<row description="'
    								, ''
    							)
    							, '"/>'
    							, ''
    						)
    					)
    FROM UneTable C
    WHERE NOT EXISTS (
    	SELECT 1
    	FROM UneTable
    	WHERE ikvisite = C.ikvisite
    	AND iktable < C.iktable
    	)

  4. #4
    Membre à l'essai
    Homme Profil pro
    Analyste d'exploitation
    Inscrit en
    Septembre 2012
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Analyste d'exploitation
    Secteur : Services de proximité

    Informations forums :
    Inscription : Septembre 2012
    Messages : 10
    Points : 11
    Points
    11
    Par défaut
    J'ai utilisé une récursive tel que suggérée. J'ai une erreur de non correspondance "Les types ne correspondent pas entre la partie d'ancrage et la partie récursive dans la colonne "histo" de la requête récursive "CTE_ND".
    Je ne vois pas mon erreur(probablement très évidente)
    ;

    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
    with 
        CTE_ND (histo, d10,f10, ikv )
        as
        ( select  HistoriqueNonDispo,
             debut10,fin10, ikvisite as ikv
            from non_disponibilite 
            union all
            select histo + (HistoriqueNonDispo 
                + CASE WHEN LEN(HistoriqueNonDispo) = 1 THEN ''
                             ELSE ' '
                                END) AS HISTO,
                debut10, fin10, ikvisite 
            from non_disponibilite suiv 
            inner join CTE_ND on suiv.ikvisite = CTE_ND.ikv
            where (suiv.debut10 <> CTE_ND.d10) 
       &nbsp;)
     
    select rtrim(histo) from CTE_ND

  5. #5
    Membre à l'essai
    Homme Profil pro
    Analyste d'exploitation
    Inscrit en
    Septembre 2012
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Analyste d'exploitation
    Secteur : Services de proximité

    Informations forums :
    Inscription : Septembre 2012
    Messages : 10
    Points : 11
    Points
    11
    Par défaut
    Merci,

    J'ai trouvé , Il me manquait un cast dans le premier select.

    Par contre j'ai atteint le maximum (100) de récursivité.
    Je vais trouver comment augmenter ce paramètre.

    Un gros merci pour pour suggestions

  6. #6
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Chocolat49 Voir le message
    Par contre j'ai atteint le maximum (100) de récursivité.
    Je vais trouver comment augmenter ce paramètre.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    OPTION (MAXRECURSION 32000)

  7. #7
    Membre du Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2007
    Messages
    36
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 36
    Points : 63
    Points
    63
    Par défaut
    Bonjour,

    Testé sur SQL Server 2008, mais ça devrait marcher sur 2005 :

    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
     
    WITH LSTFIRST AS (
    SELECT DISTINCT (SELECT TOP 1 iktable FROM MaTable A WHERE a.ikvisite = MaTable.ikvisite) AS FirstIkTable, ikvisite FROM MaTable 
    )
     
    SELECT * FROM (
    SELECT FirstIkTable AS iktable, ikvisite, 
    (STUFF((
    	SELECT MaTable.description
    	FROM MaTable 
    	WHERE MaTable.ikvisite = LSTFIRST.ikvisite ORDER BY MaTable.iktable
    	FOR XML PATH(''), TYPE, ROOT).value('root[1]','nvarchar(max)'),1,0,'') 
    	) AS description 
    FROM LSTFIRST
    UNION ALL 
    SELECT iktable, ikvisite, description FROM MaTable WHERE iktable NOT IN (SELECT FirstIkTable FROM LSTFIRST)
    ) A
    ORDER BY iktable, ikvisite

  8. #8
    Membre à l'essai
    Homme Profil pro
    Analyste d'exploitation
    Inscrit en
    Septembre 2012
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Analyste d'exploitation
    Secteur : Services de proximité

    Informations forums :
    Inscription : Septembre 2012
    Messages : 10
    Points : 11
    Points
    11
    Par défaut
    Bonjour et merci à tous pour vos suggestions de solution.

    J'ai utlisé la solution d'Amedee et c'est fonctionnelle. J'aimerais mettre à jour la MaTable à partir du CTE. Comment faire ? Je l'ai ajouté après le CTE, mais il ne reconnait plus le CTE.

    Je vais prendre le temps de bien comprendre les CTE. C'est ce qui me manquait souvent dans mes scripts.
    Je paliais souvent en créant des tables temporaires.

    Merci !

  9. #9
    Membre du Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2007
    Messages
    36
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 36
    Points : 63
    Points
    63
    Par défaut
    Bonsoir,

    Les CTE ne sont utilisables que dans la requête principale qui suit immédiatement après.

    Avec l'UPDATE ça devrait donner quelque chose comme ç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
     
    WITH LSTFIRST AS (
    SELECT DISTINCT (SELECT TOP 1 iktable FROM MaTable A WHERE a.ikvisite = MaTable.ikvisite) AS FirstIkTable, ikvisite FROM MaTable 
    )
     
    UPDATE MaTable SET MaTable.description = A.description
    FROM MaTable  
    INNER JOIN (
    SELECT FirstIkTable AS iktable, ikvisite, 
    (STUFF((
    	SELECT MaTable.description
    	FROM MaTable 
    	WHERE MaTable.ikvisite = LSTFIRST.ikvisite ORDER BY MaTable.iktable
    	FOR XML PATH(''), TYPE, ROOT).value('root[1]','nvarchar(max)'),1,0,'') 
    	) AS description 
    FROM LSTFIRST
    UNION ALL 
    SELECT iktable, ikvisite, description FROM MaTable WHERE iktable NOT IN (SELECT FirstIkTable FROM LSTFIRST)
    ) A ON A.iktable = MaTable.iktable
    Attention, je n'ai pas pu la tester.

  10. #10
    Membre à l'essai
    Homme Profil pro
    Analyste d'exploitation
    Inscrit en
    Septembre 2012
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Analyste d'exploitation
    Secteur : Services de proximité

    Informations forums :
    Inscription : Septembre 2012
    Messages : 10
    Points : 11
    Points
    11
    Par défaut
    Bonjour, Un gros merci Amedee!

    J'essaie de mieux comprendre le scritp en apportant quelques modifications. J'aimerais ajouter dans une nouvelle table le contenu des enregistrements qui ont été modifiés. Donc , j'ai modifié le Update par un select into. Je croyais que cela serait simple, mais je n'arrive pas J'ai toujours des doublons .. Qu'est-ce que je ne saisis pas ?


    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
     
    WITH LSTFIRST AS (
    SELECT DISTINCT (SELECT TOP 1 iktable FROM MaTable A WHERE a.ikvisite = MaTable.ikvisite) AS FirstIkTable, ikvisite FROM MaTable 
    )
    Select A.iktable, A.ikvisite, A.description into MaTable_temp 
    FROM MaTable  
    INNER JOIN (
    SELECT FirstIkTable AS iktable, ikvisite, 
    (STUFF((
    	SELECT MaTable.description
    	FROM MaTable 
    	WHERE MaTable.ikvisite = LSTFIRST.ikvisite ORDER BY MaTable.iktable
    	FOR XML PATH(''), TYPE, ROOT).value('root[1]','nvarchar(max)'),1,0,'') 
    	) AS description 
    FROM LSTFIRST
    UNION ALL 
    SELECT iktable, ikvisite, description FROM MaTable WHERE iktable NOT IN (SELECT FirstIkTable FROM LSTFIRST)
    ) A ON A.iktable = MaTable.iktable

  11. #11
    Membre du Club
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2007
    Messages
    36
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 36
    Points : 63
    Points
    63
    Par défaut
    Bonjour,

    Si iktable est unique alors il ne devrait pas y avoir de doublon sur cette colonne dans MaTable_Temp.
    Par contre la requête UPDATE fait une modification sur toutes les lignes de la table d'origine même si elle réaffecte le même contenu. Il est donc normal que le SELECT INTO introduise des doublons sur la colonne ikvisite.
    Pour ne pas avoir de doublons sur la colonne ikvisite, il faut retirer le UNION ALL et la requête qui suit :
    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
     
    WITH LSTFIRST AS (
    SELECT DISTINCT (SELECT TOP 1 iktable FROM MaTable A WHERE a.ikvisite = MaTable.ikvisite ORDER BY iktable) AS FirstIkTable, ikvisite FROM MaTable 
    )
     
    SELECT A.iktable, A.ikvisite, A.description INTO MaTable_temp 
    FROM MaTable 
    INNER JOIN (
    SELECT FirstIkTable AS iktable, ikvisite, 
    (STUFF((
    SELECT MaTable.description
    FROM MaTable 
    WHERE MaTable.ikvisite = LSTFIRST.ikvisite ORDER BY MaTable.iktable
    FOR XML PATH(''), TYPE, ROOT).value('root[1]','nvarchar(max)'),1,0,'') 
    ) AS description 
    FROM LSTFIRST 
    ) A ON A.iktable = MaTable.iktable
    NB : j'ai corrigé aussi une petite erreur : j'ai ajouté un ORDER BY dans le SELECT TOP 1 de la CTE.

    Pour le SELECT INTO on peut simplifier dans ce cas encore plus :
    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
     
    WITH LSTFIRST AS (
    SELECT DISTINCT (SELECT TOP 1 iktable FROM MaTable A WHERE a.ikvisite = MaTable.ikvisite ORDER BY iktable) AS FirstIkTable, ikvisite FROM MaTable 
    )
     
    SELECT A.iktable, A.ikvisite, A.description INTO MaTable_temp 
    FROM  (
    SELECT FirstIkTable AS iktable, ikvisite, 
    (STUFF((
    SELECT MaTable.description
    FROM MaTable 
    WHERE MaTable.ikvisite = LSTFIRST.ikvisite ORDER BY MaTable.iktable
    FOR XML PATH(''), TYPE, ROOT).value('root[1]','nvarchar(max)'),1,0,'') 
    ) AS description 
    FROM LSTFIRST 
    ) A

  12. #12
    Membre à l'essai
    Homme Profil pro
    Analyste d'exploitation
    Inscrit en
    Septembre 2012
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Analyste d'exploitation
    Secteur : Services de proximité

    Informations forums :
    Inscription : Septembre 2012
    Messages : 10
    Points : 11
    Points
    11
    Par défaut
    Bonjour,

    Merci à tous pour vos suggestions et principalement à Amedee.
    J'ai cheminé particulièrement, grâce à vos exemples, avec les notions de récursives.

    Bonne journée!

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

Discussions similaires

  1. Réponses: 5
    Dernier message: 30/11/2009, 11h14
  2. [VB] faire un update avec une bdd en xml
    Par ekmule dans le forum VB 6 et antérieur
    Réponses: 1
    Dernier message: 01/02/2006, 22h41
  3. comment faire un sphère avec une texture ?
    Par fregate dans le forum OpenGL
    Réponses: 1
    Dernier message: 12/09/2005, 03h37
  4. Faire un update avec une ss requete renvoyant plusieur row
    Par djodjo dans le forum Langage SQL
    Réponses: 6
    Dernier message: 02/09/2005, 15h51

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