У меня есть хранимая процедура, которая выглядит так:
CREATE FUNCTION [my_schema].[isEligible]
(@product NUMERIC(8))
RETURNS INT
AS
BEGIN
DECLARE @result INT;
/* do eligibility checking, setting @result */
RETURN @result;
END;
Это упоминается в нескольких существующих запросах, подобных этому:
SELECT *
FROM person
WHERE my_schema.isEligible(?) > -1 -- negative numbers are eligibility error codes
Где ? - параметр для данного идентификатора продукта.
В одном из нескольких запросов, вызывающих функцию, мне нужно передать новый дополнительный параметр @exception. Я хочу, чтобы функция по умолчанию вела себя так же, как и раньше, и изменяла поведение только для одного вызова, который будет передавать значение для @exception, поэтому я добавил новый параметр следующим образом:
CREATE FUNCTION [my_schema].[isEligible]
(@product NUMERIC(8),
@exception CHAR(1) = 'N')
RETURNS INT
AS
BEGIN
DECLARE @result INT;
/*
do eligibility checking (conditionally accounting for
@exception being 'Y'), and setting @result
*/
RETURN @result;
END;
Но когда я развертываю новую версию функции и запускаю запрос, который проходит только в @product, я получаю An insufficient number of arguments were supplied for the procedure or function [my_schema].[isEligible]. Я думал, что добавление = 'N' предоставит значение по умолчанию и позволит избежать этой проблемы.
Я читал здесь, что иногда эта общая ошибка звучания фактически скрывает другие ошибки, которые не могут всплывать, но я не знаю, так ли это, поскольку он говорит о процедурах, а это функция. Не уверен, есть ли разница или функции не поддерживают необязательные аргументы, такие как процедуры.
Мне бы хотелось, чтобы по возможности не передавать NULL для нового параметра, что упростило бы развертывание обновленной версии функции. Есть ли способ вызвать эту функцию как isEligible(?), так и isEligible(?, ?), или мне нужно, чтобы первая была isEligible(?, NULL), чтобы она работала?
В принятом ответе на дубликат есть хорошая идея: создайте свою функцию с двумя параметрами под новым именем и превратите свою старую функцию в оболочку, которая вызывает новую функцию со значением по умолчанию для нового параметра. Тогда вам не нужно изменять какие-либо существующие вызовы функций, и вам нужно только помнить об использовании нового имени, когда вы хотите использовать оба параметра.





Вы можете вызвать свою функцию как:
SELECT *
FROM person
WHERE my_schema.isEligible(?, default) > -1
а также:
SELECT *
FROM person
WHERE my_schema.isEligible(?, value) > -1
Ах да. NULL, о котором я предполагал, на самом деле сделает @exceptionNULL, а не активирует значение по умолчанию 'N'. Таким образом, использование default в вызывающем коде было бы необходимо, вместо того, чтобы вообще ничего не передавать, позволяя автоматически использовать значение по умолчанию?
@jinglesthula Да, это обязательно.
Если кому-то интересно, почему функция вместо подзапроса вызывает другие функции базы данных и имеет изрядную логику. Это плюс то, что он стал СУХИМ там, где он используется в нескольких запросах, я полагаю, поэтому он изначально был закодирован таким образом.