Подтвердить что ты не робот

Вывод выходного параметра 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 (чтобы он выглядел как поведение чистого выходного параметра)?

4b9b3361

Ответ 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