15

Tôi đã viết hai thủ tục lưu trữ một với sp_executesql và khác không có sp_executesql cả hai đều thực hiện kết quả đúng như vậy, tôi đã không nhận được sự khác biệt ở đây là gì giữaThủ tục lưu trữ EXEC vs sp_executesql khác biệt?

EXEC (@SQL) vs EXEC sp_executesql @SQL, N '@ eStatus varchar (12)', @eStatus = @Status

và như thế nào EXEC (@SQL) là dễ bị SQL injection và @SQL sp_executesql ...... isn 't?

Dưới Stored Procedure mà không sp_executesql

ALTER proc USP_GetEmpByStatus 
(
@Status varchar(12) 
) 
AS 
BEGIN 
DECLARE @TableName AS sysname = 'Employee' 
Declare @Columns as sysname = '*' 
DECLARE @SQL as nvarchar(128) = 'select ' + @Columns + ' from ' + @TableName + ' where Status=' + char(39) + @Status + char(39) 
print (@SQL) 
EXEC (@SQL) 
END 

EXEC USP_GetEmpByStatus 'Active' 

Dưới thủ tục lưu trữ với sp_executesql

create proc USP_GetEmpByStatusWithSpExcute 
(
@Status varchar(12) 
) 
AS 
BEGIN 
DECLARE @TableName AS sysname = 'JProCo.dbo.Employee' 
Declare @Columns as sysname = '*' 
DECLARE @SQL as nvarchar(128) = 'select ' + @Columns + ' from ' + @TableName + ' where Status=' + char(39) + @Status + char(39) 
print @SQL 
exec sp_executesql @SQL, N'@eStatus varchar(12)', @eStatus = @Status 
END 

EXEC USP_GetEmpByStatusWithSpExcute 'Active' 
+4

WHOA !!! Ngừng mã hóa SQL injection đã! Mỗi khi bạn gọi sp_executesql, bạn có khả năng cho phép mọi hacker trên máy chủ của bạn truy cập Internet. – SecurityMatt

Trả lời

12

sp_executesql SQL của bạn có thể là;

DECLARE @SQL as nvarchar(128) = 'select ' + @Columns + ' from ' + 
      @TableName + ' where [email protected]' 

Điều này sẽ cho phép bạn gọi sp_executesql với @eStatus làm thông số thay vì nhúng nó vào SQL. Điều đó sẽ mang lại lợi thế mà @eStatus có thể chứa bất kỳ ký tự nào và nó sẽ được cơ sở dữ liệu tự động thoát đúng cách nếu được yêu cầu bảo mật.

Tương phản với SQL được yêu cầu cho EXEC;

DECLARE @SQL as nvarchar(128) = 'select ' + @Columns + ' from ' + 
      @TableName + ' where Status=' + char(39) + @Status + char(39) 

... trong đó một char (39) được nhúng trong @Status sẽ làm cho SQL của bạn không hợp lệ và có thể tạo khả năng chèn SQL. Ví dụ: nếu @Status được đặt thành O'Reilly, thì kết quả SQL của bạn sẽ là;

select acol,bcol,ccol FROM myTable WHERE Status='O'Reilly' 
+0

Tại sao mệnh đề không được đính kèm với '''? –

+0

@ user1095881 Nếu bạn đính kèm @eStatus với dấu ngoặc kép, nó sẽ sử dụng _string_ '@eStatus' để tìm kiếm trong cơ sở dữ liệu, nếu bạn sử dụng một dấu @ unStatus, _value_ sẽ được sử dụng. Ví dụ, nếu @eStatus là 'test', một 'INSERT INTO myTable VALUES (@eStatus)' sẽ chèn chuỗi 'test', trong khi 'INSERT INTO myTable VALUES ('@eStatus')' sẽ chèn chuỗi '@eStatus '. –

+0

Tôi nghĩ rằng điều này thiếu một '' 'đóng trong ví dụ mã đầu tiên. – Sam

4

Với sp_executesql, bạn không cần phải xây dựng truy vấn của bạn như thế. Bạn có thể khai báo nó như thế này:

DECLARE @SQL as nvarchar(128) = 'select ' + @Columns + ' from ' + 
@TableName + ' where [email protected]' 

cách này, nếu giá trị @Status của bạn xuất thân từ một người dùng mà bạn có thể sử dụng @eStatus và không phải lo lắng về việc thoát '. sp_executesql cung cấp cho bạn khả năng đặt các biến trong truy vấn của bạn dưới dạng chuỗi, thay vì sử dụng nối. Vì vậy, bạn có ít hơn để lo lắng về.

Biến cột và bảng vẫn giữ nguyên, nhưng ít có khả năng là trực tiếp từ người dùng.

11

Bên cạnh việc sử dụng, có một số khác biệt quan trọng:

  1. sp_executesql cho phép báo cáo là tham số Do đó Đó là an toàn hơn EXEC về SQL injection

  2. sp_executesql thể thúc đẩy kế hoạch truy vấn được lưu trong bộ nhớ cache. Chuỗi TSQL được xây dựng chỉ có một thời gian, sau đó mỗi lần cùng một truy vấn được gọi với sp_executesql, SQL Server lấy kế hoạch truy vấn từ bộ nhớ cache và tái sử dụng nó

  3. bảng Temp tạo ra trong EXEC không thể sử dụng cơ chế tạm thời bảng bộ nhớ đệm

+0

Sự khác biệt thứ hai là quan trọng nhất imo (và câu trả lời upvoted cao thậm chí không đề cập đến nó). +1 – sotn

+0

Cảm ơn bạn đã đề cập – FLICKER

1

Với Exec bạn không thể có một người giữ nơi trong chuỗi câu lệnh T-SQL của bạn.

sp_executesql mang đến cho bạn những lợi thế của việc có một giữ chỗ và vượt qua giá trị thực tế tại thời gian chạy

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