2012-04-16 66 views
0

我有大量表(大约40)包含大约4000万以上车辆的快照数据。每个快照表都处于特定时间点(本季度末),并且在结构方面相同。对多个表按顺序运行相同的SQL代码

虽然我们的大部分分析都是针对单个快照,但有时我们需要针对所有快照一次运行一些分析。例如,我们可能需要从每个快照创建一个包含所有福特福克斯汽车的新表。

为了实现这一目标,我们目前有两个选择:
一)写一个很长很长,长的批处理文件,一遍又一遍重复相同的代码,只是改变了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将非常简单,我们将从我们已经在原始表中获得的所有索引中受益。

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

回答

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])) + ' ...

+0

这将工作跨单独的数据库实例吗?幸运的是,所有的表都有相同的命名模式(dbo.LicStock_yyyy),但为了让我们的实例保持在1 TB以下,它们被分割成几个独立的数据库。 – DarylLloyd 2012-04-17 06:56:24

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 ''' [email protected] + ''', 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