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 :

split un champ de ma table dans un select


Sujet :

Développement SQL Server

  1. #1
    Membre régulier
    Inscrit en
    Mai 2009
    Messages
    217
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 217
    Points : 103
    Points
    103
    Par défaut split un champ de ma table dans un select
    Bonjour à tous,

    J'ai une table sql qui contient 2 champs :
    ID int
    ADRESSE varchar(MAX)

    le champ ADRESSE contient des adresses mails séparées par des ; (en nombre variable et de longueur variable)

    Je cherche désespérément à faire une requête qui m'extrait les adresses mails exploitables :

    exemple de contenu de ma table :
    1 toto@yahoo.fr;titi@gmail.fr;tata@yahoo.fr
    2 tutu@gmail.fr;toto@yahoo.fr
    ...

    résultat escompté :
    1 toto@yahoo.fr
    1 titi@gmail.fr
    1 tata@yahoo.fr
    2 tutu@gmail.fr
    2 toto@yahoo.fr

    j'ai bien trouvé sur le net un exemple de fonction qui split un champ mais je n'arrive à le faire fonctionner que sur une ligne de la manière suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    declare @des varchar(max) = (SELECT top 1 [ADRESSE] FROM matable)
         SELECT * FROM fctSplitToChar(@des, ';')
    la fonction :
    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
    ALTER FUNCTION [fctSplitToChar]( 
        @DelimitedText VARCHAR(MAX),  -- liste CSV
        @QuoteChar CHAR(1)            -- caractère de délimitation
    ) RETURNS @Items TABLE (Item VARCHAR(MAX))
     
    BEGIN
       DECLARE @Item VARCHAR(MAX)
       WHILE CHARINDEX(@QuoteChar, @DelimitedText, 0) <> 0 BEGIN
            SELECT @Item=SUBSTRING(@DelimitedText,1,CHARINDEX(@QuoteChar,@DelimitedText, 0)-1), 
                   @DelimitedText=SUBSTRING(@DelimitedText,CHARINDEX(@QuoteChar,@DelimitedText, 0) + LEN(@QuoteChar), LEN(@DelimitedText))
            IF LEN(RTRIM(@Item)) > 0
                INSERT INTO @Items SELECT CONVERT(VARCHAR, @Item)
       END
       -- Dernier item de la liste
       IF LEN(RTRIM(@DelimitedText)) > 0
           INSERT INTO @Items SELECT CONVERT(VARCHAR, @DelimitedText)
       RETURN
    END
    impossible de la faire fonctionner dans une requête sur l'ensemble des lignes de ma table, j'ai essayé la manière suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT a.ID, b.Item
    FROM     matable a
    CROSS    APPLY fctSplitToChar(a.ADRESSE, ';') AS b
    mais ça me renvoie une erreur Syntaxe incorrecte vers '.'.

    Merci d'avance de vos réponses.

  2. #2

  3. #3
    Membre régulier
    Inscrit en
    Mai 2009
    Messages
    217
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 217
    Points : 103
    Points
    103
    Par défaut
    merci pour votre réponse mais cela parle d'une fonction de splittage utilisant une conversion en xml ... pourquoi pas. Mais cela ne réglera pas mon problème pour autant (à moins que je n'ai pas tout compris) : mon problème n'est pas tant de splitter une chaine de caractères (la fonction que j'utilise le fait très bien) mais de l’intégrer dans une requête select sur l'ensemble des lignes de ma table...

    notamment, pourquoi le cross appli ne fonctionne t il pas ? cela réglerait mon pb simplement sans tout réécrire.

  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
    21 898
    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 898
    Points : 53 139
    Points
    53 139
    Billets dans le blog
    6
    Par défaut
    Utilisez la fonction que j'ai écrit à ce sujet :
    http://blog.developpez.com/sqlpro/p7...esure_multiple

    Utilisez le lien PDF, car les balises de merde de developpez bouffent le code SQL....

    Le jeu d'essai :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    CREATE TABLE table_sql
    (ID int,
     ADRESSE varchar(MAX));
     
    INSERT INTO table_sql VALUES 
    (1, 'toto@yahoo.fr;titi@gmail.fr;tata@yahoo.fr'),
    (2, 'tutu@gmail.fr;toto@yahoo.fr');
    La requête :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT ID, MOT
    FROM   table_sql
           CROSS APPLY dbo.F_MULTIPARSE(ADRESSE, ';')
    Le résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    ID          MOT
    ----------- --------------------
    1           toto@yahoo.fr
    1           titi@gmail.fr
    1           tata@yahoo.fr
    2           tutu@gmail.fr
    2           toto@yahoo.fr
    A +

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

    Vous pouvez aussi vous aider de ce billet

    @++

  6. #6
    Membre régulier
    Inscrit en
    Mai 2009
    Messages
    217
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 217
    Points : 103
    Points
    103
    Par défaut
    Merci à tous pour vos réponses,

    Je vais essayer tout ça dés que possible.

  7. #7
    Membre régulier
    Inscrit en
    Mai 2009
    Messages
    217
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 217
    Points : 103
    Points
    103
    Par défaut
    J'ai créé la fonction.

    J'ai fait à l'identique l'exemple proposé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    CREATE TABLE table_sql_test
    (ID int,
     ADRESSE varchar(MAX));
     
    INSERT INTO table_sql_test VALUES 
    (1, 'toto@yahoo.fr;titi@gmail.fr;tata@yahoo.fr'),
    (2, 'tutu@gmail.fr;toto@yahoo.fr');
     
    SELECT ID, MOT
    FROM   table_sql_test
           CROSS APPLY dbo.F_MULTIPARSE(ADRESSE, ';')
    J'ai le message d'erreur suivant :
    Msg*321, Niveau*15, État*1, Ligne*11
    "ADRESSE" n'est pas une option d'indicateur de table reconnue. S'il s'agit d'un paramètre passé à une fonction table ou à la fonction CHANGETABLE, assurez-vous que le mode de compatibilité de votre base de données a la valeur*90.
    (et je ne sais pas à quoi correspond ce mode de compatibilité et ou on le trouve ?)

    et lorsque je rajoute un alias sur la table :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT ID, MOT
    FROM   table_sql_test as a
           CROSS APPLY dbo.F_MULTIPARSE(a.ADRESSE, ';')
    je retombe sur le même message d'erreur que j'avais lors de mes tests avec ma première fonction :
    Msg*102, Niveau*15, État*1, Ligne*11
    Syntaxe incorrecte vers '.'.

  8. #8
    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
    Citation Envoyé par cana13 Voir le message
    (et je ne sais pas à quoi correspond ce mode de compatibilité et ou on le trouve ?)

    Il permet à une base installée sur un serveur 2008, de se comporter, par exemple, comme si elle était en 2000 (a quelques exceptions près malgré tout)
    plus d'informations ici.

    Pour connaitre le niveau de compatibilité de vos bases :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    SELECT compatibility_level
    FROM sys.databases
    et pour le modifier (en connaissance de causes...! ) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    ALTER DATABASE database_name 
    SET COMPATIBILITY_LEVEL = ...

  9. #9
    Membre régulier
    Inscrit en
    Mai 2009
    Messages
    217
    Détails du profil
    Informations forums :
    Inscription : Mai 2009
    Messages : 217
    Points : 103
    Points
    103
    Par défaut
    Hum ! ça m'étonnerait fort que mon administrateur réseau et base de données accepte de toucher à ce paramètre ! trop d'inconnues et d'incidences potentielles , requêtes, fonctions, triggers etc qui risquent de ne plus fonctionner correctement je pense.

    Je vais voir...

    Merci pour vos réponses.

  10. #10
    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
    Il faut bien lire le message d'erreur :

    "ADRESSE" n'est pas une option d'indicateur de table reconnue
    Ceci signifie que SQL Server a compris quelque chose du style table (NOLOCK)
    Il y a donc une erreur de syntaxe quelque part. Rien à voir avec le niveau de compatibilité.
    Cela étant, si vous jetez un œil à ce que je vous ai donné dans mon précédent post, et aussi ici, la solution est toute prête

    @++

  11. #11
    Membre expérimenté

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Septembre 2003
    Messages
    733
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2003
    Messages : 733
    Points : 1 668
    Points
    1 668
    Billets dans le blog
    8
    Par défaut
    Citation Envoyé par elsuket Voir le message
    Il faut bien lire le message d'erreur :

    Ceci signifie que SQL Server a compris quelque chose du style table (NOLOCK)Il y a donc une erreur de syntaxe quelque part. Rien à voir avec le niveau de compatibilité.
    Non ! j’ai refait le test et le scénario complet sous SQL Server 2008. Cette erreur est vraiment liée au mode de compatibilité 2000 de la base de données.

    En compatibilité 90 (2005) et 100 (2008) , la requête SQL ci-dessus fournie par SQLPro s’exécute sans erreur, mais dès que l’on change le mode de compatibilité de la base en 80 (2000), on obtient systématiquement l’erreur indiquée. Exemple :
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT ID, MOT
    FROM table_sql
     CROSS APPLY dbo.F_MULTIPARSE(ADRESSE, ';')
    -- Résultat en compatibilité 90 (2005) et supérieure :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    1	toto@yahoo.fr
    1	titi@gmail.fr
    1	tata@yahoo.fr
    2	tutu@gmail.fr
    2	toto@yahoo.fr
    -- Résultat en compatibilité 80 (2000)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Msg 321, Niveau 15, État 1, Ligne 3
    "ADRESSE" n'est pas une option d'indicateur de table reconnue. S'il s'agit d'un paramètre passé à une fonction table ou à la fonction CHANGETABLE, assurez-vous que le mode de compatibilité de votre base de données a la valeur 90.
    Cette erreur provient de l’analyseur syntaxique en mode de compatibilité 2000, Ce dernier considère que la requête est syntaxiquement incorrecte, et ce, du fait que, dans la clause FROM, un des paramètres de la fonction est le nom d'une colonne (il s’attend à une expression).
    En effet, par exemple, même en compatibilité 80 (2000), la syntaxe ci-dessous ne génère aucune erreur (le résultat bien sûr n’est pas celui attendu ! ici on s’intéresse juste à la syntaxe).
    -- Comptabilité 80 (2000)
    Code SQL : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT ID, MOT
    FROM table_sql
     CROSS APPLY dbo.F_MULTIPARSE('toto@yahoo.fr;titi@gmail.fr', ';')
    Résultat
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    1	toto@yahoo.fr
    2	toto@yahoo.fr
    1	titi@gmail.fr
    2	titi@gmail.fr
    Par ailleurs, tous ces problèmes ayant trait aux niveaux de compatibilité de la base de données, CROSS APPLY, etc. sont bien mentionnés dans le BOL.

    Conclusion : En compatibilité 2000, l’opérateur CROSS APPLY combiné aux fonctions tables est tout simplement inutilisable !

    A+

Discussions similaires

  1. [MySQL] Trouver si une lettre existe dans le champ d'une table dans un SELECT
    Par pasc06 dans le forum PHP & Base de données
    Réponses: 15
    Dernier message: 29/12/2008, 09h01
  2. Réponses: 14
    Dernier message: 19/10/2006, 14h23
  3. [VBA-A]Recuperation champ d'une table dans une collection
    Par Nizarazu dans le forum VBA Access
    Réponses: 14
    Dernier message: 06/04/2006, 11h24
  4. afficher les champs null de deux tables dans un select
    Par poil dans le forum Langage SQL
    Réponses: 2
    Dernier message: 27/09/2005, 15h05
  5. Stocker un champs d'une table dans une variable
    Par ju360modena dans le forum ASP
    Réponses: 3
    Dernier message: 15/06/2005, 08h44

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