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концепции здесь ... Мне нужно пойти и изменить все места сейчас.
— ЖЖ

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

9
Поскольку нам не разрешено наложение, и «default», таким образом, имеет ограниченное удобство использования, часто лучшим подходом будет создание новой расширенной версии с суффиксом (скажем, здесь CheckIfSFExistsEX) с дополнительными параметрами и изменение исходной функции на вызов расширенной версии с параметром "default". Таким образом, ВСЕ существующий код работает, и у вас есть только одно место для обслуживания.
— Эске Ран

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ключевое слово требуется в select, но может быть опущено в execute? Это отстой: / Надеюсь, это когда-нибудь будет исправлено.
— Мисью

@Misiu, это не то, что должно быть "исправлено". Это по замыслу. Я прочитал много альтернатив, чтобы приблизиться к «идеальной» цели - просто вызвать функцию без указания каждого аргумента, но я не видел четкого объяснения, почему это требуется. Код должен быть ясным, и одна стратегия для достижения этого требует, чтобы кодер всегда знал, что «эй, вы вызываете функцию, которая имеет этот и этот другие аргументы, которые имеют значения по умолчанию. Не забывайте, что значения по умолчанию МОГУТ БЫТЬ ИЗМЕНЕНЫ ". Итак, ИМО, это хорошая «плохая вещь», чтобы иметь.
— Густаво Пинсард

16

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

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

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

-1

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

exec sp_mysprocname @returnvalue output, @firstparam = 1, @ secondparam = 2

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


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

Правда, однако не все блоки кода должны вызываться из запроса. Было показано, что sql не имеет хорошего метода обработки значений по умолчанию для функций (использование ключевого слова по умолчанию - почти такая же работа, как и добавление значения). Это не очень хорошее общее решение, но оно отлично работает в определенных случаях.
— Джерем Гюнтер

Люди продолжают отмечать это, однако я придерживаюсь этого. Если у вас есть потребность в повторно используемом фрагменте кода, который не будет вызываться внутри запросов, и вы хотите гибкости истинных необязательных параметров со значениями по умолчанию, хранимая процедура все же лучше, чем функция.
— Джерем Гюнтер

1
Использование хранимых процедур не означает их использование вместо использования функции - это может означать использование хранимой процедуры в качестве оболочки вокруг функции. Я часто использую эту технику; ключевые слова по умолчанию теперь скрыты внутри процедуры. Я думаю, что эта идея просто отлично. Это также позволяет мне делать более сложные значения по умолчанию, если я хочу - отдельно от функции, которую можно оставить в более чистом состоянии.
— Джей Брайан Прайс
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.