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 :

Découper une chaine séparée par des séparateur ;


Sujet :

MS SQL Server

  1. #1
    Membre du Club
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Janvier 2003
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn et Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information

    Informations forums :
    Inscription : Janvier 2003
    Messages : 85
    Points : 51
    Points
    51
    Par défaut Découper une chaine séparée par des séparateur ;
    Bonjour,
    je travail sur une base de donnée cegid et j'ai un champ qui a a forme :
    BLC;GLC;000000002;000;000003;

    j'aimerais récupérer dans
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    NATUREPIECEG = BLC             ==> 1 ier champ
    SOUCHE          =GLC              ==>  2ieme champ
    NUMPIECE        =000000002    ==> 3 ieme champ
    NUM                =000             ==> 4 ieme champ
    NUMLIGPIECE    =000003        ==> 5 ieme champ
    remarque je ne suis pas sur que les champs on une longueur fixe.
    Sinon j'aurais fait des :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    LEFT(RD8_CLEDATA,3) AS NATUREPIECEG,
    RIGHT(LEFT(RD8_CLEDATA,7),3)AS SOUCHE,
    RIGHT(LEFT(RD8_CLEDATA,17),9)as NUMPIECE,
    RIGHT(LEFT(RD8_CLEDATA,21),3)AS NUM,
    RIGHT(LEFT(RD8_CLEDATA,28),6)AS NUMLIGPIECE,
    requete :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select RD8_CLEDATA,NATUREPIECEG,SOUCHE,NUMPIECE,NUM,NUMLIGPIECE from ligne
    résultat souhaité:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    RD8_CLEDATA;NATUREPIECEG;SOUCHE;NUMPIECE;NUM;NUMLIGPIECE
    BLC;GLC;000000002;000;000003;;BLC;GLC;000000002;000;000003
    BLC;GLC;000000002;000;000004;;BLC;GLC;000000002;000;000004
    BLC;GLC;000000005;000;000003;;BLC;GLC;000000005;000;000003
    BLC;GLC;000000005;000;000004;;BLC;GLC;000000005;000;000004
    BLC;GLC;000000006;000;000002;;BLC;GLC;000000006;000;000002
    BLC;GLC;000000018;000;000002;;BLC;GLC;000000018;000;000002
    BLC;GLC;000000024;000;000003;;BLC;GLC;000000024;000;000003
    Comment faire? Ensuite je créerai une vue.

    Merci pour vos réponses.

    DT

  2. #2
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    90
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 90
    Points : 77
    Points
    77
    Par défaut
    Salut,

    Je te propose une petite fonction sans prétention qui permet de récupérer une chaine de ta valeur selon son index :
    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
    -- Fonction qui permet de récupérer une chaine
    -- Retourne la valeur si elle est trouvé ou NULL si @Index supérieur au nombre d'occurence dans @Chaine
    CREATE FUNCTION dbo.SubVal
    (
    	@Chaine VarChar(255),		-- Chaine contenant les valeurs
    	@Idx TinyInt,			-- Index de la valeur recherchée
    	@Separateur VarChar(5) = ';'	-- Séparateur des valeurs dans la chaine
    )  
    RETURNS VarChar(255)
    AS 
    BEGIN
    	Declare @Valeur VarChar(255)	-- Valeur de retour de la fonction
    	Declare @Pos Int		-- Position du curseur dans la chaine
    	Declare @Cpt Int		-- Compteur
     
    	Select @Cpt = 1, @Pos = 1, @Valeur=NULL
     
    	While (@Cpt < @Index AND Charindex(@Separateur, @Chaine, @Pos)>@Pos)
    	Begin
    		SELECT @Cpt=@Cpt+1, @Pos=Charindex(@Separateur, @Chaine, @Pos)+1
    	End
     
    	If @Cpt=@Idx
    		IF Charindex(@Separateur, @Chaine, @Pos)>@Pos
    			SET @Valeur = ltrim(rtrim(Substring(@Chaine, @Pos, Charindex(@Separateur, @Chaine, @Pos)-@Pos)))
    		ELSE IF Charindex(@Separateur, @Chaine, @Pos)=@Pos
    			SET @Valeur = ''
    		ELSE
    			SET @Valeur = ltrim(rtrim(Substring(@Chaine, @Pos, 255)))
     
    	Return @Valeur
    END
    Exemple d'appel :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    SELECT dbo.Split('a,b,,defg', 1, ',')  --> Retourne 'a'
    SELECT dbo.Split('a,b,,defg', 2, ',')  --> Retourne 'b'
    SELECT dbo.Split('a,b,,defg', 3, ',')  --> Retourne ''
    SELECT dbo.Split('a,b,,defg', 4, ',')  --> Retourne 'defg'
    SELECT dbo.Split('a,b,,defg', 5, ',')  --> Retourne NULL
    C'est pas super optimisé mais ça fonctionne.
    J'espère que ça t'aidera.

    Bonne continuation.

  3. #3
    Membre du Club
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Janvier 2003
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn et Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information

    Informations forums :
    Inscription : Janvier 2003
    Messages : 85
    Points : 51
    Points
    51
    Par défaut Merci
    Merci de ta reponse mais comment creer la fonction et l'utiliser dans un select?

    Merci.

  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 : 42
    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,

    Pour créer la fonction il suffit d'exécuter l'instruction que Te-Deum vous propose dans une fenêtre de requête sous SQL Server Management Studio.

    Pour l'utiliser dans un SELECT :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SELECT dbo.SubVal(maColonne, LEN(maColonne), ';')
    Mais à votre place j'aurai plutôt fait une table ayant autant de colonnes qu'il y a de champs dans le fichier, et chargé celle-ci à l'aide de l'instruction BULK INSERT :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    BULK INSERT dbo.maTable
    FROM 'C:\monFichier.txt'
    WITH (FIELDTERMINATOR = ';', ROWTERMINATOR = '\n')
    @++

  5. #5
    Membre du Club
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Janvier 2003
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn et Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information

    Informations forums :
    Inscription : Janvier 2003
    Messages : 85
    Points : 51
    Points
    51
    Par défaut
    Bonsoir,
    Ce n'est pas un fichier,c'est pour découper un champ clé d'une base CEGID.
    CE qui me permet de remonter dans un fichier de ligne dans la base de données.
    C'est l'application qui est faite comme ça.

    Cordialement.

  6. #6
    Membre du Club
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Janvier 2003
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn et Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information

    Informations forums :
    Inscription : Janvier 2003
    Messages : 85
    Points : 51
    Points
    51
    Par défaut Réponse à TE-DEUM
    Bonjour,
    J'ai essayé ta réponse.
    Quand je crée la fonction j'ai le message d'erreur suivant:
    Msg*137, Niveau*15, État*2, Procédure*SubVal, Ligne*17
    La variable scalaire "@INDEX" doit être déclarée.

    Alors j'ai ajouté :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Declare @INDEX Int		-- Compteur
    La fonction se crée.

    Maintenant je veut l'utiliser : je tape
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    select GL_PIECEORIGINE, dbo.Subval(GL_PIECEORIGINE, 1, ';'),dbo.Subval(GL_PIECEORIGINE, 2, ';') from ligne where GL_PIECEORIGINE<>''
    je récupére ce résultat :
    GL_PIECEORIGINE (Aucun nom de colonne) (Aucun nom de colonne)
    BRC;GLC;000000408;000;000001; BRC NULL
    BRC;GLC;000000408;000;000002; BRC NULL
    BRC;GLC;000000408;000;000003; BRC NULL
    CC ;GCC;000000113;000;000001; CC NULL
    CC ;GCC;000000113;000;000002; CC NULL
    CC ;GCC;000000113;000;000003; CC NULL
    CC ;GCC;000000104;000;000001; CC NULL
    DE ;GDC;000000039;000;000001; DE NULL
    DE ;GDC;000000039;000;000002; DE NULL
    Je récupére bien la premiére sous chaine mais pas la deuxiéme.

    Et comment modifier la fonction pour qu'elle reste valide quelque soit le caractére de séparation.

    Merci de ta réponse

  7. #7
    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
    Bonjour,

    Le caractère de séparation est un paramètre optionnel de la fonction !
    Si vous avez un autre separateur, spécifiez le à la fonction.

    Quelle version de SQL Server utilisez-vous ?

  8. #8
    Membre régulier
    Profil pro
    Inscrit en
    Janvier 2005
    Messages
    90
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2005
    Messages : 90
    Points : 77
    Points
    77
    Par défaut Correction...
    Salut,

    Désolé du petit soucis d'auto-complétion ^^
    En fait, au lieu de déclarer la variable @INDEX, il faut changer @INDEX par @Idx (Qui est l'index de l'élément qu'on recherche).

    Revoici la fonction (Ne pas oublier de supprimer celle qui existe ou alors faire un ALTER au lieu du CREATE) :
    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
    -- Fonction qui permet de récupérer une chaine
    -- Retourne la valeur si elle est trouvé ou NULL si @Index supérieur au nombre d'occurence dans @Chaine
    CREATE FUNCTION [dbo].[SubVal]
    (
    	@Chaine VarChar(255),		-- Chaine contenant les valeurs
    	@Idx TinyInt,			-- Index de la valeur recherchée
    	@Separateur VarChar(5) = ';'	-- Séparateur des valeurs dans la chaine
    )  
    RETURNS VarChar(255)
    AS 
    BEGIN
    	Declare @Valeur VarChar(255)	-- Valeur de retour de la fonction
    	Declare @Pos Int		-- Position du curseur dans la chaine
    	Declare @Cpt Int		-- Compteur
     
    	SELECT @Cpt = 1, @Pos = 0, @Valeur=NULL
     
    	While (@Cpt < @Idx AND Charindex(@Separateur, @Chaine, @Pos+1)>@Pos)
    	Begin
    		SELECT @Cpt=@Cpt+1, @Pos=Charindex(@Separateur, @Chaine, @Pos+1)
    	End
     
    	IF @Cpt=@Idx
    		SET @Pos = @Pos + 1
    		IF Charindex(@Separateur, @Chaine, @Pos)>@Pos
    			SET @Valeur = ltrim(rtrim(Substring(@Chaine, @Pos, Charindex(@Separateur, @Chaine, @Pos)-@Pos)))
    		ELSE IF Charindex(@Separateur, @Chaine, @Pos)=@Pos
    			SET @Valeur = ''
    		ELSE
    			SET @Valeur = ltrim(rtrim(Substring(@Chaine, @Pos, 255)))
     
    	RETURN @Valeur
    END
    Au plaisir et bonnes fêtes à vous :-D

  9. #9
    Expert éminent sénior
    Avatar de mikedavem
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Août 2005
    Messages
    5 450
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Ain (Rhône Alpes)

    Informations professionnelles :
    Activité : Administrateur de base de données
    Secteur : Distribution

    Informations forums :
    Inscription : Août 2005
    Messages : 5 450
    Points : 12 891
    Points
    12 891
    Par défaut
    Bon aller une autre solution a base de XML. Il faudrait voir si cela n'est pas plus performant si vous avez le temps

    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
     
    DECLARE @ligne TABLE
    (
     id INT,
     cegid VARCHAR(100)
    );
     
    INSERT @ligne VALUES (1, 'BLC;GLC;000000002;000;000003;');
    INSERT @ligne VALUES (2, 'ABC;CBA;000000004;0111;0003;');
     
    DECLARE @separateur CHAR(1);
    SET @separateur = ';';
     
    WITH CTE
    AS
    (
     SELECT id, CAST('<c>' + REPLACE(SUBSTRING(cegid, 1, LEN(cegid) -1), @separateur, '</c><c>') + '</c>' AS XML) AS V_xml
     FROM @ligne
    )
    SELECT 
     id,
     V_xml.value('(/c/text())[1]', 'VARCHAR(50)') AS NATURESPIECEG,
     V_xml.value('(/c/text())[2]', 'VARCHAR(50)') AS SOUCHE,
     V_xml.value('(/c/text())[3]', 'VARCHAR(50)') AS NUMPIECE,
     V_xml.value('(/c/text())[4]', 'VARCHAR(50)') AS NUM,
     V_xml.value('(/c/text())[5]', 'VARCHAR(50)') AS NUMLIGPIECE
    FROM CTE;
    ++

  10. #10
    Membre du Club
    Homme Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Janvier 2003
    Messages
    85
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn et Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information

    Informations forums :
    Inscription : Janvier 2003
    Messages : 85
    Points : 51
    Points
    51
    Par défaut Merci
    Bonjour
    et Merci pour toutes ces réponses.

    Cordialement

Discussions similaires

  1. Réponses: 7
    Dernier message: 27/02/2015, 15h02
  2. Découper une chaine ligne par ligne
    Par freud dans le forum Langage
    Réponses: 2
    Dernier message: 24/11/2011, 13h17
  3. Réponses: 5
    Dernier message: 24/02/2011, 15h21
  4. Découper une chaine séparée par des ; SQL SERVER 2005 express
    Par DESPREZ dans le forum Développement
    Réponses: 2
    Dernier message: 06/11/2008, 10h09
  5. découper une chaine selon un spéarateur
    Par freestyler dans le forum Delphi
    Réponses: 2
    Dernier message: 16/05/2007, 15h44

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