T-SQL — функция с параметрами по умолчанию

У меня есть этот скрипт:

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 предоставлено недостаточное количество аргументов.

Почему это не работает?


person nirmus    schedule 02.12.2011    source источник


Ответы (4)


вы должны называть это так

SELECT dbo.CheckIfSFExists(23, default)

Из Technet:

Когда параметр функции имеет значение по умолчанию, при вызове функции необходимо указать ключевое слово DEFAULT, чтобы получить значение по умолчанию. Это поведение отличается от использования параметров со значениями по умолчанию в хранимых процедурах, в которых пропуск параметра также подразумевает значение по умолчанию. Исключением из этого поведения является вызов скалярной функции с помощью инструкции EXECUTE. При использовании EXECUTE ключевое слово DEFAULT не требуется.

person SQLMenace    schedule 02.12.2011
comment
Увидев это, я расстроен. Я не получаю преимуществ от концепции default здесь... Мне нужно пойти и поменять все места сейчас. - person LCJ; 13.09.2014
comment
@Lijo, вы по-прежнему получаете преимущество, заключающееся в том, что вы не дублируете свое конкретное значение по умолчанию при каждом вызове. - person Frédéric; 26.06.2015
comment
Поскольку нам не разрешено наложение, и, таким образом, значение по умолчанию имеет ограниченное удобство использования, часто лучшим подходом будет создание новой расширенной версии с суффиксом (скажем, CheckIfSFExistsEX здесь) с дополнительными параметрами и изменение исходной функции на простой вызов расширенная версия с параметром по умолчанию. Таким образом работает ВЕСЬ существующий код, и у вас есть только одно место для поддержки. - person Eske Rahn; 18.10.2018
comment
Угу Майкрософт. На самом деле это не необязательный параметр, если вам требуется передать ему значение. Я надеюсь, что они могут изменить это в будущей версии. - person Ben; 26.01.2021
comment
@Ben Согласен, но в свою защиту они не сказали, что это необязательный параметр. Это параметр со значением по умолчанию. Единственным преимуществом является то, что вызывающая функция не должна знать, какое значение установить для параметра. Я предполагаю, что они посчитали важным, чтобы вызывающий абонент подтвердил наличие параметра, т.е. отказался. Но я бы тоже предпочел необязательный параметр. - person xr280xr; 30.01.2021

Вызвать его можно тремя способами - с параметрами, с помощью 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
person Douglas Osborne    schedule 19.09.2013
comment
Почему ключевое слово DEFAULT требуется при выборе, но может быть опущено при выполнении? Это отстой :/ Надеюсь, это когда-нибудь будет исправлено. - person Misiu; 09.01.2019
comment
@Misiu, это не то, что нужно исправлять. Это по дизайну. Я читал много альтернатив, чтобы приблизиться к идеальной цели просто иметь возможность вызывать функцию без указания каждого аргумента, но я не видел четкого объяснения, почему это требуется. Код должен быть ясным, и одна из стратегий для достижения этого требует, чтобы кодер всегда знал, что, эй, вы вызываете функцию, которая ДЕЙСТВИТЕЛЬНО имеет этот и этот другие аргументы, которые имеют значения по умолчанию. Не забывайте, что значения по умолчанию МОГУТ БЫТЬ ИЗМЕНЕНЫ. Так что, имхо, это хорошо и плохо. - person Gustavo Pinsard; 17.07.2020

В пользовательских функциях вы должны объявлять каждый параметр, даже если он имеет значение по умолчанию.

Следующее будет успешно выполнено:

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

Один из способов обойти эту проблему — использовать хранимые процедуры с выходным параметром.

exec sp_mysprocname @returnvalue вывод, @firstparam = 1, @secondparam = 2

значения, которые вы не передаете по умолчанию, в значения по умолчанию, установленные в самой хранимой процедуре. И вы можете получить результаты из своей выходной переменной.

person Jereme Guenther    schedule 26.01.2017
comment
Замена вашей функции на хранимую процедуру, как правило, не является хорошим решением, потому что хранимую процедуру нельзя вызвать из запроса, а функцию можно. - person Blade; 28.06.2017
comment
Правда, однако не все блоки кода нужно вызывать из запроса. Было показано, что в sql нет хорошего метода обработки значений по умолчанию для функций (использование ключевого слова по умолчанию требует почти такой же работы, как добавление значения). Это не очень хорошее общее решение, но оно отлично работает в определенных случаях использования. - person Jereme Guenther; 28.06.2017
comment
Люди продолжают отмечать это, однако я придерживаюсь этого. Если вам нужен повторно используемый кусок кода, который не будет вызываться внутри запросов, и вам нужна гибкость настоящих необязательных параметров со значениями по умолчанию, хранимая процедура все же лучше, чем функция. - person Jereme Guenther; 01.10.2019
comment
Использование хранимых процедур не означает их использование вместо использования функции — это может означать использование хранимой процедуры в качестве оболочки вокруг функции. Я часто использую эту технику; ключевые слова по умолчанию теперь скрыты внутри процедуры. Я думаю, что эта идея просто прекрасна. Это также позволяет мне делать более сложные значения по умолчанию, если я хочу - отдельно от функции, которую можно оставить в более чистом состоянии. - person J Bryan Price; 04.12.2019