Могу ли я иметь необязательный выходной параметр в хранимой процедуре?
у меня есть хранимая процедура, которая имеет кучу входных и выходных параметров, потому что она вставляет значения в несколько таблиц. В некоторых случаях сохраненный proc вставляется только в одну таблицу (в зависимости от входных параметров). Вот переделала сценарий, чтобы проиллюстрировать.
Таблицы / Объекты Данные:
человек
Id
Name
Address
имя
Id
FirstName
LastName
адрес
Id
Country
City
Сказать, Что Я имейте хранимую процедуру, которая вставляет человека. Если адрес не существует, я не буду добавлять его в Address
таблицы в базе данных.
таким образом, когда я генерирую код для вызова хранимой процедуры, я не хочу добавлять
5 ответов
как входные, так и выходные параметры могут быть присвоены значения по умолчанию. В этом примере:
CREATE PROCEDURE MyTest
@Data1 int
,@Data2 int = 0
,@Data3 int = null output
AS
PRINT @Data1
PRINT @Data2
PRINT isnull(@Data3, -1)
SET @Data3 = @Data3 + 1
RETURN 0
первый параметр является обязательным, а второе и третье не обязательно, если не установлен при вызове подпрограммы, им будут присваиваться значения по умолчанию. Попробуйте возиться с ним и следующей процедурой тестового вызова в SSMS, используя разные значения и настройки, чтобы увидеть, как все это работает вместе.
DECLARE @Output int
SET @Output = 3
EXECUTE MyTest
@Data1 = 1
,@Data2 = 2
,@Data3 = @Output output
PRINT '---------'
PRINT @Output
выходные параметры и значения по умолчанию не работают хорошо вместе! Это из SQL 10.50.1617 (2008 R2). не обольщайтесь полагать, это волшебно устроена не SET
к этому значению от вашего имени (как и мой коллега)!
эта "игрушка" SP допрашивает OUTPUT
значение параметра, будь то значение по умолчанию или NULL
.
CREATE PROCEDURE [dbo].[omgwtf] (@Qty INT, @QtyRetrieved INT = 0 OUTPUT)
AS
IF @QtyRetrieved = 0
BEGIN
print 'yay its zero'
END
IF @QtyRetrieved is null
BEGIN
print 'wtf its NULL'
END
RETURN
если вы отправляете неинициализированное значение (т. е. NULL
) для OUTPUT
, вы на самом деле got NULL
внутри SP, а не 0
. Имеет смысл, что-то прошло для этого параметра.
declare @QR int
exec [dbo].[omgwtf] 1, @QR output
print '@QR=' + coalesce(convert(varchar, @QR),'NULL')
вывод:
wtf its NULL
@QR=NULL
если мы добавим явный SET
от абонента мы получаем:
declare @QR int
set @QR = 999
exec [dbo].[omgwtf] 1, @QR output
print '@QR=' + coalesce(convert(varchar, @QR),'NULL')
и (неудивительно) выход:
@QR=999
опять же, имеет смысл, параметр передается, и SP не предпринял никаких явных действий для SET
значение.
добавить SET
на OUTPUT
параметр в SP (как вы предполагается сделать), но не устанавливайте ничего от вызывающего абонента:
ALTER PROCEDURE [dbo].[omgwtf] (@Qty INT, @QtyRetrieved INT = 0 OUTPUT)
AS
IF @QtyRetrieved = 0
BEGIN
print 'yay its zero'
END
IF @QtyRetrieved is null
BEGIN
print 'wtf its NULL'
END
SET @QtyRetrieved = @Qty
RETURN
теперь при выполнении:
declare @QR int
exec [dbo].[omgwtf] 1234, @QR output
print '@QR=' + coalesce(convert(varchar, @QR),'NULL')
выход:
wtf its NULL
@QR=1234
это "стандартное" поведение для OUTPUT
обработка параметров в SPs.
теперь поворот сюжета: единственный способ получить значение по умолчанию для "активировать" - это не пройдет OUTPUT
параметр вообще, что ИМХО имеет мало смысла: поскольку он настроен как OUTPUT
параметр, что означало бы возврат чего-то" важного", что должно быть собрано.
declare @QR int
exec [dbo].[omgwtf] 1
print '@QR=' + coalesce(convert(varchar, @QR),'NULL')
дает этот выход:
yay its zero
@QR=NULL
но это не удается захватить выход SPs, предположительно, цель этого SP для начала.
ИМХО эта функция сочетанием сомнительный конструкт я бы считал код запах (фух!!)
похоже, я могу просто добавить значение по умолчанию , например:
@AddressId int = -1 Output
кажется, что его плохо с точки зрения читаемости, так как AddressId
предназначен строго как OUTPUT
переменной. Но это работает. Пожалуйста, дайте мне знать, если есть лучшее решение.
добавление к тому, что сказал Филипп:
у меня была хранимая процедура в моей базе данных sql server, которая выглядела следующим образом:
dbo.<storedProcedure>
(@current_user char(8) = NULL,
@current_phase char(3) OUTPUT)
и я вызывал его из своего .net-кода следующим образом:
DataTable dt = SqlClient.ExecuteDataTable(<connectionString>, <storedProcedure>);
я получал систему.Данные.В sqlclient.SqlException: процедура или функция ожидает параметр '@current_phase', который не был предоставлен.
Я также использую эту функцию где-то еще в моей программе и передаю параметр и обработка выходного. Чтобы мне не пришлось изменять текущий вызов, я просто изменил хранимую процедуру, чтобы сделать выходной параметр также необязательным.
Итак, теперь это выглядит следующим образом:
dbo.<storedProcedure>
(@current_user char(8) = NULL,
@current_phase char(3) = NULL OUTPUT)
поскольку вы выполняете хранимую процедуру, а не инструкцию SQL, вы должны установить тип команды вашей команды SQL в хранимую процедуру:
cmd.CommandType = CommandType.StoredProcedure;
принято от здесь.
кроме того, как только вы удалите эту ошибку, вы можете использовать SQL nvl()
функция в вашей процедуре, чтобы указать, что вы хотите отобразить, когда встречается нулевое значение.
извините за неправильное решение вопроса...должно быть, неправильно вас понял. Вот пример nvl, который, я думаю, может решить его немного лучше?
select NVL(supplier_city, 'n/a')
from suppliers;
оператор SQL выше вернет 'n / a', если supplier_city
поле содержит значение null. В противном случае он вернет supplier_city
значение.