2008-08-08 33 views
16

Así que tengo un procedimiento almacenado Sybase que tiene 1 parámetro que es una lista separada por comas de cadenas y se ejecuta una consulta con en en un() cláusula IN:¿Cómo pasar una lista separada por comas a un procedimiento almacenado?

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

Como llamar en mi procedimiento almacenado con más de 1 valor en la lista? Hasta ahora 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: De hecho, encontré este page que tiene una gran referencia de las diversas formas de pas una matriz a un procedimiento almacenado

+0

Espero que haya encontrado un método que funcione para usted. La página vinculada es una buena lista de opciones, ¡pero me alegra ver que la mayoría ya se sugirieron aquí! Paul sugirió el método 2/3, tablas temporales. Sugerí el método 1, sql dinámico. Brian y Abel sugieren un método XML, aunque no tengo licencia para xml en sybase, así que no sé si funcionará en Sybase. Similar al Método 4. – AdamH

+0

posible duplicado de [Parametrización de una cláusula SQL IN?] (Http://stackoverflow.com/questions/337704/parameterizing-an-sql-in-clause) – icc97

Respuesta

3

Si utiliza Sybase 12.5 o anterior, entonces no puede utilizar las funciones. Una solución podría ser llenar una tabla temporal con los valores y leerlos desde allí.

0

¿Es necesario utilizar una coma lista separada? 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)) 
1

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 StackOverflow, maldito si puedo verlo en este momento.

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

llamada con -

exec getSomething 'John,Tom,Foo,Bar' 

Supongo Sybase debe ser capaz de hacer algo similar?

0

En cuanto 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

Splitting Text into Words in SQL

0

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

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

No está seguro de si está en ASE, pero en SQL Anywhere, la funciónsa_split_list devuelve una tabla de un archivo CSV. Tiene argumentos opcionales para pasar un delimitador diferente (por defecto es una coma) y una longitud máxima para cada valor devuelto.

sa_split_list function

0

El problema con las llamadas como esta: getSomething ejecutivo de 'Juan ", 'Tom'' es que se está tratando 'Juan", 'Tom'' como una sola cadena, que lo hará único partido una entrada en la tabla que es '' John '', 'Tom' '.

Si no desea utilizar una tabla temporal como en la respuesta de Paul, puede 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) 

Usted tendrá que asegurarse que los artículos en @keylist tienen comillas alrededor de ellos, incluso si son valores individuales.

0

Esto funciona en SQL. Declarar en su procedimiento GetSomething una variable de tipo XML como tal:

DECLARE @NameArray XML = NULL

El cuerpo del procedimiento almacenado implementa los siguientes:

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

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

DECLARE @NameArray XML

SET @NameArray = '< id> name_1 </id> < id> NAME_2 </id> < id> NAME_3 </id> < id> Name_4 </id>'

Usando su ejemplo la llamada al procedimiento almacenado sería:

EXEC GetSomething @NameArray

He utilizado este método antes y funciona bien. Si desea una prueba rápida, copia y pega el código siguiente para una nueva consulta y ejecute:

DECLARE @IdArray XML

SET @IdArray = '< id> NAME_1 </id> ID < > NAME_2 </id> < id> NAME_3 </id> < id> Name_4 </id> '

SELECT ParamValues.ID.value ('. '' VARCHAR (10) ') DE @IdArray. nodes ('id') AS ParamValues ​​(ID)

2

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

El truco es la 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.

+1

Es posible que desee examinar eso ... Si tiene a Jack en la mesa y busca a Jackie, en realidad obtendrá a Jack :) Además, probablemente no sea terriblemente eficiente, creando una cadena para cada fila de la tabla. – JanHudecek

0

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

Mi propósito era tomar lo que cada vez que el usuario final introduce desde SSRS y el uso que en mi cláusula where como A (SELECCIONAR) Obviamente @ICD_VALUE_RPT se comentaría en mi consulta de 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>') 

entonces en mi WHERE 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)) 
) 
0

probar este camino. 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,',')) 
Cuestiones relacionadas