2012-04-26 33 views
5

Tôi có mã sau đây, vấn đề là danh sách biến của tôi @LocationList về cơ bản là chuỗi csv. Khi tôi sử dụng này như là một phần của nơi LocationID trong (@LocationList) nó nói nó không phải là một int (LocationID là một int). Làm thế nào tôi có thể nhận được chuỗi csv này để được chấp nhận bởi teh trong khoản?Truy vấn SQL trong (@Variable)

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

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

thể trùng lặp của [SQL Server SP - Vượt qua tham số cho danh sách mảng "IN"?] (http://stackoverflow.com/questions/537087/sql-server-sp-pass-parameter-for-in-array-list) – Lamak

+0

Bạn đã cân nhắc sử dụng [Tham số giá trị bảng ] (http://msdn.microsoft.com/en-us/library/bb510489.aspx) thay thế. Nó sẽ làm cho nó 'chọn Địa điểm từ bảng nơi Vị tríID trong (Chọn Vị trí từ @LocationList)' –

Trả lời

5

Cách hiệu quả nhất để làm điều này là với Dynamic SQL như rt2800 đề cập (với lời cảnh báo tiêm Michael Allen)

Tuy nhiên bạn có thể làm cho một chức năng:

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 

và chọn từ nó:

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

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

HOẶC

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

Điều cực kỳ hữu ích khi bạn cố gắng gửi danh sách nhiều giá trị từ SSRS đến PROC.

+0

Xin lưu ý, bạn ** có thể ** cần truyền khi cần thiết – SQLMason

+0

Ah cũng là một ý tưởng hay, cảm ơn bạn –

0
declare @querytext Nvarchar(MAX) 

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

exec sp_executesql @querytext; 
+0

Rất gợi ý chống lại cách tiếp cận này, quá nhiều rủi ro cho tiêm sql. Nói chung tránh xa phương pháp exec, nó quá nguy hiểm. –

+0

@MichaelAllen Nó phụ thuộc vào cách danh sách của bạn được tạo ra, tuy nhiên bạn đang đúng về SQL injection và ** sp_executesql ** sẽ tốt hơn - vì nó thậm chí có thể cache kế hoạch thực hiện. – SQLMason

1

Tôi thường có yêu cầu này và SOMETIME, nếu bạn biết rõ cột bạn đang tìm kiếm [kích thước/định dạng/độ dài], bạn có thể thực hiện một loại REGEX.

Something như thế này:

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

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

LƯU Ý: nhân vật PIPE được sử dụng để bảo vệ các truy vấn từ trả lại bất kỳ LocationID có chứa một ký tự đơn (các '1', ví dụ).

Dưới đây là một ví dụ làm việc hoàn chỉnh:

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

CẢNH BÁO! Phương pháp này không thân thiện với Index!

Nếu bạn muốn làm thêm một số IN (@MyListOfLocation) trong tất cả những gì, để thúc đẩy sử dụng các chỉ số, bạn có thể sửa đổi kịch bản của bạn làm gì để:

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