根据表的外键约束对表列表进行排序的最佳方法是什么

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 以便父表在顶部而子表在底部的最佳方法是什么?

Rob*_*ley 6

一个问题是您可能有循环引用。您可能更喜欢禁用约束,执行 ETL,然后重新启用它们。

这也可能是时间问题,因此可能无法填充某些数据,因为您何时从源获取数据。例如,您从表 P 中获取数据,然后从表 C 中获取数据。但是当您从表 C 中获取数据时,您有一行引用了 C 中的一行,而该行引用了 P 中的一行t 有几毫秒前。或者,如果您按其他顺序执行,则在您抓取之前删除 P 中的行。

所以一定要使用一个聪明的脚本。但是你可能会发现你仍然有问题。

我推荐的解决方案是质疑您是否真的想要在这里使用 FK,或者您是否应该使用推断成员进行一些更复杂的查找。

  • 或者在加载之前删除/不检查所有外键约束,然后重新创建/检查它们。 (4认同)