Jam*_*mes 7 sql-server sql-server-2016
我正在处理一项 etl 任务,该任务从一个模式中获取表(没有约束)并将它们插入到相同的表中(加上约束)。
我不想打出无数的插入语句,所以我写了一些如下所示的动态 sql:
declare @table varchar(255),
@stgtable varchar(255),
@columns varchar(max),
@sql nvarchar(max)
declare c cursor for
select table_name from INFORMATION_SCHEMA.tables
open c
fetch from c into @table
while @@FETCH_STATUS = 0
begin
set @stgtable = replace(right(@table, len(@table) - 1), 'LZSTG','STG')
--print @stgtable
select @columns = stuff( (
select ', ' + Column_Name from information_schema.columns
where Table_Name = @table
for xml path ('')),1,2,'')
--print @columns
begin try
set @sql = 'truncate table ' + @stgtable
exec sp_executesql @sql
set @sql = 'insert into ' + @stgtable + ' (' + @columns + ') select ' + @columns + ' from ' + @table
print @sql
exec sp_executesql @sql
set @sql = 'select * from ' + @stgtable
exec sp_executesql @sql
end try
begin catch print 'womp womp ' + @stgtable end catch
fetch next from c into @table
end
close c
deallocate c
Run Code Online (Sandbox Code Playgroud)
问题:如果您按照默认顺序浏览 information_schema.tables,插入经常会因为外键冲突而失败。
如果我想让这个解决方案起作用,我必须先插入父表,然后再插入子表。
我有这个,但它几乎不是一个铁定的解决方案:
with fks as
(SELECT obj.name AS FK_NAME,
sch.name AS [schema_name],
tab1.name AS [table_name],
col1.name AS [column],
tab2.name AS [referenced_table],
col2.name AS [referenced_column]
FROM sys.foreign_key_columns fkc
INNER JOIN sys.objects obj
ON obj.object_id = fkc.constraint_object_id
INNER JOIN sys.tables tab1
ON tab1.object_id = fkc.parent_object_id
INNER JOIN sys.schemas sch
ON tab1.schema_id = sch.schema_id
INNER JOIN sys.columns col1
ON col1.column_id = parent_column_id AND col1.object_id = tab1.object_id
INNER JOIN sys.tables tab2
ON tab2.object_id = fkc.referenced_object_id
INNER JOIN sys.columns col2
ON col2.column_id = referenced_column_id AND col2.object_id = tab2.object_id)
select t.table_name, fks.* from
information_schema.tables t
left join fks on t.table_name = fks.table_name
order by referenced_table
Run Code Online (Sandbox Code Playgroud)
问题订购 information_schema 以便父表在顶部而子表在底部的最佳方法是什么?
一个问题是您可能有循环引用。您可能更喜欢禁用约束,执行 ETL,然后重新启用它们。
这也可能是时间问题,因此可能无法填充某些数据,因为您何时从源获取数据。例如,您从表 P 中获取数据,然后从表 C 中获取数据。但是当您从表 C 中获取数据时,您有一行引用了 C 中的一行,而该行引用了 P 中的一行t 有几毫秒前。或者,如果您按其他顺序执行,则在您抓取之前删除 P 中的行。
所以一定要使用一个聪明的脚本。但是你可能会发现你仍然有问题。
我推荐的解决方案是质疑您是否真的想要在这里使用 FK,或者您是否应该使用推断成员进行一些更复杂的查找。
归档时间: |
|
查看次数: |
282 次 |
最近记录: |