T-SQL - chức năng với các tham số mặc định


155

Tôi có kịch bản này:

CREATE FUNCTION dbo.CheckIfSFExists(@param1 INT, @param2 BIT = 1 )
RETURNS BIT
AS
BEGIN
    IF EXISTS ( bla bla bla )
        RETURN 1;
    RETURN 0;
END
GO

Tôi muốn sử dụng nó trong một thủ tục theo cách này:

IF dbo.CheckIfSFExists( 23 ) = 0
    SET @retValue = 'bla bla bla';

Nhưng tôi nhận được lỗi:

Không đủ số lượng đối số được cung cấp cho thủ tục hoặc hàm dbo.Check IfSFExists.

Tại sao nó không hoạt động?

Câu trả lời:


227

bạn phải gọi nó như thế này

SELECT dbo.CheckIfSFExists(23, default)

Từ Technet :

Khi một tham số của hàm có giá trị mặc định, từ khóa DEFAULT phải được chỉ định khi hàm được gọi để truy xuất giá trị mặc định. Hành vi này khác với việc sử dụng các tham số có giá trị mặc định trong các thủ tục được lưu trữ trong đó bỏ qua tham số cũng bao hàm giá trị mặc định. Một ngoại lệ cho hành vi này là khi gọi hàm vô hướng bằng cách sử dụng câu lệnh EXECUTE. Khi sử dụng EXECUTE, từ khóa DEFAULT là không bắt buộc.


79
Nhìn thấy điều này tôi thất vọng. Tôi không nhận được lợi thế của defaultkhái niệm ở đây ... Tôi cần phải đi và thay đổi tất cả các địa điểm bây giờ.
LCJ

8
@Lijo, bạn vẫn có được lợi thế là không sao chép giá trị mặc định cụ thể của mình tại mỗi cuộc gọi.
Frédéric

9
Vì chúng tôi không được phép phủ và do đó "mặc định" đã hạn chế khả năng sử dụng, nên cách tiếp cận tốt nhất sẽ là tạo một phiên bản mở rộng mới với hậu tố (giả sử Check IfSFExistsEX tại đây) với các tham số bổ sung và thay đổi chức năng ban đầu thành gọi phiên bản mở rộng với tham số "mặc định". Bằng cách này TẤT CẢ mã hiện có hoạt động và bạn chỉ có một nơi để duy trì.
Eske Rahn

39

Bạn có thể gọi nó theo ba cách - với các tham số, với DEFAULT và thông qua EXECUTE

SET NOCOUNT ON;

DECLARE
@Table  SYSNAME = 'YourTable',
@Schema SYSNAME = 'dbo',
@Rows   INT;

SELECT dbo.TableRowCount( @Table, @Schema )

SELECT dbo.TableRowCount( @Table, DEFAULT )

EXECUTE @Rows = dbo.TableRowCount @Table

SELECT @Rows

11
Tại sao DEFAULTtừ khóa được yêu cầu trong chọn, nhưng có thể được bỏ qua trong thực thi? Điều này thật tệ: / Hy vọng điều này sẽ được khắc phục vào một ngày nào đó.
Misiu

@Misiu, nó không phải là thứ cần được "sửa". Đó là do thiết kế. Tôi đã đọc rất nhiều lựa chọn thay thế để tiếp cận mục tiêu "lý tưởng" chỉ đơn giản là có thể gọi một hàm mà không chỉ định mọi đối số, nhưng tôi không thấy một lời giải thích rõ ràng về lý do tại sao điều đó là bắt buộc. Mã phải rõ ràng và một chiến lược để đạt được đó là yêu cầu người viết mã phải luôn ý thức rằng "này, bạn đang gọi một hàm DOES có điều này và các đối số khác, điều đó xảy ra có các giá trị mặc định. Đừng quên rằng giá trị mặc định CÓ THỂ THAY ĐỔI ". Vì vậy, IMO, đây là một "điều xấu" tốt.
Gustavo Pinsard

16

Với các hàm do người dùng xác định, bạn phải khai báo mọi tham số, ngay cả khi chúng có giá trị mặc định.

Sau đây sẽ thực hiện thành công:

IF dbo.CheckIfSFExists( 23, default ) = 0
    SET @retValue = 'bla bla bla;

-1

Một cách xung quanh vấn đề này là sử dụng các thủ tục được lưu trữ với một tham số đầu ra.

exec sp_mysprocname @returnvalue đầu ra, @firstparam = 1, @ secondparam = 2

các giá trị bạn không chuyển mặc định cho các giá trị mặc định được đặt trong chính thủ tục được lưu trữ. Và bạn có thể nhận được kết quả từ biến đầu ra của bạn.


1
Thay đổi chức năng của bạn thành một thủ tục được lưu trữ nói chung không phải là một giải pháp tốt, bởi vì một thủ tục được lưu trữ có thể được gọi từ trong một truy vấn, nhưng một hàm có thể.
Lưỡi dao

Đúng, tuy nhiên không phải tất cả các khối mã cần được gọi từ trong một truy vấn. Nó đã được chỉ ra rằng sql không có một phương pháp tốt để xử lý các giá trị mặc định cho các hàm (sử dụng từ khóa mặc định gần như là nhiều công việc như thêm một giá trị). Nó không phải là một giải pháp chung tốt, nhưng nó hoạt động rất tốt trong một số trường hợp sử dụng nhất định.
Jereme Guenther

Mọi người tiếp tục đánh dấu điều này xuống, tuy nhiên tôi vẫn gắn bó với nó. Nếu bạn có nhu cầu có một đoạn mã có thể sử dụng lại, nó sẽ không được gọi bên trong các truy vấn và bạn muốn tính linh hoạt của các tham số tùy chọn thực với các giá trị mặc định, một thủ tục được lưu trữ vẫn tốt hơn một hàm.
Jereme Guenther

1
Sử dụng các thủ tục được lưu trữ không có nghĩa là sử dụng chúng thay vì sử dụng một hàm - nó có thể có nghĩa là sử dụng thủ tục được lưu trữ như một trình bao bọc xung quanh một hàm. Tôi sử dụng kỹ thuật này thường xuyên; các từ khóa mặc định hiện được ẩn bên trong Proc. Tôi nghĩ ý tưởng này là tốt Nó cũng cho phép tôi thực hiện các mặc định phức tạp hơn nếu tôi muốn - tách biệt khỏi chức năng, có thể để ở trạng thái tinh khiết hơn.
J Bryan Giá
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.