动态SQL从多个表更新一个表?
我有一个表PI_catalog_Update,它将模式名、表名、Count(*)存储为Volume,将max(ETLRunTime)存储为来自多个原始表的LastUpdate。如何构建一个查询,该查询将使用PI_Catalog_中的SchemaName和TableName对原始表进行更新和查询,并在每次运行SP时更新卷和LastUpdate 可能我需要一些动态SQL。我还是不知道该怎么办 该表如下所示:动态SQL从多个表更新一个表?,sql,sql-server,dynamic-sql,Sql,Sql Server,Dynamic Sql,我有一个表PI_catalog_Update,它将模式名、表名、Count(*)存储为Volume,将max(ETLRunTime)存储为来自多个原始表的LastUpdate。如何构建一个查询,该查询将使用PI_Catalog_中的SchemaName和TableName对原始表进行更新和查询,并在每次运行SP时更新卷和LastUpdate 可能我需要一些动态SQL。我还是不知道该怎么办 该表如下所示: SchemaName TableName Volume LastUpd
SchemaName TableName Volume LastUpdate
ProdInsights_In abc 4680816 2017-06-04 00:00:00.000
ProdInsights_In bcd 52250 2017-06-04 00:00:00.000
ProdInsights_In def 744225 2017-06-04 00:00:00.000
ProdInsights_In gih 668502 2017-06-04 00:00:00.000
MERGE
INTO [dbo].[PI_Project_Catalogue] t1
USING [ProdInsights_In].[View_Table_Catalogue] t2
ON t1.SchemaName = t2.SchemaName
and t1.TableName = t2.TableName
WHEN MATCHED THEN
UPDATE
SET t1.Volume = t2.Volume
,t1.LastUpdate = t2.LastUpdate
WHEN NOT MATCHED THEN
INSERT (SchemaName, TableName, Volume, LastUpdate)
VALUES (t2.SchemaName. t2.TableName, t2.Volume, t2.LastUpdate)
我编写的查询是另一种方式,我从原始表[ProdInsights\u In].[view\u table\u catalog]创建了一个视图。视图如下所示:
CREATE VIEW [ProdInsights_In].[View_Table_Catalogue] AS
select
'ProdInsights_In' as SchemaName
,'abc' as TableName
,Count(*) Volume
,MAX(ETLRunTime) as LastUpdate
From [ProdInsights_In].[abc]
Union All
select
'ProdInsights_In' as SchemaName
,'bcd' as TableName
,Count(*) Volume
,MAX(ETLRunTime) as LastUpdate
From [ProdInsights_In].[bcd]
Union All ....
然后我使用下面的SP从视图中更新PI_catalog_更新表。
程序如下所示:
SchemaName TableName Volume LastUpdate
ProdInsights_In abc 4680816 2017-06-04 00:00:00.000
ProdInsights_In bcd 52250 2017-06-04 00:00:00.000
ProdInsights_In def 744225 2017-06-04 00:00:00.000
ProdInsights_In gih 668502 2017-06-04 00:00:00.000
MERGE
INTO [dbo].[PI_Project_Catalogue] t1
USING [ProdInsights_In].[View_Table_Catalogue] t2
ON t1.SchemaName = t2.SchemaName
and t1.TableName = t2.TableName
WHEN MATCHED THEN
UPDATE
SET t1.Volume = t2.Volume
,t1.LastUpdate = t2.LastUpdate
WHEN NOT MATCHED THEN
INSERT (SchemaName, TableName, Volume, LastUpdate)
VALUES (t2.SchemaName. t2.TableName, t2.Volume, t2.LastUpdate)
您可以避免使用动态sql,并使用系统视图来获取行计数,而不是从…为每个表执行
select count(*)
select
[SchemaName]= s.name
, [TableName] = o.name
, [row_count] = p.rows
from sys.partitions p
inner join sys.indexes i
on p.object_id = i.object_id
and p.index_id = i.index_id
and i.index_id < 2
inner join sys.objects o
on i.object_id = o.object_id
inner join sys.schemas s
on o.schema_id = s.schema_id
where o.is_ms_shipped=0
您可以使用单独的语句进行更新,然后插入,而不是使用merge
。我使用了merge
,因为这是您在问题中所使用的,并添加了和(holdlock)
rextester演示:
返回:
+------------+-----------+--------+---------------------+
| SchemaName | TableName | Volume | LastUpdate |
+------------+-----------+--------+---------------------+
| dbo | a | 1 | 01.01.2017 00:00:00 |
| dbo | c | 2 | 06.06.2017 00:00:00 |
| dbo | d | 3 | 06.06.2017 00:00:00 |
+------------+-----------+--------+---------------------+
使用此虚拟数据:
create table pi_Project_Catalogue (SchemaName sysname collate Latin1_General_CI_AS, TableName sysname collate Latin1_General_CI_AS, Volume bigint, LastUpdate date)
create table a (id int not null identity(1,1) primary key clustered, ETLRunTime date)
insert into a values ('20170101');
create table b (id int not null identity(1,1) ); -- no ETLRunTime column
insert into b default values
create table c (id int not null identity(1,1), ETLRunTime date );
insert into c values (sysutcdatetime()),(sysutcdatetime());
create table d (id int not null identity(1,1), ETLRunTime date );
insert into d values (sysutcdatetime()),(sysutcdatetime()),(sysutcdatetime());
合并
参考:
我建议您使用触发器而不是动态查询。您可以发布您目前编写的查询吗?我已经用代码编辑了问题部分。谢谢。嗨,这是一种很好的方式。但是sysutcdatetime()总是向我显示当前日期时间,即使我没有更新某些表的任何内容。实际上,我有一个工具,它每天在这些表中插入数据,并在该工具更新的所有表中插入名为ETLRunTime的列。我想把Max(ETLRunTime)
作为最后一次更新。有可能吗?我已经用我写的查询编辑了这个问题,但是查询看起来不够好和有效。Thanks@DataPoliceInc. 更新了我的答案以包含ETL运行时
。当我第一次读到这个问题时,不知怎的错过了。嗨,这是一个很好的方式。非常感谢你的努力。我学到了一些新东西。谢谢..@DatapolicyInc。很乐意帮忙!