我正在使用SQL Server 2008 Enterprise。我正在学习SQL Server存储过程的OUTPUT参数。例如,存储过程sp_add_jobschedule有一个名为schedule_id的OUTPUT参数。
http://msdn.microsoft.com/en-us/library/ms366342.aspx
我的困惑是,看起来OUTPUT参数可以提供一个输入值并且还返回一个值,看起来它有INPUT和OUTPUT参数的行为?是否允许不为OUTPUT参数提供任何INPUT值(使其看起来像纯输出参数行为)?
答案 0 :(得分:60)
混淆在某种程度上是合理的 - 而像Oracle这样的其他RDBMS确实有存储过程参数,可以是IN
类型(仅输入),OUT
(仅输出)或{{1 (两种方式 - “按引用传递”类型的参数)。
SQL Server在这里有点草率,因为它将参数标记为INOUT
,但实际上,这意味着OUTPUT
/ INPUT
- 它基本上只意味着存储过程有机会从该参数中调用返回值。
是的 - 即使它被称为OUTPUT
参数,它实际上更像是OUTPUT
/ INPUT
参数,而OUTPUT
,IN
,{ {1}}在SQL Server中不存在(在T-SQL中)。
答案 1 :(得分:19)
我可以举例说明如何使用输出参数创建存储过程。
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.
答案 2 :(得分:6)
是的,您可以使用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
答案 3 :(得分:3)
进一步增加其他人的说法,OUTPUT参数既可以作为INPUT,也可以作为OUTPUT。但是,它取决于存储过程使用传递给它的值。
如果存储过程忽略了传入OUTPUT参数的值(通常应该这样),则无论如何都会忽略INPUT值。
使用Sergey的代码,我可以使用为@intOutput传递的值用户(如果需要)
create PROCEDURE test_proc
@intInput int,
@intOutput int OUTPUT
AS
set @intOutput = @intOutput + 1
go
但是,这违背了OUTPUT参数的目的 为了给出不同的视图,c#编译器强制您通过赋值覆盖out参数的值(不使用输出参数)。
e.g。我不能在c#中这样做。这里它只作为out参数(即忽略传递给该函数的用户值)
static void dosomething(out int i)
{
//i = 0;
i = i + 1;
}
答案 4 :(得分:2)
问题是 - 为什么你想不允许提供输入?这没有任何意义。考虑这个简单的例子:
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
请参阅 - 如果您未首先在中添加变量,那么您应该如何获得值 ?
答案 5 :(得分:2)
考虑在编程语言中通过引用传递的OUTPUT PARAMETERS,它是相同的。我现在能想到的最好的例子是返回错误代码。你想要一些插入...如果从SP中选择返回代码,你必须在代码中取回它,使用你没有的OUTPUT参数,它将在你的参数中(我的意思是使用C#命令,PHP init存储过程方法,或者不同的东西,然后构造字符串)
答案 6 :(得分:2)
关于原始问题的一部分的另外一个注释:
“是否允许不为OUTPUT参数(..)提供任何INPUT值?”
在SQLServer中,可以为OUTPUT参数指定默认值(正如其他人实际指出的那样)。请考虑以下示例,您可以在其中指定显式值或让函数本身生成ID。
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
答案 7 :(得分:0)
我认为还有两点值得注意:
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