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 :

[SP] Comment fournir la liste d'un "IN" en paramèt


Sujet :

MS SQL Server

  1. #1
    Membre régulier
    Inscrit en
    Mai 2002
    Messages
    190
    Détails du profil
    Informations forums :
    Inscription : Mai 2002
    Messages : 190
    Points : 83
    Points
    83
    Par défaut [SP] Comment fournir la liste d'un "IN" en paramèt
    Bonjour.

    Je viens de constater qu'une procédure stockée que je croyais opérationnelle ne l'est probablement pas tant que ça...

    Voici le début de ma procédure :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    DECLARE
    	@ListePrIdParent varchar(200)
     
    	set @ListePrIdParent='304,1451'
     
    	SELECT count(*)
    	   FROM T_LIEN_NS
    	   WHERE
    1)	       LNS_NS_PR_ID_PARENT_FK IN (@ListePrIdParent)
    2)--	     LNS_NS_PR_ID_PARENT_FK IN (304, 1451)
    Les lignes 1) et 2) sont des équivalentes que je passe en commentaire alternativement pour tester.

    La vrai procedure stockée ne comporte pas la ligne 2), mais la ligne 1). Pourtant, avec les valeurs que j'ai fourni ici, la procédure ne fonctionne qu'avec la ligne 2) et pas avec la ligne 1).

    Et voilà ce qu'il me marque :
    Erreur de conversion du type de données varchar en numeric.
    Ce que je cherche à faire, c'est à lui passer sous forme d'une chaine, la liste à placer après le "IN"... mais apparemment, je n'utilise pas la bonne méthode !

    Comment puis-je faire ? Quelqu'un a une idée ?
    Pour mes développements, j'utilise :
    WinX-64bits, Delphi Tokyo 10.2.2
    Merci, merci, merci... moi aussi je vous aime, c'est trop d'émotions...
    Key user des blagues nulles

  2. #2
    Membre confirmé
    Profil pro
    Inscrit en
    Juillet 2004
    Messages
    434
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2004
    Messages : 434
    Points : 502
    Points
    502
    Par défaut
    deux solutions :
    soit tu crées une variable par valeur dans ta liste
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    declare @liste varchar(200)
    set @liste = '1'
    declare @liste2 varchar(200)
    set @liste = '2'
     
    select name
    from sysobjects
    where id in (@liste, @liste2)

    soit tu écris ta requete dans une variable de commande
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    declare @liste varchar(200)
    set @liste = '1,2'
    declare @cmd nvarchar(300)
    set @cmd = 'select name from sysobjects where id in (' + @liste + ')'
    exec (@cmd)

  3. #3
    Membre régulier
    Inscrit en
    Mai 2002
    Messages
    190
    Détails du profil
    Informations forums :
    Inscription : Mai 2002
    Messages : 190
    Points : 83
    Points
    83
    Par défaut
    Merci !!!

    La seconde solution proposée me conviens très bien et elle marche !

    Merci beaucoup.
    Pour mes développements, j'utilise :
    WinX-64bits, Delphi Tokyo 10.2.2
    Merci, merci, merci... moi aussi je vous aime, c'est trop d'émotions...
    Key user des blagues nulles

  4. #4
    Membre à l'essai
    Inscrit en
    Septembre 2008
    Messages
    21
    Détails du profil
    Informations forums :
    Inscription : Septembre 2008
    Messages : 21
    Points : 17
    Points
    17
    Par défaut Qu'en est-il si la liste contient des varchar ?
    Bonjour,
    Le passage en paramètre de données d'une liste du type int est plusieurs fois expliqué sur le forum.
    Qu'en est-il quand il s'agit de passer une liste du type varchar :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    Declare @list_char varchar;
    Set @list_char = "'toto','tata'"; --??
     
    select *
    from matable
    where
    macolonne IN (@list_char)
    Merci

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

    Citation Envoyé par ZERS
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SET @cmd = 'select name from sysobjects where id in (' + @liste + ')'
    Ceci est une horreur car à chaque fois que la requête est soumise au moteur de base de données avec @liste qui change, un nouveau plan est généré.
    Ceci a pour effet de consommer du CPU du fait de la compilation et de l'optimisation, et de pourrir la qualité du cache de procédure.

    La meilleure option que l'on ait pour ce faire est de créer une table utilitaire dans laquelle on stocke les valeurs ad-hoc. On collecte une valeur de type uniqueidentifier en invoquant la fonction NEWID() à chaque appel de la procédure : celle-ci sert alors de jeton de session.

    On stocke les valeurs dans la table utilitaire avec ce jeton, puis on effectue un IN ou un JOIN sur la colonne contenant les valeurs dans la table utilitaire, filtrée par la valeur du jeton. De cette façon le plan est robuste et unique.

    Si toutefois on rencontre ou on prévoit des problèmes de concurrence liés au stockage de ces valeurs dans la table utilitaire, il suffit de créer un certain nombre de tables, avec une clé subrogée, et une autre colonne calculée qui est ABS(CHECKSUM(jeton)) % [nombre de tables].
    Il suffit ensuite de poser une vue sur l'ensemble des tables qui fait le UNION ALL de toutes les tables. SQL Server fera le reste en stockant les lignes dans table qui convient lorsqu'on INSERT la vue.
    La jointure que je décris ci-dessus se fait alors sur la vue.
    Cela permet de répartir la charge de verrouillage sur plusieurs table, et donc d'augmenter la concurrence.

    @++

  6. #6
    Membre expert Avatar de iberserk
    Homme Profil pro
    Architecte de base de données
    Inscrit en
    Novembre 2004
    Messages
    1 795
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Architecte de base de données
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2004
    Messages : 1 795
    Points : 3 173
    Points
    3 173
    Par défaut
    Bonjour,
    Nicolas, tu oublies le plus simple: les Table Valued Parameter...


    Mais encore faudrait-il que notre ami nous précise la version du SQL SERVER visé? f
    Prendre conscience, c'est transformer le voile qui recouvre la lumière en miroir.
    MCTS Database Development
    MCTS Database Administration

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

Discussions similaires

  1. Comment récupérer la liste des contacts de outlook express?
    Par arnaud_verlaine dans le forum Outlook Express / Windows Mail
    Réponses: 6
    Dernier message: 12/10/2004, 15h53
  2. Comment récupérer la liste des logiciels installés sur une machine ?
    Par david_chardonnet dans le forum API, COM et SDKs
    Réponses: 3
    Dernier message: 19/09/2003, 17h41
  3. Comment obtenir la liste des paramètres d'une SP ?
    Par Le Gritche dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 14/03/2003, 16h54

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