Comment passer une liste séparée par des virgules à une procédure stockée ?

StackOverflow https://stackoverflow.com/questions/6369

  •  08-06-2019
  •  | 
  •  

Question

J'ai donc un processus stocké Sybase qui prend 1 paramètre qui est une liste de chaînes séparées par des virgules et exécute une requête avec in dans une clause IN() :

CREATE PROCEDURE getSomething @keyList varchar(4096)
AS
SELECT * FROM mytbl WHERE name IN (@keyList)

Comment appeler mon proc stocké avec plus d'une valeur dans la liste ?Jusqu'à présent, j'ai essayé

exec getSomething 'John'         -- works but only 1 value
exec getSomething 'John','Tom'   -- doesn't work - expects two variables
exec getSomething "'John','Tom'" -- doesn't work - doesn't find anything
exec getSomething '"John","Tom"' -- doesn't work - doesn't find anything
exec getSomething '\'John\',\'Tom\'' -- doesn't work - syntax error

MODIFIER: En fait, j'ai trouvé ça page qui contient une excellente référence sur les différentes manières de transmettre un tableau à un sproc

Était-ce utile?

La solution

Si vous utilisez Sybase 12.5 ou une version antérieure, vous ne pouvez pas utiliser de fonctions.Une solution de contournement pourrait consister à remplir une table temporaire avec les valeurs et à les lire à partir de là.

Autres conseils

C'est un peu tard, mais j'ai eu exactement ce problème il y a quelque temps et j'ai trouvé une solution.

L'astuce consiste à mettre des guillemets doubles, puis à mettre la chaîne entière entre guillemets.

exec getSomething """John"",""Tom"",""Bob"",""Harry"""

Modifiez votre processus pour faire correspondre l'entrée de la table à la chaîne.

CREATE PROCEDURE getSomething @keyList varchar(4096)
AS
SELECT * FROM mytbl WHERE @keyList LIKE '%'+name+'%' 

Je l'ai en production depuis ASE 12.5 ;nous sommes maintenant sur 15.0.3.

Transmettez la liste séparée par des virgules dans une fonction qui renvoie une valeur de tableau.Il y a un exemple MS SQL quelque part sur StackOverflow, bon sang si je peux le voir pour le moment.

CREATE PROCEDURE getSomething @keyList varchar(4096)
AS
SELECT * FROM mytbl WHERE name IN (fn_GetKeyList(@keyList))

Appeler avec -

exec getSomething 'John,Tom,Foo,Bar'

Je suppose que Sybase devrait être capable de faire quelque chose de similaire ?

Devez-vous utiliser une liste séparée par des virgules ?Ces dernières années, j'ai pris ce type d'idée et transmis un fichier XML.La "fonction" openxml prend une chaîne et la transforme en XML, puis si vous créez une table temporaire avec les données, elle est interrogeable.

DECLARE @idoc int
DECLARE @doc varchar(1000)
SET @doc ='
<ROOT>
<Customer CustomerID="VINET" ContactName="Paul Henriot">
   <Order CustomerID="VINET" EmployeeID="5" OrderDate="1996-07-04T00:00:00">
      <OrderDetail OrderID="10248" ProductID="11" Quantity="12"/>
      <OrderDetail OrderID="10248" ProductID="42" Quantity="10"/>
   </Order>
</Customer>
<Customer CustomerID="LILAS" ContactName="Carlos Gonzlez">
   <Order CustomerID="LILAS" EmployeeID="3" OrderDate="1996-08-16T00:00:00">
      <OrderDetail OrderID="10283" ProductID="72" Quantity="3"/>
   </Order>
</Customer>
</ROOT>'
--Create an internal representation of the XML document.
EXEC sp_xml_preparedocument @idoc OUTPUT, @doc
-- Execute a SELECT statement that uses the OPENXML rowset provider.
SELECT    *
FROM       OPENXML (@idoc, '/ROOT/Customer',1)
            WITH (CustomerID  varchar(10),
                  ContactName varchar(20))

Concernant l'idée de Kevin de passer le paramètre à une fonction qui divise le texte en tableau, voici mon implémentation de cette fonction il y a quelques années.Fonctionne à merveille.

Diviser le texte en mots dans SQL

Il s'agit d'une méthode rapide et sale qui peut être utile :

