T-SQL - функція з параметрами за замовчуванням


155

У мене є такий сценарій:

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

Я хочу використовувати його в процедурі таким чином:

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

Але я отримую помилку:

Для процедури або функції dbo.CheckIfSFExists було надано недостатньо аргументів.

Чому це не працює?

Відповіді:


227

ви повинні назвати це так

SELECT dbo.CheckIfSFExists(23, default)

Від Technet :

Коли параметр функції має значення за замовчуванням, під час виклику функції необхідно вказати ключове слово DEFAULT, щоб отримати значення за замовчуванням. Така поведінка відрізняється від використання параметрів із значеннями за замовчуванням у збережених процедурах, у яких пропускання параметра також передбачає значення за замовчуванням. Виняток з такої поведінки є при виклику скалярної функції за допомогою оператора EXECUTE. Під час використання EXECUTE ключове слово DEFAULT не потрібно.


80
Побачивши це, я засмучений. Я тут не отримую переваги від defaultконцепції ... Мені потрібно зараз і змінити всі місця.
LCJ

8
@Lijo, ви все одно отримуєте перевагу не дублювати конкретні значення за замовчуванням під час кожного дзвінка.
Фредерік

9
Оскільки нам не дозволяється накладати накладення, і, таким чином, "за замовчуванням" обмежена зручність використання, найчастіше найкращим підходом буде створення нової розширеної версії з суфіксом (скажімо тут CheckIfSFExistsEX) з додатковими параметрами та зміна вихідної функції на просто виклик розширеної версії параметром "за замовчуванням". Таким чином ВСІ існуючі коди працюють, і Ви маєте лише одне місце для обслуговування.
Eske Rahn

39

Ви можете назвати це трьома способами - з параметрами, за допомогою DEFAULT та через 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
Чому DEFAULTключове слово потрібне у виділенні, але його можна опустити при виконанні? Це відстійно: / Сподіваємось, це колись буде виправлено.
Misiu

@Misiu, це не те, що потрібно "виправити". Це за дизайном. Я прочитав багато альтернатив, щоб підійти до "ідеальної" мети - просто мати можливість викликати функцію, не вказуючи кожен аргумент, але я не побачив чіткого пояснення, чому це потрібно. Код повинен бути чітким, і для досягнення однієї стратегії, яка вимагає від кодера завжди усвідомлювати, що "ей, ти викликаєш функцію, у якої НЕ є цей та інші аргументи, які мають значення за замовчуванням. Не забувайте, що значення за замовчуванням МОЖЕ бути ЗМІНЕНО ". Отже, ІМО, це добре "погано".
Gustavo Pinsard

16

З визначеними користувачем функціями ви повинні оголосити кожен параметр, навіть якщо вони мають значення за замовчуванням.

Виконано наступне:

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

-1

Один із способів вирішення цієї проблеми - використання збережених процедур з вихідним параметром.

exec sp_mysprocname @returnvalue вихід, @firstparam = 1, @ secondparam = 2

значення, які ви не передаєте за замовчуванням до значень за замовчуванням, встановлених у самій збереженій процедурі. І ви можете отримати результати зі своєї вихідної змінної.


1
Зміна вашої функції на збережену процедуру, як правило, не є гарним рішенням, оскільки збережену процедуру не можна викликати із запиту, але функція може.
Лезо

Щоправда, проте не всі блоки коду потрібно викликати з запиту. Було показано, що sql не має хорошого методу обробки значень за замовчуванням для функцій (використання ключового слова за замовчуванням - це майже стільки ж роботи, скільки й додавання значення). Це не гарне загальне рішення, але воно чудово працює в певних випадках використання.
Jereme Guenther

Люди продовжують це відзначати, проте я це дотримуюся. Якщо у вас є необхідність мати багаторазовий фрагмент коду, який не буде викликаний всередині запитів, і ви хочете гнучкість справжніх необов'язкових параметрів із значеннями за замовчуванням, збережена процедура все ж краща, ніж функція.
Jereme Guenther

1
Використання збережених процедур не означає використання їх замість функції - це може означати використання збереженої процедури як обгортки навколо функції. Я часто використовую цю техніку; ключові слова за замовчуванням тепер приховані всередині proc. Я думаю, що ця ідея просто чудова. Це також дозволяє мені зробити складніші параметри за замовчуванням, якщо я хочу - окремо від функції, яку можна залишити в більш чистому стані.
Дж. Брайан Ціна
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.