データベースのテスト環境があり、テストサイクルの開始時に新しいデータでリロードしたい。データベース全体を再構築することには興味がありません。単にデータを「リセット」するだけです。
TSQLを使用してすべてのテーブルからすべてのデータを削除する最良の方法は何ですか?使用できるシステムストアドプロシージャ、ビューなどはありますか?テーブルごとにテーブルの切り捨てステートメントを手動で作成および管理したくありません。動的であることが望ましいです。
外部キー関係を持つテーブルからデータを削除する場合(基本的に適切に設計されたデータベースの場合)、すべての制約を無効にし、すべてのデータを削除してから、制約を再度有効にすることができます
-- disable all constraints
EXEC sp_MSForEachTable "ALTER TABLE ? NOCHECK CONSTRAINT all"
-- delete data in all tables
EXEC sp_MSForEachTable "DELETE FROM ?"
-- enable all constraints
exec sp_MSForEachTable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"
制約とトリガーの無効化の詳細 here
一部のテーブルにID列がある場合、それらを再シードすることができます。
EXEC sp_MSForEachTable "DBCC CHECKIDENT ( '?', RESEED, 0)"
RESEEDの動作は、新しいテーブルと、以前に BOL からいくつかのデータが挿入されたテーブルとで異なることに注意してください。
DBCC CHECKIDENT( 'table_name'、RESEED、newReseedValue)
現在のID値はnewReseedValueに設定されます。テーブルが作成されてからテーブルに行が挿入されていない場合、DBCC CHECKIDENTの実行後に挿入された最初の行は、newReseedValueをIDとして使用します。それ以外の場合、挿入される次の行はnewReseedValue + 1を使用します。newReseedValueの値がID列の最大値よりも小さい場合、テーブルへの後続の参照でエラーメッセージ2627が生成されます。
Robert のおかげで、制約を無効にすると切り捨てを使用できないという事実を指摘してくれたため、制約を削除してから再作成する必要がありました。
データベースを消去するスクリプトの王様です。すべてのテーブルをクリアし、正しく再シードします。
SET QUOTED_IDENTIFIER ON;
EXEC sp_MSforeachtable 'SET QUOTED_IDENTIFIER ON; ALTER TABLE ? NOCHECK CONSTRAINT ALL'
EXEC sp_MSforeachtable 'SET QUOTED_IDENTIFIER ON; ALTER TABLE ? DISABLE TRIGGER ALL'
EXEC sp_MSforeachtable 'SET QUOTED_IDENTIFIER ON; DELETE FROM ?'
EXEC sp_MSforeachtable 'SET QUOTED_IDENTIFIER ON; ALTER TABLE ? CHECK CONSTRAINT ALL'
EXEC sp_MSforeachtable 'SET QUOTED_IDENTIFIER ON; ALTER TABLE ? ENABLE TRIGGER ALL'
EXEC sp_MSforeachtable 'SET QUOTED_IDENTIFIER ON';
IF NOT EXISTS (
SELECT
*
FROM
SYS.IDENTITY_COLUMNS
JOIN SYS.TABLES ON SYS.IDENTITY_COLUMNS.Object_ID = SYS.TABLES.Object_ID
WHERE
SYS.TABLES.Object_ID = OBJECT_ID('?') AND SYS.IDENTITY_COLUMNS.Last_Value IS NULL
)
AND OBJECTPROPERTY( OBJECT_ID('?'), 'TableHasIdentity' ) = 1
DBCC CHECKIDENT ('?', RESEED, 0) WITH NO_INFOMSGS;
楽しんでください、しかし注意してください!
これを行う最も簡単な方法は
これにより、デバッグやすべてを含めたかどうかを心配することなく、すべてのテーブルをドロップして再作成するスクリプトが作成されます。これは単なる切り捨て以上のものを実行しますが、結果は同じです。最後に割り当てられた値を記憶する切り捨てられたテーブルとは対照的に、自動インクリメントの主キーは0から始まることに注意してください。 PreProdまたは実稼働環境でManagement Studioにアクセスできない場合は、コードからこれを実行することもできます。
1。
2。
3。
すべてのテーブルの切り捨ては、SQL Serverでは外部キーを持つテーブルを切り捨てることができないため、テーブル間に外部キーの関係がない場合にのみ機能します。
これに代わる方法は、外部キーを持つテーブルを決定し、それらから最初に削除することです。その後、外部キーのないテーブルを切り捨てることができます。
http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=65341 および http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=を参照72957 詳細については。
MSSQL Server DeveploperまたはEnterpriseで使用したい別のオプションは、空のスキーマを作成した直後にデータベースのスナップショットを作成することです。その時点で、データベースをスナップショットに復元し続けることができます。
これをしないでください!本当に、良い考えではありません。
切り捨てるテーブルがわかっている場合は、それらを切り捨てるストアドプロシージャを作成します。順序を修正して、外部キーの問題を回避できます。
それらすべてを本当に切り捨てたい場合(たとえば、BCPをロードできるように)、データベースをドロップして新しいデータベースを最初から作成するのと同じくらい迅速になります。
同じdb内の他のテーブルのデータを削除/切り捨てながら、特定のテーブル(つまり静的ルックアップテーブル)にデータを保持したい場合は、例外を含むループが必要です。これは私がこの質問に出会ったときに私が探していたものです。
sp_MSForEachTableはバグが多いようです(つまり、IFステートメントとの一貫性のない動作)。
declare @LastObjectID int = 0
declare @TableName nvarchar(100) = ''
set @LastObjectID = (select top 1 [object_id] from sys.tables where [object_id] > @LastObjectID order by [object_id])
while(@LastObjectID is not null)
begin
set @TableName = (select top 1 [name] from sys.tables where [object_id] = @LastObjectID)
if(@TableName not in ('Profiles', 'ClientDetails', 'Addresses', 'AgentDetails', 'ChainCodes', 'VendorDetails'))
begin
exec('truncate table [' + @TableName + ']')
end
set @LastObjectID = (select top 1 [object_id] from sys.tables where [object_id] > @LastObjectID order by [object_id])
end
すべてのテーブルを切り捨てることの最も難しい部分は、外部キー制約の削除と再追加です。
次のクエリは、@ myTempTableの各テーブル名に関連する各制約のdrop&createステートメントを作成します。すべてのテーブルに対してこれらを生成する場合は、代わりに情報スキーマを使用してこれらのテーブル名を収集できます。
DECLARE @myTempTable TABLE (tableName varchar(200))
INSERT INTO @myTempTable(tableName) VALUES
('TABLE_ONE'),
('TABLE_TWO'),
('TABLE_THREE')
-- DROP FK Contraints
SELECT 'alter table '+quotename(schema_name(ob.schema_id))+
'.'+quotename(object_name(ob.object_id))+ ' drop constraint ' + quotename(fk.name)
FROM sys.objects ob INNER JOIN sys.foreign_keys fk ON fk.parent_object_id = ob.object_id
WHERE fk.referenced_object_id IN
(
SELECT so.object_id
FROM sys.objects so JOIN sys.schemas sc
ON so.schema_id = sc.schema_id
WHERE so.name IN (SELECT * FROM @myTempTable) AND sc.name=N'dbo' AND type in (N'U'))
-- CREATE FK Contraints
SELECT 'ALTER TABLE [PIMSUser].[dbo].[' +cast(c.name as varchar(255)) + '] WITH NOCHECK ADD CONSTRAINT ['+ cast(f.name as varchar(255)) +'] FOREIGN KEY (['+ cast(fc.name as varchar(255)) +'])
REFERENCES [PIMSUser].[dbo].['+ cast(p.name as varchar(255)) +'] (['+cast(rc.name as varchar(255))+'])'
FROM sysobjects f
INNER JOIN sys.sysobjects c ON f.parent_obj = c.id
INNER JOIN sys.sysreferences r ON f.id = r.constid
INNER JOIN sys.sysobjects p ON r.rkeyid = p.id
INNER JOIN sys.syscolumns rc ON r.rkeyid = rc.id and r.rkey1 = rc.colid
INNER JOIN sys.syscolumns fc ON r.fkeyid = fc.id and r.fkey1 = fc.colid
WHERE
f.type = 'F'
AND
cast(p.name as varchar(255)) IN (SELECT * FROM @myTempTable)
次に、実行するステートメントをコピーしますが、少しの開発努力でカーソルを使用して動的に実行できます。
空の「テンプレート」データベースを作成し、完全バックアップを作成します。更新する必要がある場合は、WITH REPLACEを使用して復元します。高速、シンプル、防弾。また、ここまたはいくつかのテーブルにいくつかの基本データ(たとえば、構成情報、またはアプリを実行するための基本情報)が必要な場合は、それも処理します。
データベースのスクリプトを作成し、スクリプトから削除して作成する方がはるかに簡単です(場合によってはさらに高速です)。
これはoneそれを行う方法です...おそらく10個のより良い/より効率的な他のものがありますが、これは非常にまれにしか行われないように聞こえるので、ここに行きます...
tables
からsysobjects
のリストを取得し、カーソルを使用してそれらをループし、各iteration
に対してsp_execsql('truncate table ' + @table_name)
を呼び出します。
別の回答を追加するチャンスがあります...さらに悪いことに、それはほとんどリンクのみの回答です。私は回答を投稿しました here 異なるが関連するSO質問に、この質問の回答のいくつかに似たストアドプロシージャを作成します...しかし、奇妙な小さな問題の数(複数のスキーマ、奇妙な制約名、ロールバック、その他いくつか)。あなたの考えを見てください。 TruncateTables
というプロシージャを作成します。データベース全体をハックしたい場合は、次のように呼び出します。
declare @t dbo.NamesType --> this simple table type is also defined in the other answer
insert @t select schema_name(t.schema_id) + N'.' + t.name from sys.tables t
execute dbo.TruncateTables @t ,0
たぶんそれはあなたを幸せにするでしょう。そうだといい!
コメントアウトされたセクションを1回実行し、_TruncateListテーブルに切り捨てたいテーブルを追加してから、スクリプトの残りを実行します。 _ScriptLogテーブルを頻繁に実行する場合は、時間をかけてクリーンアップする必要があります。
すべてのテーブルを実行する場合は、これを変更して、SELECT名を#TruncateList FROM sys.tablesに入力するだけです。ただし、通常はすべてを行いたくありません。
また、これはデータベース内のすべての外部キーに影響を与えます。また、アプリケーションにとって強すぎる場合は、それも変更できます。私の目的ではありません。
/*
CREATE TABLE _ScriptLog
(
ID Int NOT NULL Identity(1,1)
, DateAdded DateTime2 NOT NULL DEFAULT GetDate()
, Script NVarChar(4000) NOT NULL
)
CREATE UNIQUE CLUSTERED INDEX IX_ScriptLog_DateAdded_ID_U_C ON _ScriptLog
(
DateAdded
, ID
)
CREATE TABLE _TruncateList
(
TableName SysName PRIMARY KEY
)
*/
IF OBJECT_ID('TempDB..#DropFK') IS NOT NULL BEGIN
DROP TABLE #DropFK
END
IF OBJECT_ID('TempDB..#TruncateList') IS NOT NULL BEGIN
DROP TABLE #TruncateList
END
IF OBJECT_ID('TempDB..#CreateFK') IS NOT NULL BEGIN
DROP TABLE #CreateFK
END
SELECT Scripts = 'ALTER TABLE ' + '[' + OBJECT_NAME(f.parent_object_id)+ ']'+
' DROP CONSTRAINT ' + '[' + f.name + ']'
INTO #DropFK
FROM .sys.foreign_keys AS f
INNER JOIN .sys.foreign_key_columns AS fc
ON f.OBJECT_ID = fc.constraint_object_id
SELECT TableName
INTO #TruncateList
FROM _TruncateList
SELECT Scripts = 'ALTER TABLE ' + const.parent_obj + '
ADD CONSTRAINT ' + const.const_name + ' FOREIGN KEY (
' + const.parent_col_csv + '
) REFERENCES ' + const.ref_obj + '(' + const.ref_col_csv + ')
'
INTO #CreateFK
FROM (
SELECT QUOTENAME(fk.NAME) AS [const_name]
,QUOTENAME(schParent.NAME) + '.' + QUOTENAME(OBJECT_name(fkc.parent_object_id)) AS [parent_obj]
,STUFF((
SELECT ',' + QUOTENAME(COL_NAME(fcP.parent_object_id, fcp.parent_column_id))
FROM sys.foreign_key_columns AS fcP
WHERE fcp.constraint_object_id = fk.object_id
FOR XML path('')
), 1, 1, '') AS [parent_col_csv]
,QUOTENAME(schRef.NAME) + '.' + QUOTENAME(OBJECT_NAME(fkc.referenced_object_id)) AS [ref_obj]
,STUFF((
SELECT ',' + QUOTENAME(COL_NAME(fcR.referenced_object_id, fcR.referenced_column_id))
FROM sys.foreign_key_columns AS fcR
WHERE fcR.constraint_object_id = fk.object_id
FOR XML path('')
), 1, 1, '') AS [ref_col_csv]
FROM sys.foreign_key_columns AS fkc
INNER JOIN sys.foreign_keys AS fk ON fk.object_id = fkc.constraint_object_id
INNER JOIN sys.objects AS oParent ON oParent.object_id = fkc.parent_object_id
INNER JOIN sys.schemas AS schParent ON schParent.schema_id = oParent.schema_id
INNER JOIN sys.objects AS oRef ON oRef.object_id = fkc.referenced_object_id
INNER JOIN sys.schemas AS schRef ON schRef.schema_id = oRef.schema_id
GROUP BY fkc.parent_object_id
,fkc.referenced_object_id
,fk.NAME
,fk.object_id
,schParent.NAME
,schRef.NAME
) AS const
ORDER BY const.const_name
INSERT INTO _ScriptLog (Script)
SELECT Scripts
FROM #CreateFK
DECLARE @Cmd NVarChar(4000)
, @TableName SysName
WHILE 0 < (SELECT Count(1) FROM #DropFK) BEGIN
SELECT TOP 1 @Cmd = Scripts
FROM #DropFK
EXEC (@Cmd)
DELETE #DropFK WHERE Scripts = @Cmd
END
WHILE 0 < (SELECT Count(1) FROM #TruncateList) BEGIN
SELECT TOP 1 @Cmd = N'TRUNCATE TABLE ' + TableName
, @TableName = TableName
FROM #TruncateList
EXEC (@Cmd)
DELETE #TruncateList WHERE TableName = @TableName
END
WHILE 0 < (SELECT Count(1) FROM #CreateFK) BEGIN
SELECT TOP 1 @Cmd = Scripts
FROM #CreateFK
EXEC (@Cmd)
DELETE #CreateFK WHERE Scripts = @Cmd
END
テーブルを切り捨てる前に、すべての外部キーを削除する必要があります。この script を使用して、データベース内のすべての外部キーを削除および再作成する最終スクリプトを生成します。 @action変数を「CREATE」または「DROP」に設定してください。
tABLE_TYPE = 'BASE TABLE'のINFORMATION_SCHEMA.TABLESから「+ TABLE_NAMEから削除」を選択します
結果が来る場所。
クエリウィンドウにコピーして貼り付け、コマンドを実行します
それは少し遅いですが、誰かを助けるかもしれません。 T-SQLを使用して次のことを行うプロシージャを作成することがあります。
ブログに掲載しました here
各テーブルを削除して再作成するスクリプトよりも、データをクリアするほうが良い理由はわかりません。
または、空のDBのバックアップを保持し、古いDBを復元します