вызов одного хранимого процесса из другого путем выполнения команды - PullRequest
1 голос
/ 17 августа 2010

В моей хранимой процедуре я должен передать имя таблицы и столбца, которые могут меняться каждый раз.Поэтому я строю команду и выполняю ее.Я хочу вывод в другую переменную @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 ]

2 голосов
/ 18 августа 2010

Поскольку EXEC работает в другом контексте, он не знает о вашей переменной @curr_id.Вместо этого вы можете поместить вывод вашего динамического SQL в табличную переменную, а затем использовать его для установки @curr_id.

Кроме того, никогда не запускает имя хранимой процедуры с 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
0 голосов
/ 18 августа 2010

Вы можете использовать параметр OUTPUT в sp_executesql :

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-инъекций атак.

Я рекомендую добавить что-то вроде следующего в начало хранимой процедуры:

SELECT 
  @ColName = REPLACE(
             REPLACE(
             REPLACE(@ColName, ';', ''), '-', ''), '''', ''),
  @TblName = REPLACE(
             REPLACE(
             REPLACE(@TblName, ';', ''), '-', ''), '''', '')
0 голосов
/ 17 августа 2010
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
...