执行动态查询并将值赋值给两个变量
Execute dynamic query and assign values into two variables
我要执行以下动态查询并将结果分配给两个变量。
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);
但是我收到一个错误:
Msg 137, Level 15, State 1, Line 5 Must declare the scalar variable
"@MaxDate".
您可以尝试将变量放在字符串中:
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)
正如@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
两次。
您可以为在动态 SQL 和动态 SQL 之外声明的参数使用相同的名称 @MinDate
,但我更喜欢给它们不同的名称(@MinDate
和 @MinDate_
), 所以我不会混淆什么是什么。
我要执行以下动态查询并将结果分配给两个变量。
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);
但是我收到一个错误:
Msg 137, Level 15, State 1, Line 5 Must declare the scalar variable "@MaxDate".
您可以尝试将变量放在字符串中:
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)
正如@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
两次。
您可以为在动态 SQL 和动态 SQL 之外声明的参数使用相同的名称 @MinDate
,但我更喜欢给它们不同的名称(@MinDate
和 @MinDate_
), 所以我不会混淆什么是什么。