【问题标题】:calling one stored proc from another by executing command通过执行命令从另一个调用一个存储过程
【发布时间】:2011-03-31 04:20:02
【问题描述】:

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

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

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

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

【问题讨论】:

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


    【解决方案1】:

    可以在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, ';', ''), '-', ''), '''', '')
    

    【讨论】:

      【解决方案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
      

      【讨论】:

        【解决方案3】:
        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
        

        【讨论】:

        • 我只想获取 curr_id 中的输出并从另一个存储过程中调用存储过程。这对我来说看起来很复杂。
        • 你在 ret 变量中得到输出,你可以忽略所有关于参数的代码。如果你愿意,你也可以忽略 try/catch 块。
        猜你喜欢
        • 1970-01-01
        • 2014-09-17
        • 1970-01-01
        • 1970-01-01
        • 2010-11-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多