截断表与外键

时间:2013-12-19 07:09:26

标签: sql-server sql-server-2008 tsql sql-server-2005 sql-server-2008-r2

我有一个拥有超过1000个表的数据库。我正在创建新的空白设置。为此,我必须截断所有表,但我不希望截断一些表,所以我在表上创建并将名称存储在表中。

    ----------- Create hardcode table ----------------------
    Create table TblHardCodeTableNotToTruncate(TableName varchar(100))
    go
    insert into TblHardCodeTableNotToTruncate
    select 'TblHardCodeTableNotToTruncate'
    go

    ---- insert the table names which dont wish to truncate ------------
Insert into TblHardCodeTableNotToTruncate
select 'TblAccount'
go
Insert into TblHardCodeTableNotToTruncate
select 'TblCity'
go

等,以下是我用来截断除了这些插入表之外的所有表的查询

------------------------- Truncate all the tables except the tables specified in the Hardcode table -------------------------

EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'

GO

EXEC sp_MSForEachTable 'ALTER TABLE ? DISABLE TRIGGER ALL'

GO

DECLARE @TBLTEMP TABLE(TABLENAME VARCHAR(100))
insert into @TBLTEMP
select name from sysobjects where xtype = 'U'

delete from @TBLTEMP where tablename in (
select tablename from TblHardCodeTableNotToTruncate)

DECLARE @SQLQUERY VARCHAR(MAX) =''
DECLARE @INTCNT INT = 1

DECLARE @TABLENAME VARCHAR(100) =''


WHILE (SELECT COUNT(*) FROM @TBLTEMP) > 0
BEGIN


            select  top 1 @TABLENAME = TABLENAME from @TBLTEMP
            SET @SQLQUERY = 'Truncate table ' + @TABLENAME
            EXEC(@SQLQUERY)
            PRINT @SQLQUERY
    DELETE FROM @TBLTEMP WHERE TABLENAME = @TABLENAME   
END
go

EXEC sp_MSForEachTable  'ALTER TABLE ? CHECK CONSTRAINT ALL'

GO

EXEC sp_MSForEachTable 'ALTER TABLE ? ENABLE TRIGGER ALL'
go

但我得到错误外键引用错误。我知道在做之前我需要放弃约束。但有没有办法做到这一点,因为我不能删除然后截断并再次添加这么多的表。我们可以在下面编写任何独特的脚本,如果存在则会删除约束,截断表并再次将删除的约束添加到表中。

2 个答案:

答案 0 :(得分:3)

我担心没有限制就没有办法做到这一点, 你可以编写一个代码来提取表的约束并删除它们很简单。

创建一个临时表并使用此代码获取表约束,并注意sysconstraints.status必须为1或3才能获得外键和主键:

Select  SysObjects.[Name] As "Constraint Name",
        Tabls.[Name] as "Table Name",
        Cols.[Name] As "Column Name"
From SysObjects Inner Join 
(Select [Name],[ID] From SysObjects) As Tabls
On Tabls.[ID] = Sysobjects.[Parent_Obj] 
Inner Join sysconstraints On sysconstraints.Constid = Sysobjects.[ID] 
Inner Join SysColumns Cols On Cols.[ColID] = sysconstraints.[ColID] 
And Cols.[ID] = Tabls.[ID]
where sysconstraints.status in (1, 3)
order by [Tabls].[Name] 

你必须在截断后重新创建这些约束,这也很简单,但我不会做你所有的工作:)

答案 1 :(得分:0)

即使所有tabled都为空并禁用所有约束,截断也会因FK存在而失败。你真的必须放弃它。

您可以创建一个脚本来自动化它(截断所有删除和重新创建FK的表) 我在这里找到一个(谨慎使用) http://www.sqlservercentral.com/scripts/Development/62892/

此外,如果您只想创建一个“毯子”数据库,您可以导出脚本以创建所有对象,并只填充您需要的少数(域?)表。