sql - stored - ¿Cómo pasar una lista separada por comas a un procedimiento almacenado?
procedimiento almacenado sql server select (11)
Así que tengo un procedimiento almacenado de Sybase que toma 1 parámetro que es una lista de cadenas separada por comas y ejecuta una consulta con in en una cláusula IN ():
CREATE PROCEDURE getSomething @keyList varchar(4096)
AS
SELECT * FROM mytbl WHERE name IN (@keyList)
¿Cómo llamo a mi proc almacenado con más de 1 valor en la lista? Hasta ahora lo he intentado
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
EDIT: en realidad encontré esta página que tiene una gran referencia de las diversas formas de pasar una matriz a un sproc
Intenta de esta manera. Funciona para mí
@itemIds varchar(max)
CREATE PROCEDURE getSomething @keyList varchar(4096)
AS
SELECT * FROM mytbl WHERE name IN (SELECT Value FROM [Global_Split] (@itemIds,'',''))
¿Necesita usar una lista separada por comas? En los últimos años, he estado tomando este tipo de ideas y pasando un archivo XML. La "función" de openxml toma una cadena y la hace como xml y luego si usted crea una tabla temporal con los datos, es consultable.
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))
Pase la lista separada por comas a una función que devuelve un valor de tabla. Hay un ejemplo de MS SQL en algún lugar de , maldito si puedo verlo en este momento.
CREATE PROCEDURE getSomething @keyList varchar(4096) AS SELECT * FROM mytbl WHERE name IN (fn_GetKeyList(@keyList))
Llamar con -
exec getSomething ''John,Tom,Foo,Bar''
Supongo que Sybase debería ser capaz de hacer algo similar.
Con respecto a la idea de Kevin de pasar el parámetro a una función que divide el texto en una tabla, aquí está mi implementación de esa función desde hace unos años. Funciona un placer
Este es un método rápido y sucio que puede ser útil:
select *
from mytbl
where "," + ltrim(rtrim(@keylist)) + "," like "%," + ltrim(rtrim(name)) + ",%"
El problema con las llamadas como esta: exec getSomething ''"John", "Tom"'' es que trata a '''' John '''', ''Tom'' ''como una sola cadena, solo coincidirá con una entrada en la tabla que es'' '' John "," Tom "''.
Si no quería usar una tabla temporal como en la respuesta de Paul, entonces podría usar sql dinámico. (Asume v12 +)
CREATE PROCEDURE getSomething @keyList varchar(4096)
AS
declare @sql varchar(4096)
select @sql = "SELECT * FROM mytbl WHERE name IN (" + @keyList +")"
exec(@sql)
Deberá asegurarse de que los elementos en @keylist tengan comillas a su alrededor, incluso si son valores únicos.
No estoy seguro si está en ASE, pero en SQL Anywhere, la función sa_split_list devuelve una tabla de un CSV. Tiene argumentos opcionales para pasar un delimitador diferente (por defecto es una coma) y una longitud máxima para cada valor devuelto.
Esto funciona en SQL. Declare en su procedimiento GetSomething una variable de tipo XML como tal:
DECLARAR @NameArray XML = NULL
El cuerpo del procedimiento almacenado implementa lo siguiente:
SELECCIONAR * FROM MyTbl WHERE nombre IN (SELECCIONAR ParamValues.ID.value (''.'', ''VARCHAR (10)'') FROM @ NameArray.nodes (''id'') AS ParamValues (ID))
Desde el código SQL que llama al SP a declarar e inicializar la variable XML antes de llamar al procedimiento almacenado:
DECLARE @NameArray XML
SET @NameArray = ''<id> Nombre_1 </ id> <id> Nombre_2 </ id> <id> Nombre_3 </ id> <id> Nombre_4 </ id>''
Usando su ejemplo, la llamada al procedimiento almacenado sería:
EXEC GetSomething @NameArray
He usado este método antes y funciona bien. Si desea una prueba rápida, copie y pegue el siguiente código en una nueva consulta y ejecútelo:
DECLARAR @IdArray XML
SET @IdArray = ''<id> Nombre_1 </ id> <id> Nombre_2 </ id> <id> Nombre_3 </ id> <id> Nombre_4 </ id>''
SELECT ParamValues.ID.value (''.'', ''VARCHAR (10)'') FROM @ IdArray.nodes (''id'') AS ParamValues (ID)
Esto es un poco tarde, pero tuve este problema exacto hace un tiempo y encontré una solución.
El truco es hacer una cita doble y luego envolver toda la cadena entre comillas.
exec getSomething """John"",""Tom"",""Bob"",""Harry"""
Modifique su proc para que coincida con la entrada de la tabla a la cadena.
CREATE PROCEDURE getSomething @keyList varchar(4096)
AS
SELECT * FROM mytbl WHERE @keyList LIKE ''%''+name+''%''
He tenido esto en producción desde ASE 12.5; ahora estamos en 15.0.3.
Si usa Sybase 12.5 o una versión anterior, entonces no puede usar funciones. Una solución podría ser llenar una tabla temporal con los valores y leerlos desde allí.
Para ver lo que proporcionó @Abel, lo que me ayudó fue:
Mi propósito era tomar lo que sea que el usuario final ingresara de SSRS y usarlo en mi cláusula where como In (SELECT) Obviamente @ICD_VALUE_RPT se comentaría en mi consulta Dataset.
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>'')
luego en mi WHERE
agregué:
(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))
)