Вывод выходного параметра SQL Server
Я использую SQL Server 2008 Enterprise. Я изучаю параметр OUTPUT хранимой процедуры SQL Server. Например, хранимая процедура sp_add_jobschedule имеет параметр OUTPUT, называемый sched_id.
http://msdn.microsoft.com/en-us/library/ms366342.aspx
Моя путаница, похоже, что параметр OUTPUT может быть предоставлен входным значением, а также возвращает значение, похоже, что он имеет поведение как параметра INPUT, так и OUTPUT? Разрешено ли не указывать значения INPUT для параметра OUTPUT (чтобы он выглядел как поведение чистого выходного параметра)?
Ответы
Ответ 1
Путаница оправдана до некоторой степени - и другие СУБД, такие как Oracle, имеют параметры хранимых процедур, которые могут иметь тип IN
(только для ввода), OUT
(только для вывода) или INOUT
(в обоих направлениях - тип параметра "передача по ссылке"),
SQL Server здесь немного неаккуратный, поскольку он помечает параметр как OUTPUT
, но на самом деле это означает INPUT
/OUTPUT
- это просто означает, что хранимый процесс имеет шанс вернуть значение из своего вызова в этом параметре.
Так что да - несмотря на то, что он называется параметром OUTPUT
, он на самом деле является скорее параметром INPUT
/OUTPUT
, а такие IN
, INOUT
, OUT
как в Oracle, не существуют в SQL Server (в T-SQL).
Ответ 2
Я могу привести короткий пример того, как создавать хранимую процедуру с выходным параметром.
CREATE PROCEDURE test_proc
@intInput int,
@intOutput int OUTPUT
AS
set @intOutput = @intInput + 1
go
И для вызова этой процедуры и использования выходного параметра выполните следующие действия:
declare @intResult int
exec test_proc 3 ,@intResult OUT
select @intResult
Вы видите, что сначала нужно объявить переменную ouput. И после выполнения хранимой процедуры выходное значение будет в вашей переменной. Вы можете установить любое значение в свою выходную переменную, но после выполнения хранимой процедуры он будет точно содержать возвращаемую хранимую процедуру (независимо от того, какое значение было в выходной переменной).
Например:
declare @intResult int
exec test_proc 3 ,@intResult OUT
select @intResult
Он вернется 4. И:
declare @intResult int
set @intResult = 8
exec test_proc 3 ,@intResult OUT
select @intResult
Также верните 4.
Ответ 3
Да, вы можете использовать параметр OUTPUT для передачи и получения значений (хотя я не могу придумать повод для этого в данный момент).
Вот тривиальный пример, демонстрирующий это:
-- The stored procedure
CREATE PROCEDURE OutParamExample
@pNum int OUTPUT
AS
BEGIN
select @pNum
set @pNum = @pNum + 5
END
GO
-- use a local variable to retrieve your output param value
declare @TheNumber int
set @TheNumber = 10
print @TheNumber
exec OutParamExample @TheNumber OUTPUT
print @TheNumber
Результаты будут выглядеть так:
10
-----------
10
(1 row(s) affected)
15
РЕДАКТИРОВАТЬ: ОК, я думаю, что во втором абзаце я пропустил "нет" и, возможно, не ответил на заданный вами вопрос. Если вам нужен строгий выходной параметр (например, что-то вроде кода возврата), вам, конечно же, не нужно указывать значение локальной переменной, переданной в качестве выходного параметра, но вы все равно должны объявить эту локальную переменную так, чтобы вы имеют способ доступа к возвращаемому значению вне области самой процедуры.
Например:
declare @LocalNumber int
-- I don't have to assign a value to @LocalNumber to pass it as a parameter
exex OutParamExample @LocalNumber OUTPUT
-- (assume SP has been altered to assign some reasonable value)
-- but I do have to declare it as a local variable so I can get to
-- the return value after the stored procedure has been called
print @LocalNumber
Ответ 4
В дополнение к тому, что говорили выше, параметры OUTPUT могут действовать как INPUT, так и OUTPUT. Но это зависит от хранимой процедуры для использования переданного ей значения.
Если хранимые процедуры игнорируют значение, переданное для параметра OUTPUT (что обычно должно), значение INPUT все равно игнорируется.
Используя код Сергея, я могу использовать значение, переданное для @intOutput (если нужно)
create PROCEDURE test_proc
@intInput int,
@intOutput int OUTPUT
AS
set @intOutput = @intOutput + 1
go
Но это побеждает цель параметра OUTPUT.
Чтобы дать другое представление, компилятор С# заставляет вас перезаписать значение параметра out путем назначения (без использования выходного параметра).
например. Я не могу сделать это в С#. Здесь он действует только как параметр out (i.e игнорирует значение, переданное этой функции функции)
static void dosomething(out int i)
{
//i = 0;
i = i + 1;
}
Ответ 5
Вопрос в том, почему вы хотите запретить ввод данных? Это не имеет никакого смысла. Рассмотрим этот простой пример:
CREATE PROCEDURE test (@param AS INT OUTPUT) AS
BEGIN
SET @param = 100
END
GO
DECLARE @i INT
SET @i = 0
EXECUTE test @i OUTPUT
PRINT @i
DROP PROCEDURE test
Отпечатает
100
Посмотрите - как вы должны получить значение, если вы не ввели первую переменную?
Ответ 6
Подумайте о ПАРАМЕТРАХ ВЫХОДА, которые передаются по ссылке на языках программирования, это то же самое. Лучший пример, который я могу сейчас подумать, - это вернуть код ошибки. Вам нужна какая-то вставка... если вы выберете код возврата из SP, который вы должны вернуть в свой код, с параметром OUTPUT, который у вас нет, он будет уже в вашем параметре (я имею в виду использование команд С#, PHP init хранит методы proc или что-то другое, чем строит строки)
Ответ 7
Еще одно примечание относительно части исходного вопроса:
"Разрешено ли не указывать значения INPUT для параметра OUTPUT (..)?"
В SQLServer можно указать значение по умолчанию для параметра OUTPUT (который, как указывали другие, фактически INOUT). Рассмотрим следующий пример, в котором вы можете указать явное значение или позволить самой функции генерировать идентификатор.
CREATE PROCEDURE test (@id uniqueidentifier = NULL OUTPUT) AS
BEGIN
IF @id IS NULL SET @id = NEWID()
-- INSERT INTO xyz (...) VALUES (@id, ...)
PRINT 'Insert with id: ' + CAST (@id as nvarchar(36))
END
GO
DECLARE @insertedId uniqueidentifier
EXECUTE test '00000000-0000-0000-0000-000000000000'
EXECUTE test @insertedId OUTPUT
PRINT @insertedId
DROP PROCEDURE test
Отпечатает
Insert with id: 00000000-0000-0000-0000-000000000000
Insert with id: 67AE3D27-8EAB-4301-B384-30EEA1488440
67AE3D27-8EAB-4301-B384-30EEA1488440
Ответ 8
Я думаю, что стоит отметить еще две вещи:
1) Вы можете передать более одного параметра как OUTPUT
,
2) Вам не нужно вызывать параметры с OUTPUT
если вы не хотите результатов
CREATE PROCEDURE ManyOutputs @a int, @b int output, @c varchar(100) output, @d bit output
AS
BEGIN
SET @b = @a + 11
SET @c = 'The Value of A is ' + CAST(@a AS varchar(5)) + ', and the value of B is ' + CAST(@b AS varchar(5))
IF (@a % 2 = 1)
SET @d = 1
ELSE
SET @d = 0
END
GO
Вызов этой рутины:
DECLARE @bVal int
DECLARE @cVal varchar(100)
DECLARE @dVal bit
EXEC ManyOutputs 1, @bVal, @cVal, @dVal
SELECT @bVal AS bVal, @cVal as cVal, @dVal as dVal
Возвращает NULL, NULL, NULL
EXEC ManyOutputs 2, @bVal OUT, @cVal OUT, @dVal OUT
SELECT @bVal AS bVal, @cVal as cVal, @dVal as dVal
Возвращает 13, "Значение A равно 2, а значение B равно 13", 0
EXEC ManyOutputs 3, @bVal, @cVal, @dVal
SELECT @bVal AS bVal, @cVal as cVal, @dVal as dVal
Возвращает 13, "Значение A равно 2, а значение B равно 13", 0
(аналогично последнему вызову, потому что мы не получили новые значения с помощью OUTPUT
, поэтому он сохранил старые значения.)
EXEC ManyOutputs 5, @bVal OUT, @cVal OUT, @dVal OUT
SELECT @bVal AS bVal, @cVal as cVal, @dVal as dVal
Возвращает 16, "Значение A равно 5, а значение B равно 16", 1