2008-09-18 31 views
10

Chúng ta đều biết rằng các câu lệnh chuẩn bị là một trong những cách tốt nhất để chống lại các cuộc tấn công SQL injection. Cách tốt nhất để tạo một câu lệnh chuẩn bị với mệnh đề "IN" là gì. Có cách nào dễ dàng để thực hiện việc này với số giá trị không xác định không? Lấy ví dụ sau.Xử lý dữ liệu trong mệnh đề IN, với các tham số SQL?

SELECT ID,Column1,Column2 FROM MyTable WHERE ID IN (1,2,3) 

Hiện tại tôi đang sử dụng vòng lặp trên các giá trị có thể để tạo chuỗi như.

SELECT ID,Column1,Column2 FROM MyTable WHERE ID IN (@IDVAL_1,@IDVAL_2,@IDVAL_3) 

Có thể sử dụng chỉ chuyển một mảng làm giá trị của tham số truy vấn và sử dụng truy vấn như sau không?

SELECT ID,Column1,Column2 FROM MyTable WHERE ID IN (@IDArray) 

Trong trường hợp điều quan trọng Tôi đang làm việc với SQL Server 2000, trong VB.Net

+0

thêm thẻ SQLServer – MotoWilliams

+0

thẻ t-sql cũng có thể thích hợp. –

Trả lời

1

Nếu bạn muốn vượt qua một mảng là, bạn sẽ cần một chức năng trong sql có thể biến mảng đó vào một phụ chọn.

Các chức năng này rất phổ biến và hầu hết các hệ thống trồng tại nhà đều tận dụng chúng.

Hầu hết các ORM thương mại hoặc chuyên nghiệp đều làm bằng cách thực hiện một loạt các biến, vì vậy nếu bạn làm việc đó, tôi nghĩ đó là phương pháp chuẩn.

-1

Trong SQL Server 2008, cuối cùng họ đã giải quyết vấn đề cổ điển này bằng cách thêm kiểu dữ liệu "bảng" mới. Rõ ràng, điều đó cho phép bạn chuyển vào một mảng các giá trị, có thể được sử dụng trong một lựa chọn con để thực hiện giống như một câu lệnh IN.

Nếu bạn đang sử dụng SQL Server 2008, thì bạn có thể xem xét điều đó.

+0

"Trong trường hợp điều quan trọng là tôi đang làm việc với SQL Server 2000" – digiguru

5

Ở đây bạn đi - lần đầu tiên tạo ra các chức năng sau đây ...

Create Function [dbo].[SeparateValues] 
(
    @data VARCHAR(MAX), 
    @delimiter VARCHAR(10) 
) 
    RETURNS @tbldata TABLE(col VARCHAR(10)) 
As 
Begin 
    DECLARE @pos INT 
    DECLARE @prevpos INT 

    SET @pos = 1 
    SET @prevpos = 0 

    WHILE @pos > 0 
     BEGIN 

     SET @pos = CHARINDEX(@delimiter, @data, @prevpos+1) 

     if @pos > 0 
     INSERT INTO @tbldata(col) VALUES(LTRIM(RTRIM(SUBSTRING(@data, @prevpos+1, @[email protected])))) 

     else 

     INSERT INTO @tbldata(col) VALUES(LTRIM(RTRIM(SUBSTRING(@data, @prevpos+1, len(@data)[email protected])))) 

     SET @prevpos = @pos 
    End 

    RETURN 

END 

sau đó sử dụng sau đây ...

Declare @CommaSeparated varchar(50) 
Set @CommaSeparated = '112,112,122' 
SELECT ID,Column1,Column2 FROM MyTable WHERE ID IN (select col FROM [SeparateValues](@CommaSeparated, ',')) 

Tôi nghĩ sql server 2008 sẽ cho phép chức năng bảng.

CẬP NHẬT

Bạn sẽ bóp một số hiệu năng cao hơn bằng cách sử dụng cú pháp sau ...

SELECT ID,Column1,Column2 FROM MyTable 
Cross Apply [SeparateValues](@CommaSeparated, ',') s 
Where MyTable.id = s.col 

Bởi vì cú pháp trước đó gây ra SQL Server để chạy thêm "Sắp xếp" lệnh sử dụng " IN "khoản. Plus - theo ý kiến ​​của tôi trông đẹp hơn: D!

+0

Điều này giải quyết được giải pháp, như cung cấp cho bạn một hàm tốt để tạo bảng từ danh sách của bất kỳ giá trị được tách riêng nào bạn muốn - tại sao bỏ phiếu xuống? – digiguru

+0

Tôi đã bỏ phiếu cho bạn. Đây là giải pháp mà chúng tôi sử dụng. Làm việc với SQL 2000 và khái niệm là dễ dàng cho các thành viên trong nhóm cơ sở để nắm bắt. Nếu có thể, tôi sẽ bầu bạn lên 5 điểm. Tôi đã nhìn thấy kỹ thuật này được mô tả trong bài viết và trong bài viết. Giải pháp này cũng hoạt động tốt với Dịch vụ báo cáo SQL. –

+0

Tuyệt vời, cảm ơn! – Jaxedin

-2

Dưới đây là một kỹ thuật tôi sử dụng

ALTER Procedure GetProductsBySearchString 
@SearchString varchar(1000), 
as 
set nocount on 
declare @sqlstring varchar(6000) 
select @sqlstring = 'set nocount on 
select a.productid, count(a.productid) as SumOf, sum(a.relevence) as CountOf 
from productkeywords a 
where rtrim(ltrim(a.term)) in (''' + Replace(@SearchString,' ', ''',''') + ''') 
group by a.productid order by SumOf desc, CountOf desc' 

exec(@sqlstring) 
+0

Thực hiện chuỗi sql là một cách rất nguy hiểm để thực hiện mọi thứ trong môi trường sản xuất. – digiguru

0

Bạn có thể tạo một temptable bảng tạm thời với một giá trị cột đơn và chèn tất cả các ID. Sau đó, bạn có thể làm điều đó với một lựa chọn phụ:

SELECT ID,Column1,Column2 FROM MyTable WHERE ID IN (SELECT VALUE FROM TempTable) 
0

Đi với giải pháp được đăng bởi digiguru. Đó là một giải pháp tái sử dụng tuyệt vời và chúng tôi cũng sử dụng kỹ thuật tương tự. Các thành viên trong nhóm mới yêu thích nó, vì nó giúp tiết kiệm thời gian và giữ các quy trình được lưu trữ của chúng tôi nhất quán.Các giải pháp cũng hoạt động tốt với các báo cáo SQL, như các tham số được truyền cho các thủ tục lưu trữ để tạo ra các recordsets vượt qua trong varchar (8000). Bạn chỉ cần móc nó lên và đi.

Các vấn đề liên quan