计算删除SQL Server的顺序

时间:2011-10-27 21:28:15

标签: sql sql-server-2008

我有一个庞大的数据库,有很多很少记录的约束。 我需要编写一些SQL来清除这些表的子集中的数据,我不知道如何确定删除的顺序。显然我需要在相应的PK表之前删除FK表,但正如我所说,这些关系是纠结的,并且记录不完整。

是否有可用的工具可以让我确定删除语句的正确顺序?

(我查看了Red Gate工具,并且非常惊讶地发现它们不支持我正在使用的SQL Server 2008R2。)

2 个答案:

答案 0 :(得分:0)

我认为您可以构建一个程序来获取订单。这是一个想法:

CREATE PROCEDURE get_delete_order
    @tablename varchar(MAX)
as

BEGIN
    -- Get directed related tables
    SELECT base.name base_name
         , related.name rel_name
      into #RELATED_TABLES
      FROM sys.sysobjects base 
      left join sys.sysforeignkeys on fkeyid = base.id
      left join sys.sysobjects related on related.id = rkeyid
                                      and related.id <> base.id
                                      and related.xtype = 'U'
    WHERE base.xtype = 'U'
      and base.name = @tablename

    -- Get indirected related tables using recursive call
    CREATE #ALL_RELATED_TABLES (rel_name varchar(max), del_order int)
    INSERT INTO #ALL_RELATED_TABLES (rel_name, del_order)
        SELECT rel_name
             , -1
          FROM #RELATED_TABLES

    DECLARE @relate_table
    DECLARE IND_REL CURSOR FOR
        SELECT rel_Name
          FROM #RELATED_TABLES
    open IND_REL
    fetch next from IND_REL into @relate_table

    -- TODO: IMPORTANT!!! Avoid infinite loop here
    while (@@FETCH_STATUS = 0)
    begin
        INSERT INTO #ALL_RELATED_TABLES (rel_name, del_order)
            exec get_delete_order(@relate_table)
        fetch next from IND_REL into @relate_table
    end
    close IND_REL
    deallocate IND_REL

    -- Return resultset
      SELECT rel_name
           , del_order + 1
        FROM #ALL_RELATED_TABLES
    ORDER BY del_order DESC
END

这是未经考验的,只是一个想法。 真正的程序会更复杂:)

答案 1 :(得分:0)

只需在此处粘贴Fred Fred博客中的脚本以备将来参考。对我来说效果很好。

select cast(f.name  as varchar(255)) as foreign_key_name
    , r.keycnt
    , cast(c.name as  varchar(255)) as foreign_table
    , cast(fc.name as varchar(255)) as  foreign_column_1
    , cast(fc2.name as varchar(255)) as foreign_column_2
    ,  cast(p.name as varchar(255)) as primary_table
    , cast(rc.name as varchar(255))  as primary_column_1
    , cast(rc2.name as varchar(255)) as  primary_column_2
from sysobjects f
inner join sysobjects c on  f.parent_obj = c.id
inner join sysreferences r on f.id =  r.constid
inner join sysobjects p on r.rkeyid = p.id
inner  join syscolumns rc on r.rkeyid = rc.id and r.rkey1 = rc.colid
inner  join syscolumns fc on r.fkeyid = fc.id and r.fkey1 = fc.colid
left join  syscolumns rc2 on r.rkeyid = rc2.id and r.rkey2 = rc.colid
left join  syscolumns fc2 on r.fkeyid = fc2.id and r.fkey2 = fc.colid
where f.type =  'F'
ORDER BY cast(p.name as varchar(255))