2012-04-26 20 views
5

Mam następujący kod, problem polega na tym, że moja lista zmiennych @LocationList jest w istocie ciągiem CSV. Kiedy używam tego jako części lokalizacji, gdzie LocationID znajduje się w (@LocationList), oznacza to, że nie jest int (LocationID jest int). Jak mogę uzyskać ciąg znaków CSV do zaakceptowania przez klauzulę?Zapytanie SQL w (@ Variable)

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

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

możliwe duplikat [SQL Server SP - Proszę przejść do parametru dla listy tablic "IN"?] (http://stackoverflow.com/questions/537087/sql-server-sp-pass-parameter-for-in-array-list) – Lamak

+0

Czy rozważałeś użycie parametru [Table-Value Parameter Zamiast tego (http://msdn.microsoft.com/en-us/library/bb510489.aspx). To sprawi, że 'wybierz Lokalizacje z tabeli gdzie Gdzie LocationID w (Wybierz lokalizację z @LocationList)' –

Odpowiedz

5

Najskuteczniejszym sposobem, aby to zrobić, to z dynamicznego SQL, takich jak wspomina rt2800 (z ostrzeżeniami wstrzykiwania Michael Allen)

Jednak można zrobić funkcję:

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 

i wybierz z niego:

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

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

LUB

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

co jest bardzo pomocne przy próbie wysłania listę wielu wartości z SSRS do PROC.

+0

Należy pamiętać, że ** może ** trzeba oddać w razie potrzeby – SQLMason

+0

Ah to także dobry pomysł, dziękuję –

0
declare @querytext Nvarchar(MAX) 

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

exec sp_executesql @querytext; 
+0

Wysoce sugerują przeciwko temu podejściu, zbyt duże ryzyko dla wtrysku sql. Generalnie trzymaj się z daleka od metody exec, to zbyt niebezpieczne. –

+0

@MichaelAllen To zależy od tego, jak generowana jest twoja lista, ale masz rację co do iniekcji SQL, a ** sp_executesql ** byłaby lepsza - może nawet buforować plan wykonania. – SQLMason

1

Często mam to wymaganie i SOMETIME, jeśli dobrze znasz kolumnę, której szukasz [rozmiar/format/długość], możesz zrobić rodzaj REGEX.

coś takiego:

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

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

UWAGA: postać rury jest używany do ochrony zapytania z powrotem żadnej LocationID zawierający pojedynczy znak („1”, na przykład).

Powyżej znajduje się pełna przykład praca:

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

UWAGA! Ta metoda nie jest przyjazna dla indeksu!

Jeśli chcesz sumują Niektórzy (@MyListOfLocation) we wszystkich, że aby wykorzystać wykorzystanie indeksów, można zmodyfikować skrypt zrobić:

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