SQL存储过程执行在从其他过程获取值之前选择

时间:2009-10-22 16:40:44

标签: sql sql-server stored-procedures

有一个奇怪的问题创建了一个小的存储过程,需要在执行主select语句之前执行一些其他存储过程来获取一些值,见下文,

set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[usp_get_ApplicationUserServiceRoles] 
    @UserId int,
    @ApplicationName varchar(50),
    @ServiceName varchar(50)
AS
BEGIN
    -----------------------------------------   
    SET NOCOUNT ON
    -----------------------------------------
    DECLARE @ApplicationId INT
    exec @ApplicationId = dbo.usp_get_AppIdFromName @ApplicationName
    DECLARE @ServiceId INT
    exec @ServiceId = dbo.usp_get_ServiceIdFromName @ServiceName

    SELECT
    [RoleName]
    FROM 
    [ServiceRoles] s 
    INNER JOIN 
    [ApplicationUserServiceRoles] r
    ON
    s.ServiceRoleId = r.ServiceRoleId
    INNER JOIN
    [ApplicationServices] p
    ON
    s.ServiceId = p.ServiceId
    WHERE
    r.UserId = @UserID
    AND 
    r.ApplicationId = @ApplicationId
    AND
    s.ServiceId = @ServiceId        
END

当我运行这个存储过程时,它会使用此proc返回两个过程中的两个值,但不是实际的选择值。但是,当我自己运行select语句时,辅助存储过程返回的值会返回正确的数据。

知道发生了什么,是否在两个辅助存储过程之前运行了select语句,因此select语句没有得到正确的值?

在SQL 2005中运行

4 个答案:

答案 0 :(得分:3)

存储过程返回一个数字,指示存储过程的执行状态。为了捕获select语句的输出,你必须使用INSERT ... EXECUTE(详见here

在您的情况下会发生的是每个子过程都会执行但主程序失败。检查输出窗口,它应该告诉你错误。

答案 1 :(得分:3)

捕获存储过程结果集的唯一方法是INSERT ... EXEC:

declare @applicationId int;
declare @tableApplicationId table (ApplicationId ind);
insert into @tableApplicationId
exec dbo.usp_get_AppIdFromName @ApplicationName;
select @applicationId = ApplicationId from @tableApplicationId;

您可能需要考虑将dbo.usp_get_AppIdFromName更改为函数,或者将@applicationId作为OUTPUT参数返回的过程。

INSERT ... EXEC有各种副作用问题,比如嵌套问题:

答案 2 :(得分:1)

如果你的“子”存储过程只返回一个值,你最好使用输出参数,如下所示:

.
.
DECLARE @ApplicationId INT
exec dbo.usp_get_AppIdFromName @ApplicationName, @ApplicationId OUTPUT
.
.

子程序看起来应该是这样的:

CREATE PROCEDURE dbo.usp_get_AppIdFromName
    @ApplicationName  varchar(50)
   ,@ApplicationId    int  OUTPUT

AS
 BEGIN

    --  Adjust as necessary
    SELECT @ApplicationId = ApplicationId
     from MyApplicationTable
     where Name = @ApplicationName

 END
RETURN 0

(请注意,在原始结构中,

exec @ApplicationId = dbo.usp_get_AppIdFromName @ApplicationName

@ApplicationId将被赋予RETURN语句的值,在我的示例中,它始终为0.最好保留此值以返回该过程调用的状态 - 也就是说,它是否有效。)

答案 3 :(得分:0)

我会使用两个函数调用。这些存储过程可能被称为eslewhere,如果你用输出参数修改它们,那么其他东西就会破坏。