SQL Server动态SQL-从表列表获取输出

SQL Server动态SQL-从表列表获取输出,sql,sql-server,dynamic-sql,Sql,Sql Server,Dynamic Sql,我试图循环遍历一个包含表名列表的临时表变量。我只想简单地计算每个表中DateTracked列大于30天的行数。动态地将FROM@tblName变量更改为存储记录计数,然后将其插入跟踪表时遇到问题。最后,我将使用一个游标来循环遍历每个表,但我只想首先为单个表记录这个逻辑。以下是我的测试代码: DECLARE @tblName as NVARCHAR(MAX) DECLARE @q as NVARCHAR(MAX) SET @q = 'Select Count(DateTracked) FROM A

我试图循环遍历一个包含表名列表的临时表变量。我只想简单地计算每个表中DateTracked列大于30天的行数。动态地将FROM@tblName变量更改为存储记录计数,然后将其插入跟踪表时遇到问题。最后,我将使用一个游标来循环遍历每个表,但我只想首先为单个表记录这个逻辑。以下是我的测试代码:

DECLARE @tblName as NVARCHAR(MAX)
DECLARE @q as NVARCHAR(MAX)
SET @q = 'Select Count(DateTracked) FROM Audit.' + @tblName + ' WHERE DateTracked > DATEADD(dd, -30, CAST(GETDATE() as date))'

--DECLARE @tblNameTable TABLE
--(
--  tableName NVARCHAR(MAX)
--)
--INSERT INTO @tblNameTable VALUES (N'myTestTable')

DECLARE @ExpectedRecordsToMove AS TABLE (col1 int)
INSERT INTO @ExpectedRecordsToMove EXECUTE sp_executesql @q, N'@tblName nvarchar(500)', @tblName = 'myTestTable'

SELECT * FROM @ExpectedRecordsToMove
找到了解决办法

DECLARE @tblName as NVARCHAR(MAX) = 'tblAutoDispatch_DispatchStatus_Map_Tracking'
DECLARE @q as NVARCHAR(MAX) = 'SELECT Count(DateTracked) FROM Audit.' + @tblName + ' WHERE DateTracked > DATEADD(dd, -30, CAST(GETDATE() as date))'

DECLARE @ExpectedRecordsToMove TABLE
(
    ExpectedRecordsToMove Int
)
INSERT INTO @ExpectedRecordsToMove
EXECUTE sp_executesql @q

SELECT * FROM @ExpectedRecordsToMove
注:OP提供的问题答案

sp_executesql还允许输出参数。可以在内部查询中分配变量并返回值

DECLARE @tblName AS NVARCHAR(MAX) = N'tblAutoDispatch_DispatchStatus_Map_Tracking';
DECLARE @q AS NVARCHAR(MAX)
    = N'SELECT @rowcount = COUNT(DateTracked) FROM Audit.' + @tblName
      + N' WHERE DateTracked > DATEADD(dd, -30, CAST(GETDATE() as date))';

DECLARE @rowcount INT;

EXECUTE sp_executesql
    @query = @q,
    @parameters = N'@rowcount INT OUTPUT',
    @rowcount = @rowcount OUTPUT;

SELECT
    @rowcount;
实际上,您可以不使用光标,一次完成查询

必须使用QUOTENAME以确保表名不会导致语法错误 不能参数化表名,它必须直接插入到动态SQL中 声明@tablenames表schemaName sysname,tblName sysname; -插入架构和表名 声明@sql nvarcharmax=N' 选择 ISNULLtblName,总计为tblName, SUMrowcount作为rowcount 从…起 ' + 选择字符串\u AGGCAST N'选择'+QUOTENAMEtn.schemaName,+N'.'+QUOTENAMEtn.tblName,+N'作为tblName, CountDateTracked为行计数 来自“+QUOTENAMEtn.schemaName+N”。+QUOTENAMEtn.tblName+N” 其中DateTracked>DATEADDdd,-30,CASTGETDATE作为日期' 作为nvarcharmax,N' 联合所有 ' 来自@tablenames tn 在tn.schemaName=SCHEMA\u NAMEt.SCHEMA\u id和tn.tblName=t.name上连接sys.t表 +不 作为表格 按ROLLUPBLNAME分组; '; 打印@sql;-用于测试 EXEC@sql; 如果您的SQL Server版本中没有STRING_AGG,则必须改用FOR XML
无法参数化@q,因为即使在动态SQL中也无法参数化表名;整个语句必须动态生成,因为@tblName必须插入到文本中。如果您在生成@q之前设置@tblName,您将获得与循环中相同的效果。不,这正是不起作用的。同样,表名不能是参数。”选择…“++@tblName+”其中…”是正确的,但是@tblName必须已经在那里有一个值,并且不应作为参数传递。在您的示例中,将@tblName声明为SYSNAME='myTestTable'。我现在明白了。一旦生成了该语句并将其插入到可以引用的变量中,如何获取sp_executesql的输出?不确定问题是什么-插入。。。EXEC使用表变量,因此代码的其余部分就可以了。插入当然不应该发生在动态生成的语句中,因为这样就不能引用外部作用域的变量。我现在明白了。我声明的是一个局部变量,而不是临时表变量。我在最初的帖子中没有描述这一点,但我使用游标循环200个表,使用WHILE循环批处理删除/输出,所以在这个场景中使用游标是可以的,因为没有性能影响,我仍然使用基于集合的操作来处理实际事务。