select  * 
from    mytbl 
where   "," + ltrim(rtrim(@keylist)) + "," like "%," + ltrim(rtrim(name)) + ",%"

Je ne sais pas si c'est en ASE, mais dans SQL Anywhere, le sa_split_list La fonction renvoie une table à partir d'un CSV.Il a des arguments facultatifs pour transmettre un délimiteur différent (la valeur par défaut est une virgule) et une longueur maximale pour chaque valeur renvoyée.

fonction sa_split_list

Le problème avec les appels comme celui-ci :exec getSomething '"John","Tom"' est qu'il traite '"John","Tom"' comme une seule chaîne, il ne correspondra qu'à une entrée du tableau qui est '"John","Tom"'.

Si vous ne souhaitez pas utiliser de table temporaire comme dans la réponse de Paul, vous pouvez utiliser SQL dynamique.(Suppose la v12+)

CREATE PROCEDURE getSomething @keyList varchar(4096)
AS
declare @sql varchar(4096)
select @sql = "SELECT * FROM mytbl WHERE name IN (" + @keyList +")"
exec(@sql)

Vous devrez vous assurer que les éléments de @keylist sont entourés de guillemets, même s'il s'agit de valeurs uniques.

Pour revenir sur ce que @Abel a fourni, ce qui m'a aidé était :

Mon objectif était de prendre ce que l'utilisateur final est entré de SSRS et de l'utiliser dans ma clause Where comme une (sélection) évidemment @icd_value_rpt serait commentée dans ma requête de jeu de données.

DECLARE @ICD_VALUE_RPT VARCHAR(MAX) SET @ICD_VALUE_RPT = 'Value1, Value2'
DECLARE @ICD_VALUE_ARRAY XML SET @ICD_VALUE_ARRAY = CONCAT('<id>', REPLACE(REPLACE(@ICD_VALUE_RPT, ',', '</id>,<id>'),' ',''), '</id>')

puis dans mon WHERE J'ai ajouté:

(PATS_WITH_PL_DIAGS.ICD10_CODE IN (SELECT ParamValues.ID.value('.','VARCHAR(MAX)') FROM @ICD_VALUE_ARRAY.nodes('id') AS ParamValues(ID))
OR PATS_WITH_PL_DIAGS.ICD9_CODE IN (SELECT ParamValues.ID.value('.','VARCHAR(MAX)') FROM @ICD_VALUE_ARRAY.nodes('id') AS ParamValues(ID))
)

Essayez de cette façon.Cela fonctionne pour moi.

@itemIds varchar(max)

CREATE PROCEDURE getSomething @keyList varchar(4096)
AS
SELECT * FROM mytbl WHERE name IN (SELECT Value FROM [Global_Split] (@itemIds,','))

Cela fonctionne en SQL.Déclarez dans votre GetSomething procédure une variable de type XML comme telle :

DECLARE @NameArray XML = NULL

Le corps de la procédure stockée implémente les éléments suivants :

SELECT * FROM MyTbl WHERE name IN (SELECT ParamValues.ID.value('.','VARCHAR(10)')
FROM @NameArray.nodes('id') AS ParamValues(ID))

Depuis le code SQL qui appelle le SP pour déclarer et initialiser la variable XML avant d'appeler la procédure stockée :

DECLARE @NameArray XML

SET @NameArray = '<id><</id>id>Name_1<<id>/id></id><id><</id>id>Name_2<<id>/id></id><id><</id>id>Name_3<<id>/id></id><id><</id>id>Name_4<<id>/id></id>'

En utilisant votre exemple, l'appel à la procédure stockée serait :

EXEC GetSomething @NameArray

J'ai déjà utilisé cette méthode et cela fonctionne très bien.Si vous souhaitez un test rapide, copiez et collez le code suivant dans une nouvelle requête et exécutez :

DECLARE @IdArray XML

SET @IdArray = '<id><</id>id>Name_1<<id>/id></id><id><</id>id>Name_2<<id>/id></id><id><</id>id>Name_3<<id>/id></id><id><</id>id>Name_4<<id>/id></id>'

SELECT ParamValues.ID.value('.','VARCHAR(10)')
FROM @IdArray.nodes('id') AS ParamValues(ID)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top