首页 > 解决方案 > 通过动态 SQL 设置 SQL 变量

问题描述

我知道我想太多了,但是我已经反对这个太久了,所以我正在寻求帮助。

这是我要运行的语句:SELECT @cntMax = MAX(id) FROM [Raw_Item-FieldReport] 但是,表名是一个变量@reportTable

这不起作用:

SET @sql = 'SELECT @cntMax = MAX(id) FROM @reportTable'
EXEC sp_executesql @sql

我什至尝试在其中包含实际的表名,SET @sql但这也不起作用。我没想到会这么难,请告诉我我错过了一些简单/明显的东西。

对于那些想要它的人,这是完整的代码:

DECLARE
    @inTable nvarchar(255) = 'Raw_Item',
    @reportTable nvarchar(255),
    @fieldName nvarchar(255),
    @cnt int,
    @cntMax int,
    @sql nvarchar(max)

SET @reportTable = @inTable + '-FieldReport'

SET @cnt = 1
SELECT @cntMax = MAX(id) FROM [Raw_Item-FieldReport]
PRINT @cntMax
SET @cntMax = 0

SET @sql = 'SELECT @cntMax = MAX(id) FROM [Raw_Item-FieldReport]'
EXEC sp_executesql @sql
PRINT @cntMax

SQL Server 12.0.2008.8(在 Azure 上)

标签: sqlsql-servervariablesdynamic-sql

解决方案


您需要使用输出参数,否则 SQL Server 不知道如何在动态 SQL 中连接@cntMax@cntMax 不在动态 SQL 中,因为它们是不同的范围。为了保护自己免受 SQL 注入(此处此处的一些提示),请始终检查您的对象是否存在,并使用QUOTENAME()而不是手动添加方括号(并且QUOTENAME()在从用户输入或变量构建对象名称时应始终使用,即使它们没有破折号之类的坏字符):

DECLARE @sql         nvarchar(max),
        @inTable     nvarchar(255) = N'Raw_Item',
        @reportTable nvarchar(255);

SET @reportTable = N'dbo.' + QUOTENAME(@inTable + '-FieldReport');

IF OBJECT_ID(@reportTable) IS NOT NULL
BEGIN
  SET @sql = N'SELECT @cntMax = MAX(id) FROM ' + @reportTable + N';';

  EXEC sys.sp_executesql @sql,
           N'@cntMax int output', 
           @cntMax = @cntMax OUTPUT;

  PRINT @cntMax;
END
ELSE
BEGIN
  PRINT 'Nice try, h@xx0rs!';
END

始终使用模式引用( dbo),始终使用语句终止符,并且请尽量避免使用无效的标识符字符命名事物,例如破折号 ( -)。还有一个提示:始终在 .N上使用前缀N'nvarchar string literals'


推荐阅读