执行动态查询并将值分配给两个变量

问题描述 投票:1回答:2

我有以下动态查询来执行并将结果分配给两个变量。

DECLARE @MinDate VARCHAR(10) = ''
DECLARE @MaxDate VARCHAR(10) = ''

SET @SQL = 'SELECT @MinDate = Convert(Varchar,Cast(Min(ColumnDate) AS DATE),105),
                   @MaxDate = Convert(Varchar,Cast(Max(ColumnDate) AS DATE),105)
            FROM ['+@Table+']';

PRINT(@SQL);
EXEC(@SQL)

PRINT(@MinDate);
PRINT(@MaxDate);

但我收到一个错误:

消息137,级别15,状态1,行5必须声明标量变量“@MaxDate”。

sql sql-server sql-server-2008-r2
2个回答
1
投票

正如@Jeroen Mostert在评论中正确地说,你需要使用sp_executesql而不是EXEC

sp_executesql允许为动态SQL提供参数,这些参数可以标记为OUTPUT,这里需要它。

此外,最好使用适当的参数来防止SQL注入问题。在你的例子中,@MinDate@MaxDate可以而且应该作为适当的参数。 @Table不能成为参数,因此它将保持连接到SQL字符串。只有这部分才能继续使用SQL注入。

这是一个例子:

DECLARE @MinDate_ VARCHAR(10) = '';
DECLARE @MaxDate_ VARCHAR(10) = '';
DECLARE @SQL nvarchar(max);

SET @SQL = 
    'SELECT 
        @MinDate = Convert(Varchar,Cast(Min(ColumnDate) AS DATE),105),
        @MaxDate = Convert(Varchar,Cast(Max(ColumnDate) AS DATE),105)
    FROM ['+@Table+']';

EXEC sp_executesql @SQL
    ,N'@MinDate VARCHAR(10) OUTPUT, @MaxDate VARCHAR(10) OUTPUT'
    ,@MinDate = @MinDate_ OUTPUT
    ,@MaxDate = @MaxDate_ OUTPUT
;

SELECT @MinDate_, @MaxDate_;

请注意,您必须指定OUTPUT两次。

您可以使用相同的名称@MinDate作为在动态SQL和动态SQL之外声明的参数,但我更喜欢给它们不同的名称(@MinDate@MinDate_),所以我不会混淆什么是什么。


0
投票

您可以尝试将变量放在字符串中:

SET @SQL = '
DECLARE @MinDate VARCHAR(10) = ''''
DECLARE @MaxDate VARCHAR(10) = ''''

SELECT @MinDate = Convert(Varchar,Cast(Min(ColumnDate) AS DATE),105),
       @MaxDate = Convert(Varchar,Cast(Max(ColumnDate) AS DATE),105)
FROM ['+@Table+']

PRINT(@MinDate)
PRINT(@MaxDate)
            '
EXEC(@SQL)
© www.soinside.com 2019 - 2024. All rights reserved.