使用返回值作为每一行的列值执行动态SQL

时间:2019-05-24 17:58:35

标签: sql-server

我有一个相当简单的查询,为了删除临时表,我开始对其进行修改,因为我们在许多不同的系统和客户端上都存在并发问题。

现在,简单的解决方案是将查询分解为多个单独的查询,以复制SQL之前所做的事情。

我正在尝试找到一种方法来将动态SQL查询的结果作为列值返回。新查询非常简单,它会在系统对象中查找具有特定格式和输出的所有表。我所缺少的是,对于每条记录,我都需要在每个表上输出动态查询的结果。

查询:

SELECT [name] as 'TableName' 
FROM SYSOBJECTS WHERE xtype = 'U' 
AND (CHARINDEX('_PCT', [name]) <> 0 
OR CHARINDEX('_WHT', [name]) <> 0)

所有这些表都有一个称为Result的公共列,该列为浮点数。我想做的是返回某个通用的WHERE子句下的该列的计数,该子句也将适用于所有表。

所需查询(我知道这是无效的)将是:

SELECT [name] as 'TableName',
sp_executesql 'SELECT COUNT(*) FROM ' + [name] + ' WHERE Result > 0 OR (Result < 139 AND CurrentIndex < 15)' as 'ResultValue'
FROM SYSOBJECTS WHERE xtype = 'U' 
AND (CHARINDEX('_PCT', [name]) <> 0 
OR CHARINDEX('_WHT', [name]) <> 0)

以前很容易。我们有一个包含2列的临时表,并且首先填充了表名。然后,我们迭代临时表并执行动态sql,并在OUTPUT变量中返回值,然后简单地更新临时表的记录,最后返回该表。

我尝试了标量函数,但是它不支持动态SQL,所以它不起作用。我宁愿不为13,000〜个表创建13,000〜个不同的查询。

我尝试使用参考表并使用触发器来更新状态,但是这会使系统速度大大降低。平均表插入和删除2千8百万条记录。原始的临时表查询由于建立了很好的索引而只花了5-6分钟的时间来执行,而现在我们达到25-30分钟。

除了查询表列表然后客户端一一查询每个表以了解其状态之外,还有其他解决方案吗?

如果某些新功能现在可用,我们正在使用SQL Server 2017

1 个答案:

答案 0 :(得分:1)

您可以根据需要使用此脚本(在SQL Server 2016中经过测试)。

已更新:由于结果现在是单个集合,因此现在应该可以使用。

EXEC sp_msforeachtable
@precommand = 'CREATE TABLE ##Statistics 
    (TableName varchar(128) NOT NULL, 
    NumOfRows int)',
@command1 ='INSERT INTO ##Statistics (TableName, NumOfRows)
    SELECT ''?'' Table_Name, COUNT(*) Row_Count FROM ? WHERE Result > 0 OR (Result < 139 AND CurrentIndex < 15)',
@postcommand = 'SELECT TableName, NumOfRows FROM ##Statistics;
    DROP TABLE ##Statistics'
,@whereand = ' And Object_id In (Select Object_id From sys.objects
    Where name like ''%_PCT%'' OR name like ''%_WHT%'')'

有关 sp_msforeachtable 的详细信息,请访问this链接