依次对许多表运行相同的SQL代码

时间:2012-04-16 15:02:23

标签: sql sql-server sql-server-2005

我有许多表(大约40个)包含大约4000万多辆车的快照数据。每个快照表都在特定的时间点(季度末),并且在结构方面是相同的。

虽然我们的大多数分析都针对单个快照,但有时我们需要同时对所有快照进行一些分析。例如,我们可能需要在每个快照中构建一个包含所有福特福克斯汽车的新表。

为实现这一目标,我们目前有两种选择:
a)写一个长,长,长的批处理文件一遍又一遍地重复相同的代码,只需更改FROM子句
[缺点 - 在一个块中编写和更改单行代码需要很长时间才需要在所有其他块中进行繁琐的更改]
b)使用视图将所有表合并在一起并查询而不是 [缺点 - 我们的表存储在单独的数据库实例中,无法编制索引,加上生成的视图类似于6亿条长125列宽的记录,因此非常慢]

所以,我想知道的是我是否可以使用动态sql或将SQL放入循环以截断所有表。这将是:

for each *table* in TableList
INSERT INTO output_table
SELECT *table* as OriginTableName, Make, Model
FROM *table*
next *table* in TableList

这可能吗?这意味着当我们的客户端更改他们需要的东西(非常经常发生!)时更新原始SQL将非常简单,我们将从原始表中已有的所有索引中受益。

任何指针,建议或帮助将不胜感激。

2 个答案:

答案 0 :(得分:3)

如果您可以识别您的表格(例如命名模式),您可以简单地说:

DECLARE @sql NVARCHAR(MAX);

SELECT @sql = N'';

SELECT @sql = @sql + 'INSERT output_table SELECT ''' + name + ''', Make, Model
    FROM dbo.' + QUOTENAME(name) + ';'
FROM sys.tables 
WHERE name LIKE 'pattern%';
-- or WHERE name IN ('t1', 't2', ... , 't40');

EXEC sp_executesql @sql;

这假设它们都在dbo架构中。如果不是,则调整很简单......只需将dbo替换为' + QUOTENAME(SCHEMA_NAME([schema_id])) + ' ...

即可

答案 1 :(得分:0)

最后我使用了两种方法:
另一个论坛上有人建议使用sp_msforeachtable和一个包含所有表名的表。他们的建议是:

create table dbo.OutputTable (OriginTableName nvarchar(500), RecordCount INT)
create table dbo.TableList (Name nvarchar (500))

insert dbo.TableList 
        select '[dbo].[swap]'
union   select '[dbo].[products]'
union   select '[dbo].[structures]'
union   select '[dbo].[stagingdata]'

exec sp_msforeachtable @command1 = 'INSERT INTO dbo.OutputTable SELECT ''?'',    COUNT(*)     from ?'
,@whereand = 'and syso.object_id in (select object_id(Name) from dbo.TableList)'             

select * from dbo.OutputTable

这对某些查询非常有效,但似乎受到以下事实的影响:在查询中不能使用GROUP BY子句(或者,至少,我找不到这样做的方法)。

我使用的最终解决方案是使用动态SQL和包含表名的查找表。以一种非常简单的形式,这看起来像:

DECLARE @TableName varchar(500)
DECLARE @curTable CURSOR
DECLARE @sql NVARCHAR(1000)

SET @curTable = CURSOR FOR 
SELECT [Name] FROM Vehicles_LookupTables.dbo.AllStockTableList

OPEN @curTable
FETCH NEXT
FROM @curTable INTO @TableName

WHILE @@FETCH_STATUS = 0
BEGIN

SET @sql = 'SELECT ''' +@TableName + ''', Make, sum(1) as Total FROM ' + @TableName + ' GROUP BY Make'
EXEC sp_executesql @sql

FETCH NEXT
FROM @curTable INTO @TableName

END
CLOSE @curTable
DEALLOCATE @curTable