SQL Server - 存储过程问题

时间:2010-01-12 17:21:15

标签: sql-server stored-procedures

对于我正在处理的应用程序......我们正在创建一个自定义日志系统。用户可以查看日志并对其应用“标签”(就像您可以在此处将标签应用于问题一样!)

在这个例子中,我试图获得一个给出“标签”的所有日志的列表。我意识到我可以通过使用连接来实现这一点......但这也是我练习存储过程的一个练习:)

我有一个看起来像这样的存储过程来通过PK

选择日志
ALTER PROCEDURE [dbo].[getLogByLogId] 
    -- Add the parameters for the stored procedure here
    @ID int

AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    -- Insert statements for procedure here
    SELECT  TOP 1

    LOG_ID,
    a.A,
    a.B,
    a.C

    FROM dbo.LOG a
    WHERE a.LOG_ID = @ID

现在我想把这个存储过程称为另一个......就像这样

ALTER PROCEDURE [dbo].[getLogsByTagName] 
        -- Add the parameters for the stored procedure here
        @TAG nvarchar(50)

AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    -- Insert statements for procedure here
    SELECT  TOP 1000

    LOG_ID --somehow store this and execute the dbo.getLogByLogId procedure here

    FROM dbo.LOG_TAG a
    WHERE a.TAG = @TAG

由于

4 个答案:

答案 0 :(得分:2)

如果您的logbyid SP中有复杂的逻辑,您试图避免在系统中的多个位置进行复制(选择列,派生列等),我建议将其转换为内联表值函数(可能没有获取ID参数,在这种情况下,您实际上可以使用普通视图。

然后你可以加入到你的其他存储过程中的ITVF /视图(或者也可以创建另一个udf)进行搜索或使用OUTER APPLY功能(效率不高)。

内联表值函数基本上是参数化视图,可以通过优化器相当容易地优化。

答案 1 :(得分:0)

如果你想在sproc中调用另一个sproc,只需使用:

CREATE PROCEDURE myTestProc
AS
BEGIN

--Do some work in this procedure
SELECT blah FROM foo

--now call another sproc
EXEC nameOfSecondSproc
END

答案 2 :(得分:0)

您可以使用CURSOR

来实现您尝试的内容的唯一方法

如果这只是为了你的学习,那么一定要试一试,但我不会推荐这个用于制作。

它会像这样

DECLARE @Table TABLE(
        ID INT
)

INSERT INTO @Table SELECT 1
INSERT INTO @Table SELECT 2
INSERT INTO @Table SELECT 3
INSERT INTO @Table SELECT 4
INSERT INTO @Table SELECT 5
INSERT INTO @Table SELECT 6


DECLARE Cur CURSOR FOR 
SELECT ID
FROM @Table

OPEN Cur

DECLARE @ID INT
FETCH NEXT FROM Cur INTO @ID

WHILE @@FETCH_STATUS = 0 
BEGIN
    PRINT @ID
    FETCH NEXT FROM Cur INTO @ID
END

CLOSE Cur
DEALLOCATE Cur

通过使用 WHILE 循环中检索到的 @ID ,您可以执行所需的sp并将值插入表变量

INSERT INTO @Table EXEC sp_MySP @ID

答案 3 :(得分:0)

您可以使用以下语法从另一个存储过程调用存储过程:

    ALTER PROCEDURE [dbo].[getLogsByTagName]  
            -- Add the parameters for the stored procedure here 
            @TAG nvarchar(50) 

    AS 
    BEGIN 
        -- SET NOCOUNT ON added to prevent extra result sets from 
        -- interfering with SELECT statements. 
        SET NOCOUNT ON; 

        -- Insert statements for procedure here 
        SELECT  TOP 1000 

        LOG_ID --somehow store this and execute the dbo.getLogByLogId procedure here 

        FROM dbo.LOG_TAG a 
        WHERE a.TAG = @TAG 

        -- Execute dbo.getLogByLogId stored procedure
    DECLARE @logId INTEGER
    SET @logId = <some value>
    EXEC dbo.getLogByLogId @logId
END

但是,您的问题的难点在于您的dbo.getLogByLogId过程只能接受单个LogID参数,因此只能返回单个日志记录。您需要返回LogId在Tags表中具有相应记录的所有Log的信息。

执行此操作的正确方法是将Log和Tag表连接在一起,如下所示:

SELECT *
FROM dbo.LOG_TAG a
INNER JOIN dbo.LOG b ON a.LOG_ID = b.LOG_ID
WHERE a.TAG = @TAG

如果您担心多次返回相同的logId,可以使用SELECT语句中的DISTINCT关键字来过滤掉重复的logId。

您也可以将dbo.getLogByLogId过程重写为用户定义的函数(UDF)。 UDF可以接受表作为参数并返回表结果。

可以在this article中找到用户定义函数的介绍。