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.