2012-04-17 19 views
0

データベースのすべてのテーブルからすべての行を削除するには、すでに誰かがスクリプトを作成している必要があります。 DELETEコマンドを使用するのは、大規模なテーブルで時間がかかるため、オプションではありません。 もちろん、stackoverflowや他の場所で多くの例がありますが、外部キーを使用するテーブルでは機能しません。データベースのすべてのテーブルからすべての行を削除する

基本的には、スクリプトはこれを行う必要があります。

  • ストアを一時テーブル内のすべての外部キー定義
  • は、すべてのテーブルのすべての外部キーに
  • TRUNCATEを削除
  • 復元外部キー

私はそれを持っていると思う:

IF OBJECT_ID('tempdb..#ForeignKeys') IS NOT NULL 
    DROP TABLE #ForeignKeys; 

WITH ForeignKeys AS (
SELECT 
    QUOTENAME(SCHEMA_NAME(t.schema_id)) + '.' + QUOTENAME(t.name) AS ParentTable 
    , QUOTENAME(SCHEMA_NAME(rt.schema_id)) + '.' + QUOTENAME(rt.name) AS ReferenceTable 
    , QUOTENAME(f.name) AS ConstraintName 
    , STUFF(Parent.Cols, 1, 1, '') AS ParentColumns 
    , STUFF(Reference.Cols, 1, 1, '') AS ReferenceColumns 
    , REPLACE(f.update_referential_action_desc, '_', ' ') AS UpdateAction 
    , REPLACE(f.delete_referential_action_desc, '_', ' ') AS DeleteAction 
FROM 
    sys.tables AS t 
    LEFT JOIN sys.foreign_keys AS f 
     ON f.parent_object_id = t.object_id 
     AND f.type = 'F' 
    LEFT JOIN sys.tables AS rt 
     ON f.referenced_object_id = rt.object_id 
    CROSS APPLY 
    (
     SELECT 
      ',' + QUOTENAME(COL_NAME(fc.parent_object_id, fc.parent_column_id))AS [text()] 
     FROM 
      sys.foreign_key_columns AS fc 
     WHERE 
      fc.constraint_object_id = f.object_id 
     ORDER BY 
      fc.constraint_column_id 
     FOR XML PATH('') 
    ) Parent(Cols) 
    CROSS APPLY 
    (
     SELECT 
      ',' + QUOTENAME(COL_NAME(fc.referenced_object_id, fc.referenced_column_id)) AS [text()] 
     FROM 
      sys.foreign_key_columns AS fc 
     WHERE 
      fc.constraint_object_id = f.object_id 
     ORDER BY 
      fc.constraint_column_id 
     FOR XML PATH('') 
    ) Reference(Cols) 
) 
SELECT 
    ParentTable AS TableName 
    , 'ALTER TABLE ' + ParentTable + ' DROP CONSTRAINT ' + ConstraintName AS DropCmd 
    , 'TRUNCATE TABLE ' + ParentTable AS TruncateCmd 
    , 'ALTER TABLE ' + ParentTable + ' ADD CONSTRAINT ' + ConstraintName + ' FOREIGN KEY(' 
     + ParentColumns + ') REFERENCES ' + ReferenceTable + ' (' + ReferenceColumns 
     + ') ON UPDATE ' + UpdateAction 
     + ' ON DELETE ' + DeleteAction COLLATE SQL_Latin1_General_CP1_CI_AS AS CreateCmd 
INTO 
    #ForeignKeys 
FROM 
    ForeignKeys 
ORDER BY 
1; 

-- SELECT * FROM #ForeignKeys 

DECLARE @TableName SYSNAME 
DECLARE @Sql NVARCHAR(MAX) 

-- Drop all constraints 
DECLARE FkCursor CURSOR FOR 
SELECT 
    TableName 
    , DropCmd 
FROM 
    #ForeignKeys 
WHERE 
    DropCmd IS NOT NULL  

OPEN FkCursor 
FETCH NEXT FROM FkCursor INTO @TableName, @Sql 
WHILE @@FETCH_STATUS = 0 
BEGIN 
    PRINT @TableName + ' : ' + @sql 
    EXEC sp_executesql @Sql 
    FETCH NEXT FROM FkCursor INTO @TableName, @Sql 
END 
CLOSE FkCursor 
DEALLOCATE FkCursor 

-- Truncate all tables 
DECLARE FkCursor CURSOR FOR 
SELECT 
    TableName 
    , TruncateCmd 
FROM 
    #ForeignKeys  

OPEN FkCursor 

FETCH NEXT FROM FkCursor INTO @TableName, @Sql 
WHILE @@FETCH_STATUS = 0 
BEGIN 
    PRINT @TableName + ' : ' + @sql 
    EXEC sp_executesql @Sql 
    FETCH NEXT FROM FkCursor INTO @TableName, @Sql 
END 
CLOSE FkCursor 
DEALLOCATE FkCursor 

-- Create all foreign keys 
DECLARE FkCursor CURSOR FOR 
SELECT 
    TableName 
    , CreateCmd 
FROM 
    #ForeignKeys 
WHERE 
    CreateCmd IS NOT NULL  

OPEN FkCursor 
FETCH NEXT FROM FkCursor INTO @TableName, @Sql 
WHILE @@FETCH_STATUS = 0 
BEGIN 
    PRINT @TableName + ' : ' + @sql 
    EXEC sp_executesql @Sql 
    FETCH NEXT FROM FkCursor INTO @TableName, @Sql 
