SQL Server:调用另一个存储过程的存储过程

时间:2014-11-14 13:50:02

标签: sql-server tsql stored-procedures

修改

有问题的例子对我想要的东西可能并不理想,因为它总是给出一个结果。 基本上,我想要一种方法来从一个表中选择所有列加上计算值(在我的情况下为Country),其中传递给该存储过程的id是itm.ID(导致许多行)

Veera给出了一个有效的解决方案,我想知道这是否可以通过存储过程更有效地完成。


我是使用SQL Server的初学者,我希望得到以下帮助:我正在编写一个调用另一个存储过程的存储过程。

主存储过程如下所示:

ALTER  PROCEDURE [Store].[usp_GetItem]
(
      @ID INT ,
      @Name NVARCHAR(255),
      @GroupNum INT
)   
AS
BEGIN
    SET NOCOUNT ON

    SELECT * 
    FROM Items itm
    WHERE itm.ID = @ID 
      AND itm.Name = @Name 
      AND itm.GroupNum = @GroupNum
END

现在,我有另一个存储过程,如下所示:

ALTER  PROCEDURE Country
     (@ID INT) 
AS
BEGIN 
    SET NOCOUNT ON  

    DECLARE @CountryName NVARCHAR(255)
    Set @CountryName = SELECT Name
                       FROM General_c_Country 
                       WHERE ItemID = @ID  

    SELECT @CountryName
END

现在,我希望第一个过程将项目的ID(itm.ID)传递给第二个过程, 获取结果(国家/地区名称),然后获取主存储过程以显示以下记录:

ID     Name        GroupNum   Country
-------------------------------------------------------------
1      Page          32       Spain (Country of Item with ID1

依旧......

注意:我知道这可以通过一个简单的内连接在一个程序中完成。 然而,我想知道如何以我描述的方式做到这一点。谢谢!

5 个答案:

答案 0 :(得分:1)

不需要第二个SP。而是使用如下功能。

CREATE FUNCTION Country( @ID INT)
RETURNS NVARCHAR(255)
  AS
BEGIN 
 SET NOCOUNT ON     
   DECLARE @CountryName NVARCHAR(255)
   Set @CountryName =SELECT Name
                     FROM General_c_Country 
                     WHERE ItemID = @ID  
   RETURN @CountryName
END

将第一个SP的功能调用为:

ALTER  PROCEDURE [Store].[usp_GetItem]
(
      @ID INT ,
      @Name NVARCHAR(255),
      @GroupNum INT
  )   
AS
BEGIN
    SET NOCOUNT ON

    SELECT *, dbo.Country(itm.ID) AS Country
    FROM Items itm
    where itm.ID = @ID AND itm.Name = @Name AND itm.GroupNum = @GroupNum
END

答案 1 :(得分:0)

您可以在第一个过程中创建一个临时表,然后调用第二个过程。临时表在第二个过程中被识别(因为它是由第一个过程调用的,它以某种方式嵌套)。第二个过程应将其值插入临时表中,并且当执行返回到第一个过程时,临时表将填充准备使用的数据。

答案 2 :(得分:0)

您可以使用output parameters的存储过程。

第二个存储过程的代码应如下所示:

ALTER  PROCEDURE Country
     (@ID INT, @CountryNameParam NVARCHAR(255) OUTPUT) 
AS
BEGIN 
    SET NOCOUNT ON  

    SELECT @CountryNameParam = Name
    FROM General_c_Country 
    WHERE ItemID = @ID  

END

在第一个存储过程中,使用以下代码检索coutry名称:

declare @CountryName NVARCHAR(255)

exec Country @ID=[your id here], @CountryNameParam=@CountryName OUTPUT

print @CountryName

请注意,我使用了2个不同的标识符名称(@CountryName@CountryNameParam),只是为了明确谁是谁。

答案 3 :(得分:0)

为什么你首先需要一个单独的电话?为什么不直接加入表并以预期的方式使用数据库?两个查询都依赖于相同的@ID输入参数,因此自然适合执行以下操作:

SELECT itm.*, gcc.Name AS [Country]
FROM Items itm
INNER JOIN General_c_Country gcc
        ON gcc.ItemID = itm.ID
WHERE itm.ID = @ID 
  AND itm.Name = @Name 
  AND itm.GroupNum = @GroupNum;

修改
我刚刚注意到问题的最后一行,说你知道你可以做到这一点,但想知道如何完成具体问题。我应该指出你的示例输出是不可能的。您将单个@ID传递给第一个存储过程,但在输出中显示两个不同的ID。您在问题中显示的两个存储过程将只返回一行。这里的确切意图是什么,因为这将决定如何实现它。如果你想要多行,因此返回第二个proc中的多个值,那么无法在存储过程中获取该国家,因为它将被调用一次并且不能成为查询的一部分,但它可以用于单行。如果你需要多个值,那么你需要填充一个本地临时表,其中包含所有可能的值和JOIN(在这种情况下,为什么不只是做我建议的简单JOIN),或者你需要一个标量用户 - 定义函数(UDF),它接收@ID并返回名称。

答案 4 :(得分:0)

第一个过程

  ALTER  PROCEDURE [Store].[usp_GetItem]
        (
              @ID INT output,
              @Name NVARCHAR(255),
              @GroupNum INT
        )   
        AS
        BEGIN
            SET NOCOUNT ON
        set @id=
            (SELECT id 
            FROM Items itm
            WHERE  
               itm.Name = @Name 
              AND itm.GroupNum = @GroupNum
return
    END

第二次过程

ALTER  PROCEDURE Country

AS
BEGIN 
    SET NOCOUNT ON  
declare @idx int
    DECLARE @CountryName NVARCHAR(255)
    Set @CountryName = SELECT Name
                       FROM General_c_Country 
                       WHERE ItemID =[Store].[usp_GetItem] [@Name],[@GroupNum],@ID =@idx output   

    SELECT @CountryName
END

插入[@Name],[@ GroupNum]正确的数据