我有一个表PI_Catalogue_Update,它将Schema Name,Table Name,Count(*)作为Volume和max(ETLRunTime)存储为来自多个原始表的LastUpdate。如何构建一个查询,该查询将使用PI_Catalogue_Update中的SchemaName和TableName并查询原始表,并在每次运行SP时更新卷和LastUpdate。
可能我需要一些动态SQL。我仍然无法弄明白该怎么做。
表格如下:
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
我写的查询是另一种方法,我创建了一个原始表格的视图,[ProdInsights_In]。[View_Table_Catalogue] .View看起来像:
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从View中更新PI_Catalogue_Update表。 程序如下:
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)
答案 0 :(得分:2)
您可以避免使用动态sql并使用系统视图来获取行计数,而不是为每个表执行select count(*) from ...
。
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
作为更新:
update picu
set [Volume] = p.rows
, [LastUpdate] = sysutcdatetime()
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
inner join PI_Catalogue_Update picu
on picu.SchemaName = s.name
and picu.TableName = o.name
参考:
使用临时表和循环来获取max(ETLRunTime)
以使用动态sql进行更新:
/* --- get all tables and row count that have `ETLRunDate` column. --- */
create table #tmp (
id int not null identity(1,1)
, SchemaName sysname collate Latin1_General_CI_AS -- set collation to match collation of `pi_Project_Catalogue`
, TableName sysname collate Latin1_General_CI_AS
, Volume bigint
, LastUpdate date
);
insert into #tmp (SchemaName, TableName, Volume)
select
[SchemaName]= s.name
, [TableName] = o.name
, [Volume] = 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
and exists (
select 1
from sys.columns c
where c.object_id = o.object_id
and c.name = 'ETLRunTime'
)
/* --- loop --- */
declare @c bigint = (select max(id) from #tmp);
declare @id bigint = 1;
declare @sql nvarchar(4000);
declare @params nvarchar(32) = N'@id bigint';
while @id <= @c
begin;
select @sql = N'
update #tmp
set LastUpdate = (
select max(ETLRunTime)
from '+quotename(SchemaName)+'.'+quotename(TableName)+'
)
where id = @id;'
from #tmp where id = @id
exec sp_executesql @sql, @params, @id;
set @id = @id+1;
end;
/* --- merge --- */
merge into [dbo].[pi_Project_Catalogue] with (holdlock) as tar
using #tmp as src
on tar.SchemaName = src.SchemaName
and tar.TableName = src.TableName
when matched then update
set tar.Volume = src.Volume
, tar.LastUpdate = src.LastUpdate
when not matched then insert (SchemaName, TableName, Volume, LastUpdate)
values (src.SchemaName, src.TableName, src.Volume, src.LastUpdate);
您可以使用单独的语句进行更新,然后插入,而不是您使用的merge
。我使用merge
,因为这是您在问题中的内容,添加了with (holdlock)
。
rextester演示:http://rextester.com/HCOLM75894
返回:
+------------+-----------+--------+---------------------+
| 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());
merge
参考:
MERGE
Statement - Aaron Bertrand Merge
- Dan Guzman MERGE
Bug - Paul White merge
statement - Aaron Bertrand MERGE
, please read this! - Aaron Bertrand Merge
Statement (LCK_M_RS_U locks) - Kendra Little merge
statements the right way - David Stein