END 
CLOSE FkCursor 
DEALLOCATE FkCursor 

DROP TABLE #ForeignKeys; 
+1

これまでに書いたことはありますか? – rvphx

+4

すべてのテーブル用の作成スクリプトがある場合は、すべてのテーブル(またはデータベース)を削除してから、作成スクリプトを再実行してみてください。 –

+0

FKによるテーブル参照で削除が機能しません。 FKによって参照されていないテーブルをあなたのために回してください。年齢を定義する。私は100 GB以上のデータベースを持っており、スクリプトを使ってすべての行を切り捨てて、20分のように削除しています。 – Paparazzi

答えて

4
DECLARE @drop NVARCHAR(MAX), @truncate NVARCHAR(MAX), @create NVARCHAR(MAX); 

SELECT @drop = N'', @truncate = N'', @create = N''; 

;WITH x AS 
(
    SELECT id = f.[object_id], 
     cname = QUOTENAME(f.name), 
     ctable = QUOTENAME(OBJECT_SCHEMA_NAME(f.parent_object_id)) 
     + '.' + QUOTENAME(OBJECT_NAME(f.parent_object_id)), 
     ccol = QUOTENAME(COL_NAME(fc.parent_object_id,fc.parent_column_id)), 
     rtable = QUOTENAME(OBJECT_SCHEMA_NAME(f.referenced_object_id)) 
     + '.' + QUOTENAME(OBJECT_NAME(f.referenced_object_id)), 
     rcol = QUOTENAME(COL_NAME(fc.referenced_object_id,fc.referenced_column_id)), 
     ou = f.update_referential_action_desc COLLATE SQL_Latin1_General_CP1_CI_AS, 
     od = f.delete_referential_action_desc COLLATE SQL_Latin1_General_CP1_CI_AS 
    FROM sys.foreign_keys AS f 
    INNER JOIN sys.foreign_key_columns AS fc 
    ON f.[object_id] = fc.constraint_object_id 
    -- where clause to leave out certain tables here 
), 
y AS 
(
    SELECT 
    d = CHAR(13) + CHAR(10) + 'ALTER TABLE ' + ctable + ' DROP CONSTRAINT ' + cname + ';', 
    c = CHAR(13) + CHAR(10) + 'ALTER TABLE ' + ctable + ' ADD CONSTRAINT ' + cname 
     + ' FOREIGN KEY (' + STUFF((SELECT ',' + ccol FROM x AS x2 
     WHERE x2.id = x.id FOR XML PATH('')), 1, 1, '') 
     + ') REFERENCES ' + rtable + '(' + STUFF((SELECT ',' + rcol FROM x AS x3 
     WHERE x3.id = x.id FOR XML PATH('')), 1, 1, '') + ')' 
    + CASE WHEN od <> 'NO_ACTION' THEN 
     ' ON DELETE ' + REPLACE(od, 'SET_', 'SET ') ELSE '' END 
    + CASE WHEN ou <> 'NO_ACTION' THEN 
     ' ON UPDATE ' + REPLACE(ou, 'SET_', 'SET ') ELSE '' END 
    FROM x 
) 
SELECT 
    @drop = @drop + d, 
    @create = @create + c 
FROM y GROUP BY d,c; 

SELECT @truncate = @truncate + CHAR(13) + CHAR(10) + 'TRUNCATE TABLE ' 
    + QUOTENAME(SCHEMA_NAME(schema_id)) + '.' + QUOTENAME(name) + ';' 
    FROM sys.tables 
    -- where clause to leave out certain tables here 
; 

-- use results to text. Note that for 200 tables you won't be able to 
-- manually inspect the entire script in Management Studio because it 
-- will only show a certain number of characters depending on settings. 

SELECT @drop; 
SELECT @truncate; 
SELECT @create; 

-- when you are happy, uncomment these: 

--EXEC sp_executesql @drop; 
--EXEC sp_executesql @truncate; 
--EXEC sp_executesql @create; 
+0

私は似たような解決策を見つけたと思いますが、 'ON(UPDATE | DELETE SET(DEFAULT | NULL)')または空白の列を持つ外部キーを持っていると問題が発生します – psadac

+0

:上記のようにQUOTENAMEを追加してください。FK制約テーブルに名前を付けるとどうなりますか?ケータリングに時間を費やすことができるあらゆる種類のエッジケースがありますが、100%の防弾ソリューションや、あなたがすでに知っているいくつかの非典型的なものが欠けている場合は完璧です –

+0

列名のスペースは想像できるように人格的な選択肢ではありません。しかし、あなたは正しいです、何か "馬鹿な"ものを持つことは難しく、私はQUOTENAMEを使用しています。 – psadac

0

(オブジェクトエクスプローラ内の)オブジェクトを右クリックし、[スクリプトをドロップする]をクリックします。同じメソッドとスクリプトを使用して - >作成する。これは、データベースのすべてのオブジェクトを作成するだけでなく、ドロップするためのスクリプトを提供する必要があります。好きな順序で実行してください。

テーブルやオブジェクトがたくさんある場合は、データベースを右クリックして[タスクに移動してスクリプトを生成]をクリックします。 enter image description here

+0

うわー、500テーブルがある場合、これはまったく生産的ではありません。外来キーとは、正しい順序を決定するために多くの作業が必要になるということです。 –

+0

Yepp。しかし、彼が500テーブルを持っているかどうかはわかりますか? – rvphx

+0

10があっても、それは手動のポインティングとクリックが多く、テーブルをスキップする可能性が非常に高いです。 –

関連する問題