通过执行命令从另一个调用一个存储过程

时间:2010-08-17 19:11:04

标签: sql-server sql-server-2005 dynamic-sql

在我的存储过程中,我必须传递一个表和列名,它可能每次都会改变。所以我构建命令并执行它。我希望输出另一个变量@curr_id。第二个存储过程将使用@curr_id作为输入来调用此存储过程。

我的问题是填充@curr_id vriable。它返回零。如果我删除了 curr_id变量然后它工作(参见注释行)

有人可以。告诉我 - 如何填充@curr_id并作为OUTPUT返回? - 如何从第二个存储过程调用第一个存储过程?

ALTER PROCEDURE [dbo].[sp_astm_getcurrid]
@ColName as nvarchar(250),
@TblName as nvarchar(250),
@curr_id nvarchar(max) OUTPUT 
AS
BEGIN
DECLARE @cmd nvarchar(max)

SET @cmd =N'SET '+@curr_id+'= SELECT MAX('+@ColName+') FROM '+@TblName;
--SET @cmd =N'SELECT MAX('+@ColName+') FROM '+@TblName;

EXEC (@cmd)

END

3 个答案:

答案 0 :(得分:2)

因为EXEC在不同的上下文中运行,所以它不知道你的@curr_id变量。相反,您可以将动态SQL的输出放入表变量中,然后使用它来设置@curr_id。

另外,never start a stored procedure name with sp_

    ALTER PROCEDURE [dbo].[usp_astm_getcurrid]
        @ColName as nvarchar(250),
        @TblName as nvarchar(250),
        @curr_id nvarchar(max) OUTPUT 
    AS
    BEGIN
        DECLARE @cmd nvarchar(max)

        declare @dummy table (
            ReturnColumn nvarchar(max)
        )

        SET @cmd = N'SELECT MAX(' + @ColName + N') FROM ' + @TblName;

        insert into @dummy
            (ReturnColumn)
            exec (@cmd)

        set @curr_id = (select ReturnColumn from @dummy)
    END

然后,从另一个内部调用此过程的示例可能是这样的。重要的关键是在调用中以及上述过程的声明中使用OUTPUT关键字。

    CREATE PROCEDURE CallMyProcedure
    AS
    BEGIN
        declare @curr_id nvarchar(max)
        exec dbo.usp_astm_getcurrid N'YourColumnName', N'YourTableName', @curr_id OUTPUT
        select @curr_id
    END

答案 1 :(得分:0)

Friend Function execSP(ByVal spName As String, Optional ByVal params As Collection = Nothing) As Integer
        Dim cmd As SqlCommand
        Dim param As SqlParameter
        Dim ret As Integer
        Dim iParam As Integer

        cmd = New SqlCommand
        cmd.CommandText = spName
        cmd.CommandType = CommandType.StoredProcedure
        cmd.Connection = _sqlConn
        cmd.CommandTimeout = 0

        If Not params Is Nothing Then
            For iParam = 1 To params.Count
                param = params(iParam)
                cmd.Parameters.Add(param)
            Next
        End If

        If _sqlConn.State <> ConnectionState.Open Then
            _sqlConn.Open()
        End If

        Try
            ret = cmd.ExecuteNonQuery()
        Catch ex As Exception
            Throw New Exception(ex.Message)
        Finally
            _sqlConn.Close()
        End Try
        Return ret
    End Function

答案 2 :(得分:0)

您可以使用sp_executesql中的OUTPUT参数:

ALTER PROCEDURE [dbo].[sp_astm_getcurrid] 
@ColName as nvarchar(250), 
@TblName as nvarchar(250), 
@curr_id nvarchar(max) OUTPUT  
AS 
BEGIN 

DECLARE 
  @cmd nvarchar(max)

SET @cmd =N'SELECT @curr_id_out = MAX('+@ColName+') FROM '+@TblName 

EXEC sp_executesql 
  @cmd, 
  N'@curr_id_out nvarchar(max) OUTPUT', 
  @curr_id_out = @curr_id OUTPUT

END 

我不能不提及,在这种情况下,使用EXEC(@cmd)或sp_executesql(@cmd)会使您容易受到SQL injection攻击。

我建议在存储过程的开头添加如下内容:

SELECT 
  @ColName = REPLACE(
             REPLACE(
             REPLACE(@ColName, ';', ''), '-', ''), '''', ''),
  @TblName = REPLACE(
             REPLACE(
             REPLACE(@TblName, ';', ''), '-', ''), '''', '')