Tại sao các hàm có giá trị vô hướng cần thực thi quyền chứ không phải chọn?


15

Tôi tự hỏi tại sao, đối với hàm có giá trị vô hướng, tôi phải cấp cho người dùng thực thi thay vì chỉ chọn?

trong khi đó một hàm có giá trị bảng chỉ hoạt động tốt với chỉ quyền hoặc db_datareaderthành viên được chọn.

để rõ ràng hơn ở đây là ví dụ của tôi: Tôi cần một người dùng chỉ đọc quyền đối với cơ sở dữ liệu. Vì vậy, tôi đã tạo một người dùng được gọi testUservà cung cấp cho nó db_datareaderthành viên. sau đó tôi tạo ra một hàm có giá trị bảng gọi là fn_InlineTable. Và tất cả đều tuyệt vời. testUserchạy SQL này cả ngày

select * from dbo.fn_InlineTable

sau đó tôi cần một hàm vô hướng, vì vậy tôi đã tạo ra một hàm vô hướng được gọi là fn_ScalarTest. testUserkhông thể chạy SQL này

Select dbo.fn_ScalarTest(1) 

Cũng dễ hiểu: đó là vì tôi chưa cho phép "testUser" thực thi fn_ScalarTest.

Câu hỏi của tôi là: dựa trên liên kết này /programming/6150888/insert-update-delete-with-feft-in-sql-server , nói rằng FUNCTIONkhông thể sử dụng để thực hiện các hành động sửa đổi trạng thái cơ sở dữ liệu . Vậy tại sao không để một hàm vô hướng được sử dụng với cùng quyền "CHỌN" thay vì thực thi quyền ??

Tôi hy vọng câu hỏi của tôi có ý nghĩa. Cảm ơn bạn.

Câu trả lời:


15

Lý do chính rất có thể là các Hàm có giá trị bảng trả về Tập kết quả, giống như Bảng và dạng xem. Điều này có nghĩa rằng chúng có thể được sử dụng trong các FROMđiều khoản (bao gồm cả JOINs và APPLYs, vv) của SELECT, UPDATEDELETEtruy vấn. Tuy nhiên, bạn không thể sử dụng UDF vô hướng trong bất kỳ bối cảnh nào.

Thứ hai, bạn cũng có thể là EXECUTEmột UDF vô hướng. Cú pháp này khá tiện lợi khi bạn có các giá trị mặc định được chỉ định cho các tham số đầu vào. Lấy UDF sau, ví dụ:

CREATE FUNCTION dbo.OptionalParameterTest (@Param1 INT = 1, @Param2 INT = 2)
RETURNS INT
AS
BEGIN
    RETURN @Param1 + @Param2;
END;

Nếu bạn muốn coi bất kỳ tham số đầu vào nào là "tùy chọn", bạn vẫn cần chuyển DEFAULTtừ khóa khi gọi nó như một hàm vì chữ ký được cố định:

DECLARE @Bob1 INT;

SET @Bob1 = dbo.OptionalParameterTest(100, DEFAULT);

SELECT @Bob1;
-- Returns: 102

Mặt khác, nếu bạn EXECUTElà hàm, thì bạn có thể coi bất kỳ tham số nào có giá trị mặc định là thực sự tùy chọn, giống như bạn có thể với Thủ tục lưu trữ. Bạn có thể truyền vào n tham số đầu tiên mà không chỉ định tên tham số:

DECLARE @Bob2 INT;

EXEC @Bob2 = dbo.OptionalParameterTest 50;

SELECT @Bob2;
-- Returns: 52

Bạn thậm chí có thể bỏ qua tham số đầu tiên bằng cách chỉ định lại tên tham số, giống như với Thủ tục lưu trữ:

DECLARE @Bob3 INT;

EXEC @Bob3 = dbo.OptionalParameterTest @Param2 = 50;

SELECT @Bob3;
-- Returns: 51

CẬP NHẬT

Tại sao bạn có thể muốn sử dụng EXECcú pháp để gọi UDF vô hướng giống như Thủ tục được lưu trữ? Đôi khi, có những UDF rất tuyệt vời khi có UDF vì chúng có thể được thêm vào một truy vấn và hoạt động trên tập hợp các hàng được trả về, trong khi nếu mã nằm trong Quy trình được lưu trữ thì nó cần phải được đặt vào một con trỏ để lặp đi lặp lại trên một tập hợp các hàng. Nhưng sau đó, có những lúc bạn muốn gọi hàm đó trên một giá trị duy nhất, có thể từ bên trong một UDF khác. Gọi UDF cho một giá trị có thể được thực hiện như sau:

SELECT dbo.UDF('some value');

trong trường hợp bạn nhận được giá trị trả về trong tập kết quả (tập kết quả sẽ không hoạt động). Hoặc nó có thể được thực hiện như sau:

DECLARE @Dummy INT;

SET @Dummy = dbo.UDF('some value');

trong trường hợp bạn cần khai báo @Dummybiến;

TUY NHIÊN, với EXECcú pháp, bạn có thể tránh được cả hai điều phiền toái đó:

EXEC dbo.UDF 'some value';

CSONG, UDF vô hướng có kế hoạch thực thi của họ được lưu trữ. Điều này có nghĩa là có thể chạy vào các vấn đề đánh hơi tham số nếu có các truy vấn trong UDF có kế hoạch thực hiện. Đối với các kịch bản có thể sử dụng EXECcú pháp, thì cũng có thể sử dụng WITH RECOMPILEtùy chọn để bỏ qua các giá trị được biên dịch cho các thực thi đó . Ví dụ:

THIẾT LẬP:

GO
CREATE FUNCTION dbo.TestUDF (@Something INT)
RETURNS INT
AS 
BEGIN
   DECLARE @Ret INT;
   SELECT @Ret = COUNT(*)
   FROM   sys.indexes si
   WHERE  si.[index_id] = @Something;

   RETURN @Ret;
END;
GO

KIỂM TRA:

DECLARE @Val INT;

SET @Val = dbo.TestUDF(1);
SELECT @Val;

EXEC @Val = dbo.TestUDF 0 -- uses compiled value of (1)
SELECT @Val;

EXEC @Val = dbo.TestUDF 0 WITH RECOMPILE; -- uses compiled value of (0)
SELECT @Val;

EXEC @Val = dbo.TestUDF 3 -- uses compiled value of (1)
SELECT @Val;

4

Tôi nghĩ rằng sự khác biệt về quyền là bởi vì bạn thực sự có thể gọi các hàm do người dùng định nghĩa vô hướng với EXEC giống như các thủ tục được lưu trữ (điều mà tôi đã nhận ra cho đến khi tôi tìm hiểu về SQL Server 2000 Books Online, nơi họ đã giới thiệu các hàm do người dùng xác định) , nhưng bạn thực sự không thể chọn từ chúng làm nguồn bảng. Ví dụ:

DECLARE @date datetime
EXEC @date = dbo.first_day_of_month '8/14/2015'
SELECT @date

Trong trường hợp này, dbo.first_day_of_month là một hàm do người dùng định nghĩa. Tôi không biết tại sao bạn lại gọi hàm theo cách đó, nhưng tôi sẽ suy đoán rằng họ yêu cầu sự cho phép EXECUTE thay vì CHỌN để duy trì tính nhất quán. Ngày nay, nó có lẽ chỉ giữ hành lý tương thích.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.