Technical Article

How to empty database

,

Last week we discussed about problem how to do some data action on all tables and not to break relationship rules.

If you consult sysobjects and sysforeignkeys you will be able to create the hierarchy of tables either from root(s) to leaves or vice-versa.

Once when you have this list you can construct dynamic script and do the action against these tables. Possibilities are unlimited.

This example will empty the content of current database. I found this useful when end users are doing final test in production environment (because they don't have test environment) and after that they ask to switch from test to production. Or, you can export (bcp out, when table order is not important) data and than import (bcp in, when proper order is precondition for successful execution).

set nocount on

declare @Order int
Set @Order = 1

IF Exists(SELECT * FROM tempdb.dbo.sysobjects WHERE [ID] = OBJECT_ID('tempdb.dbo.#a'))
 DROP TABLE #a
IF Exists(SELECT * FROM tempdb.dbo.sysobjects WHERE [ID] = OBJECT_ID('tempdb.dbo.#b'))
 DROP TABLE #b
create table #a ([id] int, [order] int)
create table #b (fid int, rid int)

-- First, delete from tables which are not referenced by any foreign key
insert into #a
select id, 0
 from sysobjects left join sysforeignkeys on id = rkeyid
where objectproperty(id, 'isusertable') = 1 
 and rkeyid is null

-- Make a clone of key pairs from sysforeignkeys
insert into #b
select distinct fkeyid, rkeyid
from sysforeignkeys

-- While there are leaves tables do:
while exists(select distinct f1.fid
 from #b f1 left join #b f2 on f1.fid = f2.rid
 where f2.rid is null)
begin
 -- Insert leaves first
 insert into #a
 select distinct f1.fid, @Order 
 from #b f1 left join #b f2 on f1.fid = f2.rid
 where f2.rid is null
 -- Delete just "ordered" tables
 delete f1
 from #b f1 left join #b f2 on f1.fid = f2.rid
 where f2.rid is null

 Set @Order = @Order + 1
end

-- Insert if something is rest in #b (e.g. self-join)
insert into #a
select distinct fid, @Order 
 from #b

-- Insert top level tables
insert into #a
select distinct f1.rkeyid, @Order + 1
from sysforeignkeys f1 left join sysforeignkeys f2 on f1.rkeyid = f2.fkeyid
where f2.rkeyid is null


declare @id int
DECLARE @DelCmd nvarchar(1000)
-- Now when we have all tables in temporary table #a
-- we can create dynamic script and execute it
-- If you need list like this often you can create table-valued function
-- starting code from this line, replacing temp table with function call
declare c cursor
for
select [id], max([order])
 from #a
group by [id]
order by max([order]) asc

open c

--begin tran
FETCH NEXT FROM c INTO @id, @Order
WHILE (@@fetch_status <> -1)
BEGIN
    IF (@@fetch_status <> -2)
    BEGIN
        
        SET @DelCmd = 'DELETE FROM ' + quotename(Object_name(@id))
-- EXEC sp_executesql @DelCmd
        PRINT cast(quotename(Object_name(@id)) as char(50)) + cast(@@rowcount as char(7)) + ' row(s) deleted '
    END
    FETCH NEXT FROM c INTO @id, @Order
END

CLOSE c
DEALLOCATE c

--commit
--rollback

drop table #a
drop table #b

set nocount off

Rate

4.67 (3)

You rated this post out of 5. Change rating

Share

Share

Rate

4.67 (3)

You rated this post out of 5. Change rating