简体   繁体   English

在 exec sp_executesql 中从 proc 获取标量值

[英]Get the scalar value from proc in exec sp_executesql

I have a proc that returns a different numeric value for different conditions.我有一个 proc,它针对不同的条件返回不同的数值。 And I call to this proc from the exec sp_executesql But all the time I get 0 .我从exec sp_executesql调用这个 proc 但是我一直得到0 What I didn't do in the correct code is why it doesn't work for me, can anyone help?我没有在正确的代码中做的是为什么它对我不起作用,有人可以帮忙吗?

Stored procedure:存储过程:

ALTER PROCEDURE [dbo].[AAAProc](
@Field1 INT, @Field2 INT = null, @FileName NVARCHAR(MAX))
AS
BEGIN

SET NOCOUNT ON;

DECLARE @DestFile NVARCHAR(MAX)
declare @p1 int = 100
declare @p2 int = 500
SELECT  @DestFile = dbo.Func1(@p1, @p2)

DECLARE @CmdString VARCHAR(1000)
DECLARE @MyTable TABLE
(
  Line NVARCHAR(1000)
)

SET @CmdString = 'copy '+@FileName+' '+ @DestFile

print @CmdString

if(dbo.FileExists(@FileName)=1)
begin
    INSERT INTO @OutputTable EXEC master..xp_cmdshell @CmdString 

    if ((select count(*) from @MyTable where Line like '%1 file(s) copied.%')>0)
    begin
        RETURN 1;
    end
    ELSE
    begin
        return 0;
        declare @error nvarchar(max) = '!!!!Error!!!!! move file failed'
        RAISERROR (@error,16,1);
    end
end
else
begin
    RETURN 0;
end
END

And this is the call statment:这是调用语句:

SET @Sql = 'EXEC dbo.AAAProc '+@SomeField1+','+CONVERT(NVARCHAR(MAX), @SomeField2)+', ' + ISNULL(CONVERT(NVARCHAR(MAX), @SomeField3),'null')+', '''+  @SomeField4+'''';
declare @result int
EXEC @result = sp_executesql @Sql

PRINT '@result = ' + CONVERT(NVARCHAR,@result)

sp_executesql is used to avoid string concatenation, passing values as parameters instead. sp_executesql用于避免字符串连接,而是将值作为参数传递。 No amount of quoting or escaping can prevent SQL injection and conversion issues.没有多少引用或转义可以防止 SQL 注入和转换问题。 By using string concatenation, the question's code is fully exposed to those problems.通过使用字符串连接,问题的代码完全暴露在这些问题中。

In this case though, one can just call EXEC directly, pass the parameters and store the return value:但是在这种情况下,可以直接调用EXEC ,传递参数并存储返回值:

declare @ret int;
EXEC @ret = dbo.AAAProc @SomeField1 ,@SomeField2,ISNULL(@SomeField3),'null');

Which is equivalent to :这相当于:

declare @someValue varchar(max)=ISNULL(@SomeField3,'null');

declare @ret int;
EXEC @ret = dbo.AAAProc @SomeField1 ,@SomeField2,@someValue;

The stored procedure only accepts 3 parameters, so passing @SomeField4 is probably a bug hidden by the string concatenation.存储过程只接受 3 个参数,因此传递@SomeField4可能是字符串连接隐藏的错误。

Should there be a need to call sp_executesql ( why ?) the same statement can be used provided @ret is defined as an output parameter for the sp_executesql call.如果需要调用sp_executesql为什么?),可以使用相同的语句,前提是@ret被定义为sp_executesql调用的输出参数。 Everything else should be passed as a parameter.其他一切都应该作为参数传递。 That means, NO functions inside the string, and everything else should be declared as a parameter to sp_executesql :这意味着,该字符串NO的功能,和其他一切应该声明作为参数传递给sp_executesql

declare @ret int

exec sp_executesql N'EXEC @ret = dbo.AAAProc @Field1 ,@Field2,@FileName',
     N'@Field1 INT, @Field2 INT, @FileName varchar(max), @ret int OUTPUT',
     @Field1=@SomeField1,
     @Field2=@SomeField2,
     @FileName=ISNULL(@SomeField3,'null')
     @ret = @ret OUTPUT 

ISNULL is called outside the query string, when passing the parameter value.传递参数值时,在查询字符串外部调用ISNULL

With your script, the @result variable holds the result from sp_executesql execution, not the result from your stored procedure.有了您的脚本中, @result变量保存结果sp_executesql执行,而不是从你的存储过程的结果。 If I understand your case correctly, you need to get the result from your stored procedure in the following way (note, that the result from execution is always an integer and an output parameter is also an option in your case):如果我正确理解您的情况,您需要通过以下方式从您的存储过程中获取结果(请注意,执行结果始终是一个整数,并且输出参数也是您的情况下的一个选项):

DECLARE @sql nvarchar(max)
SET @Sql = 'EXEC @rc = dbo.AAAProc '+ @SomeField1 + ',' + CONVERT(NVARCHAR(MAX), @SomeField2)+', ' + ISNULL(CONVERT(NVARCHAR(MAX), @SomeField3),'null');

DECLARE @result int
DECLARE @rc int
EXEC @result = sp_executesql @sql, N'@rc int OUTPUT', @rc OUTPUT

IF @result = 0  
    PRINT 'Result = ' + CONVERT(NVARCHAR, @rc)
ELSE 
    PRINT 'Error'

Note, that you need to call your procedure using parameters, without string concatenations, to prevent SQL injection attacks:请注意,您需要使用参数调用您的过程,而不使用字符串连接,以防止 SQL 注入攻击:

DECLARE @sql nvarchar(max)
SET @Sql = 'EXEC @rc = dbo.AAAProc @SomeField1, @SomeField2, @SomeFileName';

DECLARE @result int
DECLARE @rc int
DECLARE @SomeField1 int 
DECLARE @SomeField2 int
DECLARE @SomeFileName nvarchar(max)

-- Set values for parameters

EXEC @result = sp_executesql 
                    @sql, 
                    N'@rc int OUTPUT, @SomeField1 int, @SomeField2 int, @SomeFileName nvarchar(max)', 
                    @rc OUTPUT, @SomeField1, @SomeField2, @SomeFileName

PRINT @result

IF @result = 0  
    PRINT 'Result = ' + CONVERT(NVARCHAR, @rc)
ELSE 
    PRINT 'Error'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM