2012-04-26 25 views
5

Tengo el siguiente código, el problema es que mi lista de variables @LocationList es esencialmente una cadena csv. Cuando uso esto como parte de where ID de ubicación en (@LocationList) dice que no es un int (LocationID es un int). ¿Cómo puedo obtener esta cadena csv para ser aceptada por la cláusula teh in?SQL en consulta (@Variable)

Declare @LocationList varchar(1000) 
Set @LocationList = '1,32' 

select Locations from table where Where LocationID in (@LocationList) 
+1

posible duplicado de [SP de SQL Server - Pase de parámetros para la lista de arreglos "IN"?] (http://stackoverflow.com/questions/537087/sql-server-sp-pass-parameter-for-in-array-list) – Lamak

+0

¿Ha considerado usar un [Parámetro de valor de tabla ] (http://msdn.microsoft.com/en-us/library/bb510489.aspx) en su lugar. Lo haría 'seleccionar Ubicaciones de la tabla donde Where ID de ubicación en (Seleccionar ubicación de @LocationList) ' –

Respuesta

5

La forma más eficaz de hacerlo es con SQL dinámico como menciona rt2800 (con advertencias de inyección de Michael Allen)

Sin embargo, puede hacer una función:

ALTER FUNCTION [dbo].[CSVStringsToTable_fn] (@array VARCHAR(8000)) 
RETURNS @Table TABLE (value VARCHAR(100)) 
AS 
    BEGIN 
     DECLARE @separator_position INTEGER, 
      @array_value VARCHAR(8000) 

     SET @array = @array + ',' 

     WHILE PATINDEX('%,%', @array) <> 0 
      BEGIN 
       SELECT @separator_position = PATINDEX('%,%', @array) 
       SELECT @array_value = LEFT(@array, @separator_position - 1) 

       INSERT @Table 
       VALUES (@array_value) 

       SELECT @array = STUFF(@array, 1, @separator_position, '') 
      END 
     RETURN 
    END 

y seleccionar de él:

DECLARE @LocationList VARCHAR(1000) 
SET @LocationList = '1,32' 

SELECT Locations 
FROM table 
WHERE LocationID IN (SELECT * 
          FROM  dbo.CSVStringsToTable_fn(@LocationList)) 

O

SELECT Locations 
FROM table loc 
     INNER JOIN dbo.CSVStringsToTable_fn(@LocationList) list 
      ON list.value = loc.LocationID 

que es extremadamente útil cuando se intenta enviar una lista de valores múltiples de SSRS a un PROC.

+0

Tenga en cuenta que ** puede ** necesitar emitir según sea necesario – SQLMason

+0

Ah, eso es una buena idea también, gracias –

0
declare @querytext Nvarchar(MAX) 

set @querytext = 'select Locations from table where Where LocationID in (' + @LocationList + ');'; 

exec sp_executesql @querytext; 
+0

Sugerir altamente en contra de este enfoque, demasiado riesgo para la inyección sql. En general, manténgase alejado del método de ejecución, es demasiado peligroso. –

+0

@MichaelAllen Depende de cómo se genere su lista; sin embargo, tiene razón acerca de la inyección SQL y ** sp_executesql ** sería mejor, ya que incluso puede almacenar en caché el plan de ejecución. – SQLMason

1

A menudo tengo este requisito, y SOMETIME, si conoce muy bien la columna que está buscando en [el tamaño/formato/longitud], puede hacer una especie de REGEX.

Algo como esto:

DECLARE @MyListOfLocation varchar(255) 
    set @MyListOfLocation = '|1|32|36|24|3|' 

    Select LocationID 
    from Table 
    where @MyListOfLocation like '%|' + LocationID + '|%' 

NOTA: el carácter de barra vertical se utiliza para proteger la consulta de devolver cualquier LocationID que contiene un único carácter (el '1', por ejemplo).

Aquí es un ejemplo de trabajo completo:

DECLARE @MyListOfLocation varchar(255) 
set @MyListOfLocation = '|1|11|21|' 

SELECT LocationName 
FROM (
     select '1' as LocationID, 'My Location 1' as LocationName 
     union all 
     select '11' as LocationID, 'My Location 11' as LocationName 
     union all 
     select '12' as LocationID, 'My Location 12' as LocationName 
     union all 
     select '13' as LocationID, 'My Location 13' as LocationName 
     union all 
     select '21' as LocationID, 'My Location 21' as LocationName 
    ) as MySub 
where @MyListOfLocation like '%|' + LocationID + '|%' 

ADVERTENCIA! ¡Este método no es amigable con el índice!

Si no desea añadir un poco de IN (@MyListOfLocation) en todo lo que, para aprovechar el uso de los índices, puede modificar la secuencia de comandos para hacer:

SELECT MyDATA.* 
FROM HugeTableWithAnIndexOnLocationID as MyDATA 
WHERE LocationID in (
     Select LocationID 
     from Table 
     where @MyListOfLocation like '%|' + LocationID + '|%')