Bạn có thể thực hiện điều này (nếu tôi hiểu bạn đang cố gắng làm gì) bằng cách sử dụng SQL động.
Bí quyết là bạn cần tạo một chuỗi chứa câu lệnh SQL. Đó là bởi vì tên bảng phải được chỉ định trong văn bản SQL thực, khi bạn thực thi câu lệnh. Tham chiếu bảng và tham chiếu cột không thể được cung cấp dưới dạng tham số, chúng phải xuất hiện trong văn bản SQL.
Vì vậy, bạn có thể sử dụng cách tiếp cận như sau:
SET @stmt = 'INSERT INTO @tmpTbl1 SELECT ' + @KeyValue
+ ' AS fld1 FROM tbl' + @KeyValue
EXEC (@stmt)
Đầu tiên, chúng ta tạo một câu lệnh SQL dưới dạng một chuỗi. Đưa ra @KeyValue của 'Foo', điều đó sẽ tạo ra một chuỗi chứa:
'INSERT INTO @tmpTbl1 SELECT Foo AS fld1 FROM tblFoo'
Tại thời điểm này, nó chỉ là một chuỗi. Nhưng chúng ta có thể thực thi nội dung của chuỗi, như một câu lệnh SQL động, bằng cách sử dụng EXECUTE
(hoặc EXEC
viết tắt).
Trường học cũ sp_executesql
thủ tục là một giải pháp thay thế cho EXEC, một cách khác để thực thi SQL dymamic, cũng cho phép bạn chuyển các tham số, thay vì chỉ định tất cả các giá trị dưới dạng các ký tự trong văn bản của câu lệnh.
THEO DÕI
EBarr chỉ ra (một cách chính xác và quan trọng) rằng cách tiếp cận này dễ bị SQL Injection.
Xem xét điều gì sẽ xảy ra nếu @KeyValue
chứa chuỗi:
'1 AS foo; DROP TABLE students; -- '
Chuỗi mà chúng tôi sẽ tạo ra dưới dạng một câu lệnh SQL sẽ là:
'INSERT INTO @tmpTbl1 SELECT 1 AS foo; DROP TABLE students; -- AS fld1 ...'
Khi chúng ta THỰC HIỆN chuỗi đó dưới dạng câu lệnh SQL:
INSERT INTO @tmpTbl1 SELECT 1 AS foo;
DROP TABLE students;
-- AS fld1 FROM tbl1 AS foo; DROP ...
Và nó không chỉ là một DROP TABLE có thể được đưa vào. Bất kỳ SQL nào cũng có thể được đưa vào, và nó có thể phức tạp hơn nhiều và thậm chí còn bất chính hơn. (Các cuộc tấn công đầu tiên có thể là cố gắng truy xuất thông tin về các bảng và cột, sau đó là các nỗ lực truy xuất dữ liệu (địa chỉ email, số tài khoản, v.v.)
Một cách để giải quyết lỗ hổng này là xác thực nội dung của @KeyValue, giả sử nó chỉ được chứa các ký tự chữ và số (ví dụ:kiểm tra bất kỳ ký tự nào không nằm trong các dải đó bằng cách sử dụng LIKE '%[^A-Za-z0-9]%'
. Nếu một ký tự không hợp lệ được tìm thấy, hãy từ chối giá trị và thoát mà không thực thi bất kỳ SQL nào.