Sqlserver
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> Sqlserver

Tham số hóa một mệnh đề SQL IN

Bạn có thể tham số hóa từng giá trị, vì vậy một cái gì đó như:

string[] tags = new string[] { "ruby", "rails", "scruffy", "rubyonrails" };
string cmdText = "SELECT * FROM Tags WHERE Name IN ({0})";

string[] paramNames = tags.Select(
    (s, i) => "@tag" + i.ToString()
).ToArray();

string inClause = string.Join(", ", paramNames);
using (SqlCommand cmd = new SqlCommand(string.Format(cmdText, inClause))) {
    for(int i = 0; i < paramNames.Length; i++) {
       cmd.Parameters.AddWithValue(paramNames[i], tags[i]);
    }
}

Cái nào sẽ mang lại cho bạn:

cmd.CommandText = "SELECT * FROM Tags WHERE Name IN (@tag0, @tag1, @tag2, @tag3)"
cmd.Parameters["@tag0"] = "ruby"
cmd.Parameters["@tag1"] = "rails"
cmd.Parameters["@tag2"] = "scruffy"
cmd.Parameters["@tag3"] = "rubyonrails"

Không, điều này không mở cho SQL injection. Văn bản duy nhất được chèn vào CommandText không dựa trên đầu vào của người dùng. Nó chỉ dựa trên tiền tố "@tag" được mã hóa cứng và chỉ mục của một mảng. Chỉ mục sẽ luôn luôn là một số nguyên, không phải do người dùng tạo và an toàn.

Các giá trị do người dùng nhập vẫn được nhồi vào các tham số, vì vậy không có lỗ hổng ở đó.

Chỉnh sửa:

Bỏ qua mối quan tâm về tiêm, hãy cẩn thận lưu ý rằng việc xây dựng văn bản lệnh để chứa một số lượng biến các tham số (như ở trên) cản trở khả năng của máy chủ SQL trong việc tận dụng các truy vấn được lưu trong bộ nhớ cache. Kết quả cuối cùng là bạn gần như chắc chắn mất giá trị của việc sử dụng các tham số ngay từ đầu (trái ngược với việc chỉ chèn các chuỗi vị từ vào chính SQL).

Không phải là các kế hoạch truy vấn được lưu trong bộ nhớ cache không có giá trị, nhưng IMO truy vấn này gần như không đủ phức tạp để thấy được nhiều lợi ích từ nó. Mặc dù chi phí biên dịch có thể tiếp cận (hoặc thậm chí vượt quá) chi phí thực thi, bạn vẫn đang nói chuyện mili giây.

Nếu bạn có đủ RAM, tôi hy vọng SQL Server có thể cũng sẽ lưu vào bộ đệm một kế hoạch cho số lượng thông số phổ biến. Tôi cho rằng bạn luôn có thể thêm năm tham số và để các thẻ không xác định là NULL - kế hoạch truy vấn phải giống nhau, nhưng nó có vẻ khá xấu đối với tôi và tôi không chắc rằng nó xứng đáng với việc tối ưu hóa vi mô (mặc dù, trên Stack Overflow - nó có thể rất đáng giá).

Ngoài ra, SQL Server 7 trở lên sẽ tự động tham số hóa các truy vấn, do đó, việc sử dụng các tham số không thực sự cần thiết từ quan điểm hiệu suất - tuy nhiên, nó là quan trọng từ quan điểm bảo mật - đặc biệt là với dữ liệu do người dùng nhập như thế này.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Tìm hiểu Hệ điều hành SQL Server đang chạy (Ví dụ T-SQL)

  2. Làm cách nào để tôi có được một Kế hoạch Thực thi Truy vấn trong SQL Server?

  3. Cách chuyển đổi số nguyên thành số thập phân trong SQL Server

  4. Cách thích hợp để triển khai ràng buộc duy nhất cho phép nhiều giá trị NULL trong SQL Server

  5. Chuyển đổi ‘datetimeoffset’ thành ‘datetime2’ trong SQL Server (Ví dụ T-SQL)