¿Cómo pasar una lista separada por comas a un procedimiento almacenado?

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

  •  08-06-2019
  •  | 
  •  

Pregunta

Entonces tengo un proceso almacenado en Sybase que toma 1 parámetro que es una lista de cadenas separadas por comas y ejecuta una consulta con una cláusula IN():

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

¿Cómo llamo a mi proceso 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

EDITAR: De hecho encontré esto página que tiene una gran referencia de las diversas formas de pasar una matriz a un sproc

¿Fue útil?

Solución

Si está utilizando Sybase 12.5 o una versión anterior, no podrá utilizar funciones.Una solución podría ser llenar una tabla temporal con los valores y leerlos desde allí.

Otros consejos

Esto es un poco tarde, pero tuve exactamente este problema hace un tiempo y encontré una solución.

El truco consiste en comillas dobles y luego envolver toda la cadena entre comillas.

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

Modifique su proceso para hacer coincidir la entrada de la tabla con 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.

Pase la lista separada por comas a una función que devuelva un valor de tabla.Hay un ejemplo de MS SQL en algún lugar de StackOverflow, maldita sea 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 poder hacer algo similar?

¿Necesita utilizar una lista separada por comas?En los últimos años, he tomado este tipo de ideas y las he pasado en un archivo XML.La "función" openxml toma una cadena y la convierte en xml y luego, si crea una tabla temporal con los datos, se puede consultar.

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))

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 de hace unos años.Funciona de maravilla.

Dividir texto en palabras en SQL

Este es un método rápido y sucio que puede resultar útil:

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

No estoy seguro si está en ASE, pero en SQL Anywhere, el sa_lista_dividida La función devuelve una tabla de un CSV.Tiene argumentos opcionales para pasar un delimitador diferente (el valor predeterminado es una coma) y una longitud máxima para cada valor devuelto.

función sa_split_list

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 sea '"John","Tom"'.

Si no quisiera usar una tabla temporal como en la respuesta de Paul, entonces podría usar SQL dinámico.(Se supone 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, incluso si son valores únicos.

Para comentar lo que proporcionó @Abel, lo que me ayudó fue:

Mi propósito era tomar lo que el usuario final ingresado desde las SSRS y usarlo en mi cláusula Where como un en (seleccionar) obviamente @ICD_VALUE_RPT se comentaría en mi consulta de conjunto de datos.

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>')

entonces en mi WHERE yo añadí:

(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))
)

Pruebe 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,','))

Esto funciona en SQL.Declara en tu GetSomething procedimiento una variable de tipo XML como tal:

DECLARE @NameArray XML = NULL

El cuerpo del procedimiento almacenado implementa lo siguiente:

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

Desde dentro del código SQL que llama al SP para declarar e inicializar la variable XML antes de llamar al procedimiento almacenado:

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>'

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:

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)
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top