FOREIGN KEY制約によって参照されているため、テーブルを切り捨てられませんか?


459

MSSQL2005を使用して、最初に子テーブル(FK関係の主キーを持つテーブル)を切り捨てた場合、外部キー制約でテーブルを切り捨てることができますか?

私はどちらかができることを知っています

  • DELETEwhere句なしでRESEEDIDを使用してから、ID(または)
  • FKを削除し、テーブルを切り捨てて、FKを再作成します。

親の前に子テーブルを切り捨てている限り、上記のいずれのオプションも実行しなくても大丈夫だと思いましたが、次のエラーが発生します。

FOREIGN KEY制約によって参照されているため、テーブル 'TableName'を切り捨てることはできません。

回答:


379

正しい; FK制約が設定されているテーブルを切り捨てることはできません。

通常、これに対する私のプロセスは次のとおりです。

  1. 制約を削除する
  2. テーブルを切り捨てます
  3. 制約を再作成します。

(もちろん、トランザクション内のすべて。)

もちろん、これは子供がすでに切り捨てられている場合にのみ適用されます。それ以外の場合は、データがどのように見えるかに完全に依存して、別のルートに進みます。(ここに入るには変数が多すぎます。)

元のポスターはなぜこれが事実であるかを決定しました。詳細については、この回答を参照してください。


73
"DELETE FROM"は自動インクリメント列をリセットしません。切り捨ては行います。それらは機能的に同等ではありません。
robross0606 2015

35
大量のデータを削除する場合、切り捨てはたいてい正確に実行したいことです。100万行を切り捨てますか?10億?1ミリ秒...したがって、@ M07、「アプローチからの削除はよりクリーンである」と言わないでください。これは、リモートで正確ではないためです。
ctb 2016年

1
大きなデータを削除した後、ユーザーはテーブルとログファイルを圧縮して、ディスク領域を再利用する必要があります。
Muhammad Yousaf Sulahria

2
マジックシュリンクボタン(またはスクリプト)は、99%の場合は推奨されません。
トムスティッケル2017年

1
そして、あなたはどうしますか?リクエストの例?
jeromej

356
DELETE FROM TABLENAME
DBCC CHECKIDENT ('DATABASENAME.dbo.TABLENAME',RESEED, 0)

非常に遅いため、数百万以上のレコードがある場合、これはおそらく望ましいことではないことに注意してください。


これは、制約を無効にして有効にするよりも速く、便利でした。
先生

これは、データが少ないテーブルでのみ機能します。@Pure
Dhanuka777に

1
これは、スキーマのテストが完了した場合に最適です
ohmusama

3
このエラーが発生する可能性があるため、このルートを使用することはお勧めしません
。DELETE

うまくいきませんでした。それでもDELETEステートメントを取得すると、REFERENCE制約と競合します。
emirhosseini 2017

192

TRUNCATE TABLEDDLコマンドなので、テーブル内のレコードが子テーブル内のレコードによって参照されているかどうかを確認できません。

これがDELETE機能し、TRUNCATE TABLE機能しない理由です。データベースは、別のレコードによって参照されていないことを確認できるためです。


92

なし ALTER TABLE

-- Delete all records
DELETE FROM [TableName]
-- Set current ID to "1"
-- If table already contains data, use "0"
-- If table is empty and never insert data, use "1"
-- Use SP https://github.com/reduardo7/TableTruncate
DBCC CHECKIDENT ([TableName], RESEED, 0)

ストアドプロシージャとして

https://github.com/reduardo7/TableTruncate

これは非常に遅いため、数百万以上のレコードがある場合、これはおそらく望ましいことではないことに注意しください


3
DELETE FROMの後に、reseed new value = 1を使用すると、1ではなくすべてID 2から開始されます。Technetから(technet.microsoft.com/en-us/library/ms176057%28SQL.90%29.aspx)テーブルが作成されてからテーブルに挿入された場合、またはTRUNCATE TABLEステートメントを使用してすべての行が削除された場合、DBCC CHECKIDENTの実行後に挿入された最初の行は、new_reseed_valueをIDとして使用します。それ以外の場合、挿入される次の行は、new_reseed_value +現在の増分値を使用します。
Zoran P.

@ZoranP。ストアドプロシージャバリアントを参照してください:github.com/reduardo7/TableTruncate
Eduardo Cuomo

4
DBCC CHECKIDENT([TableName]、RESEED、0)not 1
Tico

1
@TicoFortes投稿を更新しました。ストアドプロシージャのバリアントを参照してください
エドゥアルド・クオモ

1
これは良い方法ではありません。この質問に対する同じ回答の700の他のバージョンでコメントされています。トランザクションロギングを制限するために、データベースがシンプルリカバリモードでない限り。
Pimbrouwers 2017

68

上記で提供された@denver_citizenの解決策は私にとってはうまくいきませんでしたが、私はその精神が好きだったのでいくつか変更しました:

  • ストアドプロシージャにした
  • 外部キーの入力方法と再作成方法を変更しました
  • 元のスクリプトはすべての参照テーブルを切り捨てます。これにより、参照テーブルに他の外部キー参照がある場合、外部キー違反エラーが発生する可能性があります。このスクリプトは、パラメーターとして指定されたテーブルのみを切​​り捨てます。すべてのテーブルでこのストアドプロシージャを正しい順序で複数回呼び出すのはユーザー次第です

公衆のために、ここに更新されたスクリプトがあります:

CREATE PROCEDURE [dbo].[truncate_non_empty_table]

  @TableToTruncate                 VARCHAR(64)

AS 

BEGIN

SET NOCOUNT ON

-- GLOBAL VARIABLES
DECLARE @i int
DECLARE @Debug bit
DECLARE @Recycle bit
DECLARE @Verbose bit
DECLARE @TableName varchar(80)
DECLARE @ColumnName varchar(80)
DECLARE @ReferencedTableName varchar(80)
DECLARE @ReferencedColumnName varchar(80)
DECLARE @ConstraintName varchar(250)

DECLARE @CreateStatement varchar(max)
DECLARE @DropStatement varchar(max)   
DECLARE @TruncateStatement varchar(max)
DECLARE @CreateStatementTemp varchar(max)
DECLARE @DropStatementTemp varchar(max)
DECLARE @TruncateStatementTemp varchar(max)
DECLARE @Statement varchar(max)

        -- 1 = Will not execute statements 
 SET @Debug = 0
        -- 0 = Will not create or truncate storage table
        -- 1 = Will create or truncate storage table
 SET @Recycle = 0
        -- 1 = Will print a message on every step
 set @Verbose = 1

 SET @i = 1
    SET @CreateStatement = 'ALTER TABLE [dbo].[<tablename>]  WITH NOCHECK ADD  CONSTRAINT [<constraintname>] FOREIGN KEY([<column>]) REFERENCES [dbo].[<reftable>] ([<refcolumn>])'
    SET @DropStatement = 'ALTER TABLE [dbo].[<tablename>] DROP CONSTRAINT [<constraintname>]'
    SET @TruncateStatement = 'TRUNCATE TABLE [<tablename>]'

-- Drop Temporary tables

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

-- GET FKs
SELECT ROW_NUMBER() OVER (ORDER BY OBJECT_NAME(parent_object_id), clm1.name) as ID,
       OBJECT_NAME(constraint_object_id) as ConstraintName,
       OBJECT_NAME(parent_object_id) as TableName,
       clm1.name as ColumnName, 
       OBJECT_NAME(referenced_object_id) as ReferencedTableName,
       clm2.name as ReferencedColumnName
  INTO #FKs
  FROM sys.foreign_key_columns fk
       JOIN sys.columns clm1 
         ON fk.parent_column_id = clm1.column_id 
            AND fk.parent_object_id = clm1.object_id
       JOIN sys.columns clm2
         ON fk.referenced_column_id = clm2.column_id 
            AND fk.referenced_object_id= clm2.object_id
 --WHERE OBJECT_NAME(parent_object_id) not in ('//tables that you do not wont to be truncated')
 WHERE OBJECT_NAME(referenced_object_id) = @TableToTruncate
 ORDER BY OBJECT_NAME(parent_object_id)


-- Prepare Storage Table
IF Not EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Internal_FK_Definition_Storage')
   BEGIN
        IF @Verbose = 1
     PRINT '1. Creating Process Specific Tables...'

  -- CREATE STORAGE TABLE IF IT DOES NOT EXISTS
  CREATE TABLE [Internal_FK_Definition_Storage] 
  (
   ID int not null identity(1,1) primary key,
   FK_Name varchar(250) not null,
   FK_CreationStatement varchar(max) not null,
   FK_DestructionStatement varchar(max) not null,
   Table_TruncationStatement varchar(max) not null
  ) 
   END 
ELSE
   BEGIN
        IF @Recycle = 0
            BEGIN
                IF @Verbose = 1
       PRINT '1. Truncating Process Specific Tables...'

    -- TRUNCATE TABLE IF IT ALREADY EXISTS
    TRUNCATE TABLE [Internal_FK_Definition_Storage]    
      END
      ELSE
         PRINT '1. Process specific table will be recycled from previous execution...'
   END


IF @Recycle = 0
   BEGIN

  IF @Verbose = 1
     PRINT '2. Backing up Foreign Key Definitions...'

  -- Fetch and persist FKs             
  WHILE (@i <= (SELECT MAX(ID) FROM #FKs))
   BEGIN
    SET @ConstraintName = (SELECT ConstraintName FROM #FKs WHERE ID = @i)
    SET @TableName = (SELECT TableName FROM #FKs WHERE ID = @i)
    SET @ColumnName = (SELECT ColumnName FROM #FKs WHERE ID = @i)
    SET @ReferencedTableName = (SELECT ReferencedTableName FROM #FKs WHERE ID = @i)
    SET @ReferencedColumnName = (SELECT ReferencedColumnName FROM #FKs WHERE ID = @i)

    SET @DropStatementTemp = REPLACE(REPLACE(@DropStatement,'<tablename>',@TableName),'<constraintname>',@ConstraintName)
    SET @CreateStatementTemp = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@CreateStatement,'<tablename>',@TableName),'<column>',@ColumnName),'<constraintname>',@ConstraintName),'<reftable>',@ReferencedTableName),'<refcolumn>',@ReferencedColumnName)
    SET @TruncateStatementTemp = REPLACE(@TruncateStatement,'<tablename>',@TableName) 

    INSERT INTO [Internal_FK_Definition_Storage]
                        SELECT @ConstraintName, @CreateStatementTemp, @DropStatementTemp, @TruncateStatementTemp

    SET @i = @i + 1

    IF @Verbose = 1
       PRINT '  > Backing up [' + @ConstraintName + '] from [' + @TableName + ']'

    END   
    END   
    ELSE 
       PRINT '2. Backup up was recycled from previous execution...'

       IF @Verbose = 1
     PRINT '3. Dropping Foreign Keys...'

    -- DROP FOREING KEYS
    SET @i = 1
    WHILE (@i <= (SELECT MAX(ID) FROM [Internal_FK_Definition_Storage]))
          BEGIN
             SET @ConstraintName = (SELECT FK_Name FROM [Internal_FK_Definition_Storage] WHERE ID = @i)
    SET @Statement = (SELECT FK_DestructionStatement FROM [Internal_FK_Definition_Storage] WITH (NOLOCK) WHERE ID = @i)

    IF @Debug = 1 
       PRINT @Statement
    ELSE
       EXEC(@Statement)

    SET @i = @i + 1


    IF @Verbose = 1
       PRINT '  > Dropping [' + @ConstraintName + ']'

             END     


    IF @Verbose = 1
       PRINT '4. Truncating Tables...'

    -- TRUNCATE TABLES
-- SzP: commented out as the tables to be truncated might also contain tables that has foreign keys
-- to resolve this the stored procedure should be called recursively, but I dont have the time to do it...          
 /*
    SET @i = 1
    WHILE (@i <= (SELECT MAX(ID) FROM [Internal_FK_Definition_Storage]))
          BEGIN

    SET @Statement = (SELECT Table_TruncationStatement FROM [Internal_FK_Definition_Storage] WHERE ID = @i)

    IF @Debug = 1 
       PRINT @Statement
    ELSE
       EXEC(@Statement)

    SET @i = @i + 1

    IF @Verbose = 1
       PRINT '  > ' + @Statement
          END
*/          


    IF @Verbose = 1
       PRINT '  > TRUNCATE TABLE [' + @TableToTruncate + ']'

    IF @Debug = 1 
        PRINT 'TRUNCATE TABLE [' + @TableToTruncate + ']'
    ELSE
        EXEC('TRUNCATE TABLE [' + @TableToTruncate + ']')


    IF @Verbose = 1
       PRINT '5. Re-creating Foreign Keys...'

    -- CREATE FOREING KEYS
    SET @i = 1
    WHILE (@i <= (SELECT MAX(ID) FROM [Internal_FK_Definition_Storage]))
          BEGIN
             SET @ConstraintName = (SELECT FK_Name FROM [Internal_FK_Definition_Storage] WHERE ID = @i)
    SET @Statement = (SELECT FK_CreationStatement FROM [Internal_FK_Definition_Storage] WHERE ID = @i)

    IF @Debug = 1 
       PRINT @Statement
    ELSE
       EXEC(@Statement)

    SET @i = @i + 1


    IF @Verbose = 1
       PRINT '  > Re-creating [' + @ConstraintName + ']'

          END

    IF @Verbose = 1
       PRINT '6. Process Completed'


END

11
この回答は投票に値します!実際、私はできれば喜んであなたにビールを買います、ピーター:)
nsimeonov

これは、テストのためにデータのいくつかの大きなテーブルをすばやくクリアするための今日の私にとって大きな助けでした。これに関する品質の作業に感謝します。
Craig Selbert 2016

4
このコードの一部をありがとう。ただし、無効なFKをチェックするためのロジックを追加する必要があることに注意してください。それ以外の場合は、現在無効になっている制約を有効にします。
Andre Figueiredo 2017

2
@AndreFigueiredoの提案でバージョンを作成しました。私はそれをGitlabに入れています:gitlab.com/ranolfi/truncate-referenced-table。答えにコードを組み込んでください。
Marc.2377

1
これはすばらしいことですが、テーブルがデフォルト(dbo)スキーマにない場合は機能しないことに注意してください。
Sidewinder94

19

deleteステートメントを使用してテーブル内のすべての行を削除した後、次のコマンドを使用します

delete from tablename

DBCC CHECKIDENT ('tablename', RESEED, 0)

編集:SQL Serverの構文を修正


9
TRUNCATEログを回避し、DELETE大きなテーブルよりもかなり高速です。そのため、これは真の同等のソリューションではありません。
siride 2014年

1
この回答は、1年前に出され回答とどのように異なりますか?
Ofer Zelig 2018年

17

まあ、私が使用した非常に単純な解決策のが見つからなかったので、それは:

  1. 外部キーを削除します。
  2. テーブルを切り捨て
  3. 外部キーを再作成する

ここに行く:

1)失敗の原因となっている外部キー名を見つけます(例:FK_PROBLEM_REASON、フィールド付きID、テーブルからTABLE_OWNING_CONSTRAINT)2)テーブルからそのキーを削除します。

ALTER TABLE TABLE_OWNING_CONSTRAINT DROP CONSTRAINT FK_PROBLEM_REASON

3)必要なテーブルを切り捨てます

TRUNCATE TABLE TABLE_TO_TRUNCATE

4)その最初のテーブルにキーを再度追加します。

ALTER TABLE TABLE_OWNING_CONSTRAINT ADD CONSTRAINT FK_PROBLEM_REASON FOREIGN KEY(ID) REFERENCES TABLE_TO_TRUNCATE (ID)

それでおしまい。


外部キー参照を持つ複数のテーブルがある場合、これは機能しません。データベース全体で、多くの外部キー制限を削除する必要があります。
jbright

13

これは、プロセスを自動化するために私が作成したスクリプトです。お役に立てば幸いです。

SET NOCOUNT ON

-- GLOBAL VARIABLES
DECLARE @i int
DECLARE @Debug bit
DECLARE @Recycle bit
DECLARE @Verbose bit
DECLARE @TableName varchar(80)
DECLARE @ColumnName varchar(80)
DECLARE @ReferencedTableName varchar(80)
DECLARE @ReferencedColumnName varchar(80)
DECLARE @ConstraintName varchar(250)

DECLARE @CreateStatement varchar(max)
DECLARE @DropStatement varchar(max)   
DECLARE @TruncateStatement varchar(max)
DECLARE @CreateStatementTemp varchar(max)
DECLARE @DropStatementTemp varchar(max)
DECLARE @TruncateStatementTemp varchar(max)
DECLARE @Statement varchar(max)

        -- 1 = Will not execute statements 
 SET @Debug = 0
        -- 0 = Will not create or truncate storage table
        -- 1 = Will create or truncate storage table
 SET @Recycle = 0
        -- 1 = Will print a message on every step
 set @Verbose = 1

 SET @i = 1
    SET @CreateStatement = 'ALTER TABLE [dbo].[<tablename>]  WITH NOCHECK ADD  CONSTRAINT [<constraintname>] FOREIGN KEY([<column>]) REFERENCES [dbo].[<reftable>] ([<refcolumn>])'
    SET @DropStatement = 'ALTER TABLE [dbo].[<tablename>] DROP CONSTRAINT [<constraintname>]'
    SET @TruncateStatement = 'TRUNCATE TABLE [<tablename>]'

-- Drop Temporary tables
DROP TABLE #FKs

-- GET FKs
SELECT ROW_NUMBER() OVER (ORDER BY OBJECT_NAME(parent_object_id), clm1.name) as ID,
       OBJECT_NAME(constraint_object_id) as ConstraintName,
       OBJECT_NAME(parent_object_id) as TableName,
       clm1.name as ColumnName, 
       OBJECT_NAME(referenced_object_id) as ReferencedTableName,
       clm2.name as ReferencedColumnName
  INTO #FKs
  FROM sys.foreign_key_columns fk
       JOIN sys.columns clm1 
         ON fk.parent_column_id = clm1.column_id 
            AND fk.parent_object_id = clm1.object_id
       JOIN sys.columns clm2
         ON fk.referenced_column_id = clm2.column_id 
            AND fk.referenced_object_id= clm2.object_id
 WHERE OBJECT_NAME(parent_object_id) not in ('//tables that you do not wont to be truncated')
 ORDER BY OBJECT_NAME(parent_object_id)


-- Prepare Storage Table
IF Not EXISTS(SELECT 1 FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Internal_FK_Definition_Storage')
   BEGIN
        IF @Verbose = 1
     PRINT '1. Creating Process Specific Tables...'

  -- CREATE STORAGE TABLE IF IT DOES NOT EXISTS
  CREATE TABLE [Internal_FK_Definition_Storage] 
  (
   ID int not null identity(1,1) primary key,
   FK_Name varchar(250) not null,
   FK_CreationStatement varchar(max) not null,
   FK_DestructionStatement varchar(max) not null,
   Table_TruncationStatement varchar(max) not null
  ) 
   END 
ELSE
   BEGIN
        IF @Recycle = 0
            BEGIN
                IF @Verbose = 1
       PRINT '1. Truncating Process Specific Tables...'

    -- TRUNCATE TABLE IF IT ALREADY EXISTS
    TRUNCATE TABLE [Internal_FK_Definition_Storage]    
      END
      ELSE
         PRINT '1. Process specific table will be recycled from previous execution...'
   END

IF @Recycle = 0
   BEGIN

  IF @Verbose = 1
     PRINT '2. Backing up Foreign Key Definitions...'

  -- Fetch and persist FKs             
  WHILE (@i <= (SELECT MAX(ID) FROM #FKs))
   BEGIN
    SET @ConstraintName = (SELECT ConstraintName FROM #FKs WHERE ID = @i)
    SET @TableName = (SELECT TableName FROM #FKs WHERE ID = @i)
    SET @ColumnName = (SELECT ColumnName FROM #FKs WHERE ID = @i)
    SET @ReferencedTableName = (SELECT ReferencedTableName FROM #FKs WHERE ID = @i)
    SET @ReferencedColumnName = (SELECT ReferencedColumnName FROM #FKs WHERE ID = @i)

    SET @DropStatementTemp = REPLACE(REPLACE(@DropStatement,'<tablename>',@TableName),'<constraintname>',@ConstraintName)
    SET @CreateStatementTemp = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@CreateStatement,'<tablename>',@TableName),'<column>',@ColumnName),'<constraintname>',@ConstraintName),'<reftable>',@ReferencedTableName),'<refcolumn>',@ReferencedColumnName)
    SET @TruncateStatementTemp = REPLACE(@TruncateStatement,'<tablename>',@TableName) 

    INSERT INTO [Internal_FK_Definition_Storage]
                        SELECT @ConstraintName, @CreateStatementTemp, @DropStatementTemp, @TruncateStatementTemp

    SET @i = @i + 1

    IF @Verbose = 1
       PRINT '  > Backing up [' + @ConstraintName + '] from [' + @TableName + ']'

   END
    END   
    ELSE 
       PRINT '2. Backup up was recycled from previous execution...'

       IF @Verbose = 1
     PRINT '3. Dropping Foreign Keys...'

    -- DROP FOREING KEYS
    SET @i = 1
    WHILE (@i <= (SELECT MAX(ID) FROM [Internal_FK_Definition_Storage]))
          BEGIN
             SET @ConstraintName = (SELECT FK_Name FROM [Internal_FK_Definition_Storage] WHERE ID = @i)
    SET @Statement = (SELECT FK_DestructionStatement FROM [Internal_FK_Definition_Storage] WITH (NOLOCK) WHERE ID = @i)

    IF @Debug = 1 
       PRINT @Statement
    ELSE
       EXEC(@Statement)

    SET @i = @i + 1

    IF @Verbose = 1
       PRINT '  > Dropping [' + @ConstraintName + ']'
             END     

    IF @Verbose = 1
       PRINT '4. Truncating Tables...'

    -- TRUNCATE TABLES
    SET @i = 1
    WHILE (@i <= (SELECT MAX(ID) FROM [Internal_FK_Definition_Storage]))
          BEGIN
    SET @Statement = (SELECT Table_TruncationStatement FROM [Internal_FK_Definition_Storage] WHERE ID = @i)

    IF @Debug = 1 
       PRINT @Statement
    ELSE
       EXEC(@Statement)

    SET @i = @i + 1

    IF @Verbose = 1
       PRINT '  > ' + @Statement
          END

    IF @Verbose = 1
       PRINT '5. Re-creating Foreign Keys...'

    -- CREATE FOREING KEYS
    SET @i = 1
    WHILE (@i <= (SELECT MAX(ID) FROM [Internal_FK_Definition_Storage]))
          BEGIN
             SET @ConstraintName = (SELECT FK_Name FROM [Internal_FK_Definition_Storage] WHERE ID = @i)
    SET @Statement = (SELECT FK_CreationStatement FROM [Internal_FK_Definition_Storage] WHERE ID = @i)

    IF @Debug = 1 
       PRINT @Statement
    ELSE
       EXEC(@Statement)

    SET @i = @i + 1

    IF @Verbose = 1
       PRINT '  > Re-creating [' + @ConstraintName + ']'
          END

    IF @Verbose = 1
       PRINT '6. Process Completed'

2
注意してください。スクリプトのキーに参照アクションを追加すると、カスケード設定が失われます。
alphadogg 2010

1
これは私にはうまくいきませんが、私はその精神が好きだったので、いくつか変更しました:ストアドプロシージャを変更して外部キーの入力方法を変更し、元のスクリプトがすべての参照テーブルを切り捨てました。テーブルは外部キー参照も持っているため、切り捨てることはできません。パラメータとして指定されたテーブルだけが切り捨てられます。このバージョンでは、すべての参照テーブルは、私はここに、このスレッドに更新tolutionを掲載、このスクリプトを呼び出す前に、手動で切り捨てられるべきで stackoverflow.com/a/13249209/157591
ピーターSzanto

1
@alphadoggこれらの参照アクションを見つける方法はありますか?私はインターネットを探し回っていましたが、見つけられないようです。よろしければ、正式な質問として投稿できます。
マイケル-クレイシャーキーはどこにいるか2014年

1
将来の訪問者への注意:それはsys.foreign_keys表にあります。(参考文献
マイケル-クレイシャーキーはどこにあるか

@Michael:INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS(msdn.microsoft.com/en-us/library/ms179987.aspx
alphadogg

13

この手順に従うことができます。これによりreseeding table、テーブルのデータを削除できます。

delete from table_name
dbcc checkident('table_name',reseed,0)

エラーが発生した場合は、プライマリテーブルを再シードする必要があります。


1
これは適切に機能しますが、トランザクションログは、テーブル内のレコード数によって増加しますが、トランザクションログにレコードを1つだけ置く 'truncate table'と比較してください。ほとんどのテーブルでは大した問題ではありませんが、数百万行以上ある場合は問題になる可能性があります。
David

9
SET FOREIGN_KEY_CHECKS = 0; 

truncate table "yourTableName";

SET FOREIGN_KEY_CHECKS = 1;

8
この質問は、FOREIGN_KEY_CHECKS設定がないMS SQL Serverに関するものです
Elezar

1
これはMySQLで機能すると思いますが、MS SQL Serverでは機能しません
Cocowalla

8

私が正しく理解していれば、統合テストを含むクリーンな環境をDB用にセットアップすることをお勧めします。

ここでの私のアプローチは、スキーマ全体を削除して後で再作成することです。

理由:

  1. おそらく「スキーマの作成」スクリプトをすでに持っています。テストの分離に再利用するのは簡単です。
  2. スキーマの作成は非常に迅速です。
  3. そのアプローチを使用すると、各フィクスチャに(一時的な名前で)新しいスキーマを作成するようにスクリプトを設定するのが非常に簡単で、テストフィクスチャの並列実行を開始して、テストスイートの最も遅い部分をはるかに高速にすることができます。 。

1
削除するのではなく、すべてのスキーマを「切り捨てる」必要があります。統合テストのSetupメソッドでそれを実行したいと思います。統合テスト内からDB作成スクリプトを呼び出すことは...最初の解決策ではありません。
ripper234 2010年

7

ウェブの他の場所で見つかりました

EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
EXEC sp_MSForEachTable 'ALTER TABLE ? DISABLE TRIGGER ALL'
-- EXEC sp_MSForEachTable 'DELETE FROM ?' -- Uncomment to execute
EXEC sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'
EXEC sp_MSForEachTable 'ALTER TABLE ? ENABLE TRIGGER ALL'

3
おそらく 'ALTER TABLE?チェックWITH CHECK CONSTRAINT ALL」。
Andriy M

20
-1:質問で尋ねられたように、これがtruncateコマンドでまったく機能しないことを確認しました。stackoverflow.com/questions/3843806/…を
Lynn Crumbling 2007

7

制約を削除しないと、テーブルを切り捨てることはできません。無効化も機能しません。あなたはすべてを落とす必要があります。すべての制約を削除してから再作成するスクリプトを作成しました。

必ずトランザクションでラップしてください;)

SET NOCOUNT ON
GO

DECLARE @table TABLE(
RowId INT PRIMARY KEY IDENTITY(1, 1),
ForeignKeyConstraintName NVARCHAR(200),
ForeignKeyConstraintTableSchema NVARCHAR(200),
ForeignKeyConstraintTableName NVARCHAR(200),
ForeignKeyConstraintColumnName NVARCHAR(200),
PrimaryKeyConstraintName NVARCHAR(200),
PrimaryKeyConstraintTableSchema NVARCHAR(200),
PrimaryKeyConstraintTableName NVARCHAR(200),
PrimaryKeyConstraintColumnName NVARCHAR(200)
)

INSERT INTO @table(ForeignKeyConstraintName, ForeignKeyConstraintTableSchema, ForeignKeyConstraintTableName, ForeignKeyConstraintColumnName)
SELECT
U.CONSTRAINT_NAME,
U.TABLE_SCHEMA,
U.TABLE_NAME,
U.COLUMN_NAME
FROM
INFORMATION_SCHEMA.KEY_COLUMN_USAGE U
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS C
ON U.CONSTRAINT_NAME = C.CONSTRAINT_NAME
WHERE
C.CONSTRAINT_TYPE = 'FOREIGN KEY'

UPDATE @table SET
PrimaryKeyConstraintName = UNIQUE_CONSTRAINT_NAME
FROM
@table T
INNER JOIN INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS R
ON T.ForeignKeyConstraintName = R.CONSTRAINT_NAME

UPDATE @table SET
PrimaryKeyConstraintTableSchema = TABLE_SCHEMA,
PrimaryKeyConstraintTableName = TABLE_NAME
FROM @table T
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS C
ON T.PrimaryKeyConstraintName = C.CONSTRAINT_NAME

UPDATE @table SET
PrimaryKeyConstraintColumnName = COLUMN_NAME
FROM @table T
INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE U
ON T.PrimaryKeyConstraintName = U.CONSTRAINT_NAME

--DROP CONSTRAINT:

DECLARE @dynSQL varchar(MAX);

DECLARE cur CURSOR FOR
SELECT
'
ALTER TABLE [' + ForeignKeyConstraintTableSchema + '].[' + ForeignKeyConstraintTableName + ']
DROP CONSTRAINT ' + ForeignKeyConstraintName + '
'
FROM
@table

OPEN cur

FETCH cur into @dynSQL
WHILE @@FETCH_STATUS = 0 
BEGIN
    exec(@dynSQL)
    print @dynSQL

    FETCH cur into @dynSQL
END
CLOSE cur
DEALLOCATE cur
---------------------



   --HERE GOES YOUR TRUNCATES!!!!!
   --HERE GOES YOUR TRUNCATES!!!!!
   --HERE GOES YOUR TRUNCATES!!!!!

    truncate table your_table

   --HERE GOES YOUR TRUNCATES!!!!!
   --HERE GOES YOUR TRUNCATES!!!!!
   --HERE GOES YOUR TRUNCATES!!!!!

---------------------
--ADD CONSTRAINT:

DECLARE cur2 CURSOR FOR
SELECT
'
ALTER TABLE [' + ForeignKeyConstraintTableSchema + '].[' + ForeignKeyConstraintTableName + ']
ADD CONSTRAINT ' + ForeignKeyConstraintName + ' FOREIGN KEY(' + ForeignKeyConstraintColumnName + ') REFERENCES [' + PrimaryKeyConstraintTableSchema + '].[' + PrimaryKeyConstraintTableName + '](' + PrimaryKeyConstraintColumnName + ')
'
FROM
@table

OPEN cur2

FETCH cur2 into @dynSQL
WHILE @@FETCH_STATUS = 0 
BEGIN
    exec(@dynSQL)

    print @dynSQL

    FETCH cur2 into @dynSQL
END
CLOSE cur2
DEALLOCATE cur2

6

@denver_citizenと@Peter Szantoの回答は私にとってはうまくいきませんでしたが、次のように修正しました:

  1. 複合キー
  2. 削除時および更新時のアクション
  3. 再追加時にインデックスを確認する
  4. dbo以外のスキーマ
  5. 一度に複数のテーブル
DECLARE @Debug bit = 0;

-- List of tables to truncate
select
    SchemaName, Name
into #tables
from (values 
    ('schema', 'table')
    ,('schema2', 'table2')
) as X(SchemaName, Name)


BEGIN TRANSACTION TruncateTrans;

with foreignKeys AS (
     SELECT 
        SCHEMA_NAME(fk.schema_id) as SchemaName
        ,fk.Name as ConstraintName
        ,OBJECT_NAME(fk.parent_object_id) as TableName
        ,SCHEMA_NAME(t.SCHEMA_ID) as ReferencedSchemaName
        ,OBJECT_NAME(fk.referenced_object_id) as ReferencedTableName
        ,fc.constraint_column_id
        ,COL_NAME(fk.parent_object_id, fc.parent_column_id) AS ColumnName
        ,COL_NAME(fk.referenced_object_id, fc.referenced_column_id) as ReferencedColumnName
        ,fk.delete_referential_action_desc
        ,fk.update_referential_action_desc
    FROM sys.foreign_keys AS fk
        JOIN sys.foreign_key_columns AS fc
            ON fk.object_id = fc.constraint_object_id
        JOIN #tables tbl 
            ON OBJECT_NAME(fc.referenced_object_id) = tbl.Name
        JOIN sys.tables t on OBJECT_NAME(t.object_id) = tbl.Name 
            and SCHEMA_NAME(t.schema_id) = tbl.SchemaName
            and t.OBJECT_ID = fc.referenced_object_id
)



select
    quotename(fk.ConstraintName) AS ConstraintName
    ,quotename(fk.SchemaName) + '.' + quotename(fk.TableName) AS TableName
    ,quotename(fk.ReferencedSchemaName) + '.' + quotename(fk.ReferencedTableName) AS ReferencedTableName
    ,replace(fk.delete_referential_action_desc, '_', ' ') AS DeleteAction
    ,replace(fk.update_referential_action_desc, '_', ' ') AS UpdateAction
    ,STUFF((
        SELECT ',' + quotename(fk2.ColumnName)
        FROM foreignKeys fk2 
        WHERE fk2.ConstraintName = fk.ConstraintName and fk2.SchemaName = fk.SchemaName
        ORDER BY fk2.constraint_column_id
        FOR XML PATH('')
    ),1,1,'') AS ColumnNames
    ,STUFF((
        SELECT ',' + quotename(fk2.ReferencedColumnName)
        FROM foreignKeys fk2 
        WHERE fk2.ConstraintName = fk.ConstraintName and fk2.SchemaName = fk.SchemaName
        ORDER BY fk2.constraint_column_id
        FOR XML PATH('')
    ),1,1,'') AS ReferencedColumnNames
into #FKs
from foreignKeys fk
GROUP BY fk.SchemaName, fk.ConstraintName, fk.TableName, fk.ReferencedSchemaName, fk.ReferencedTableName, fk.delete_referential_action_desc, fk.update_referential_action_desc



-- Drop FKs
select 
    identity(int,1,1) as ID,
    'ALTER TABLE ' + fk.TableName + ' DROP CONSTRAINT ' + fk.ConstraintName AS script
into #scripts
from #FKs fk

-- Truncate 
insert into #scripts
select distinct 
    'TRUNCATE TABLE ' + quotename(tbl.SchemaName) + '.' + quotename(tbl.Name) AS script
from #tables tbl

-- Recreate
insert into #scripts
select 
    'ALTER TABLE ' + fk.TableName + 
    ' WITH CHECK ADD CONSTRAINT ' + fk.ConstraintName + 
    ' FOREIGN KEY ('+ fk.ColumnNames +')' + 
    ' REFERENCES ' + fk.ReferencedTableName +' ('+ fk.ReferencedColumnNames +')' +
    ' ON DELETE ' + fk.DeleteAction COLLATE Latin1_General_CI_AS_KS_WS + ' ON UPDATE ' + fk.UpdateAction COLLATE Latin1_General_CI_AS_KS_WS AS script
from #FKs fk


DECLARE @script nvarchar(MAX);

DECLARE curScripts CURSOR FOR 
    select script
    from #scripts
    order by ID

OPEN curScripts

WHILE 1=1 BEGIN
    FETCH NEXT FROM curScripts INTO @script
    IF @@FETCH_STATUS != 0 BREAK;

    print @script;
    IF @Debug = 0
        EXEC (@script);
END
CLOSE curScripts
DEALLOCATE curScripts


drop table #scripts
drop table #FKs
drop table #tables


COMMIT TRANSACTION TruncateTrans;

4

切り捨ては私にとってはうまくいきませんでした、削除+再シードが最善の方法です。削除+再シードを実行するために膨大な数のテーブルを反復処理する必要のある人がいる場合、ID列がないテーブルで問題が発生する可能性があります。次のコードは、ID列が存在するかどうかを確認する前に確認します再シードする

    EXEC ('DELETE FROM [schemaName].[tableName]')
    IF EXISTS (Select * from sys.identity_columns where object_name(object_id) = 'tableName')
    BEGIN
        EXEC ('DBCC CHECKIDENT ([schemaName.tableName], RESEED, 0)')
    END

4

私は次の方法を書いて、それらをパラメーター化しようとしました。そうすれ、それらをQuery documentOrで実行したり、それらを簡単に使用SPできるようにすることができます。

A)削除

テーブルに数百万のレコードがない場合、これは適切に機能し、Alterコマンドはありません

---------------------------------------------------------------
------------------- Just Fill Parameters Value ----------------
---------------------------------------------------------------
DECLARE @DbName AS NVARCHAR(30) = 'MyDb'         --< Db Name
DECLARE @Schema AS NVARCHAR(30) = 'dbo'          --< Schema
DECLARE @TableName AS NVARCHAR(30) = 'Book'      --< Table Name
------------------ /Just Fill Parameters Value ----------------

DECLARE @Query AS NVARCHAR(500) = 'Delete FROM ' + @TableName

EXECUTE sp_executesql @Query
SET @Query=@DbName+'.'+@Schema+'.'+@TableName
DBCC CHECKIDENT (@Query,RESEED, 0)
  • 上記の私の回答では、質問で言及された問題を解決する方法は@ s15199dの 回答に基づいています

B)切り捨て

テーブルに数百万のレコードがある場合、またはコードのAlterコマンドに問題がない場合は、次のコードを使用します。

--   Book                               Student
--
--   |  BookId  | Field1 |              | StudentId |  BookId  |
--   ---------------------              ------------------------ 
--   |    1     |    A   |              |     2     |    1     |  
--   |    2     |    B   |              |     1     |    1     |
--   |    3     |    C   |              |     2     |    3     |  

---------------------------------------------------------------
------------------- Just Fill Parameters Value ----------------
---------------------------------------------------------------
DECLARE @DbName AS NVARCHAR(30) = 'MyDb'
DECLARE @Schema AS NVARCHAR(30) = 'dbo'
DECLARE @TableName_ToTruncate AS NVARCHAR(30) = 'Book'

DECLARE @TableName_OfOwnerOfConstraint AS NVARCHAR(30) = 'Student' --< Decelations About FK_Book_Constraint
DECLARE @Ref_ColumnName_In_TableName_ToTruncate AS NVARCHAR(30) = 'BookId' --< Decelations About FK_Book_Constraint
DECLARE @FK_ColumnName_In_TableOfOwnerOfConstraint AS NVARCHAR(30) = 'Fk_BookId' --< Decelations About FK_Book_Constraint
DECLARE @FK_ConstraintName AS NVARCHAR(30) = 'FK_Book_Constraint'                --< Decelations About FK_Book_Constraint
------------------ /Just Fill Parameters Value ----------------

DECLARE @Query AS NVARCHAR(2000)

SET @Query= 'ALTER TABLE '+@TableName_OfOwnerOfConstraint+' DROP CONSTRAINT '+@FK_ConstraintName
EXECUTE sp_executesql @Query

SET @Query= 'Truncate Table '+ @TableName_ToTruncate
EXECUTE sp_executesql @Query

SET @Query= 'ALTER TABLE '+@TableName_OfOwnerOfConstraint+' ADD CONSTRAINT '+@FK_ConstraintName+' FOREIGN KEY('+@FK_ColumnName_In_TableOfOwnerOfConstraint+') REFERENCES '+@TableName_ToTruncate+'('+@Ref_ColumnName_In_TableName_ToTruncate+')'
EXECUTE sp_executesql @Query
  • 上記の私の回答では、質問で述べた問題を解決する方法は@LauroWolffValenteSobrinhoの 回答に基づいてます

  • CONSTRAINTが複数ある場合は、上記のクエリに私のようなコードを追加する必要があります

  • また、上記のコードベース@SerjSaganの 回答を変更して、制約を有効にすることを無効にすることもできます。


3

それがこの問題の私の解決策です。PKを変更するために使用しましたが、考え方は同じです。これが役立つことを願っています)

PRINT 'Script starts'

DECLARE @foreign_key_name varchar(255)
DECLARE @keycnt int
DECLARE @foreign_table varchar(255)
DECLARE @foreign_column_1 varchar(255)
DECLARE @foreign_column_2 varchar(255)
DECLARE @primary_table varchar(255)
DECLARE @primary_column_1 varchar(255)
DECLARE @primary_column_2 varchar(255)
DECLARE @TablN varchar(255)

-->> Type the primary table name
SET @TablN = ''
---------------------------------------------------------------------------------------    ------------------------------
--Here will be created the temporary table with all reference FKs
---------------------------------------------------------------------------------------------------------------------
PRINT 'Creating the temporary table'
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
    into #ConTab
    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' and p.name = @TablN
 ORDER BY cast(p.name as varchar(255))
---------------------------------------------------------------------------------------------------------------------
--Cursor, below, will drop all reference FKs
---------------------------------------------------------------------------------------------------------------------
DECLARE @CURSOR CURSOR
/*Fill in cursor*/

PRINT 'Cursor 1 starting. All refernce FK will be droped'

SET @CURSOR  = CURSOR SCROLL
FOR
select foreign_key_name
    , keycnt
    , foreign_table
    , foreign_column_1
    , foreign_column_2
    , primary_table
    , primary_column_1
    , primary_column_2
    from #ConTab

OPEN @CURSOR

FETCH NEXT FROM @CURSOR INTO @foreign_key_name, @keycnt, @foreign_table,         @foreign_column_1, @foreign_column_2, 
                        @primary_table, @primary_column_1, @primary_column_2

WHILE @@FETCH_STATUS = 0
BEGIN

    EXEC ('ALTER TABLE ['+@foreign_table+'] DROP CONSTRAINT ['+@foreign_key_name+']')

FETCH NEXT FROM @CURSOR INTO @foreign_key_name, @keycnt, @foreign_table, @foreign_column_1, @foreign_column_2, 
                         @primary_table, @primary_column_1, @primary_column_2
END
CLOSE @CURSOR
PRINT 'Cursor 1 finished work'
---------------------------------------------------------------------------------------------------------------------
--Here you should provide the chainging script for the primary table
---------------------------------------------------------------------------------------------------------------------

PRINT 'Altering primary table begin'

TRUNCATE TABLE table_name

PRINT 'Altering finished'

---------------------------------------------------------------------------------------------------------------------
--Cursor, below, will add again all reference FKs
--------------------------------------------------------------------------------------------------------------------

PRINT 'Cursor 2 starting. All refernce FK will added'
SET @CURSOR  = CURSOR SCROLL
FOR
select foreign_key_name
    , keycnt
    , foreign_table
    , foreign_column_1
    , foreign_column_2
    , primary_table
    , primary_column_1
    , primary_column_2
    from #ConTab

OPEN @CURSOR

FETCH NEXT FROM @CURSOR INTO @foreign_key_name, @keycnt, @foreign_table, @foreign_column_1, @foreign_column_2, 
                         @primary_table, @primary_column_1, @primary_column_2

WHILE @@FETCH_STATUS = 0
BEGIN

    EXEC ('ALTER TABLE [' +@foreign_table+ '] WITH NOCHECK ADD  CONSTRAINT [' +@foreign_key_name+ '] FOREIGN KEY(['+@foreign_column_1+'])
        REFERENCES [' +@primary_table+'] (['+@primary_column_1+'])')

    EXEC ('ALTER TABLE [' +@foreign_table+ '] CHECK CONSTRAINT [' +@foreign_key_name+']')

FETCH NEXT FROM @CURSOR INTO @foreign_key_name, @keycnt, @foreign_table, @foreign_column_1, @foreign_column_2, 
                         @primary_table, @primary_column_1, @primary_column_2
END
CLOSE @CURSOR
PRINT 'Cursor 2 finished work'
---------------------------------------------------------------------------------------------------------------------
PRINT 'Temporary table droping'
drop table #ConTab
PRINT 'Finish'

3

の場合MS SQL、少なくとも新しいバージョンでは、次のようなコードで制約を無効にすることができます。

ALTER TABLE Orders
NOCHECK CONSTRAINT [FK_dbo.Orders_dbo.Customers_Customer_Id]
GO

TRUNCATE TABLE Customers
GO

ALTER TABLE Orders
WITH CHECK CHECK CONSTRAINT [FK_dbo.Orders_dbo.Customers_Customer_Id]
GO

これはうまくいかないことを上で確立したと思いますか?多分それは新しいバージョンのためにありますか?
コープ2013

2
Fwiw、これはOPのバージョン(2005)では機能せず、後継(MSSQL2008)でも機能しません。
CB

3

以下は、FK制約がある場合でも機能し、次の回答を組み合わせて指定されたテーブルのみを削除します


USE [YourDB];

DECLARE @TransactionName varchar(20) = 'stopdropandroll';

BEGIN TRAN @TransactionName;
set xact_abort on; /* automatic rollback https://stackoverflow.com/a/1749788/1037948 */
    -- ===== DO WORK // =====

    -- dynamic sql placeholder
    DECLARE @SQL varchar(300);

    -- LOOP: https://stackoverflow.com/a/10031803/1037948
    -- list of things to loop
    DECLARE @delim char = ';';
    DECLARE @foreach varchar(MAX) = 'Table;Names;Separated;By;Delimiter' + @delim + 'AnotherName' + @delim + 'Still Another';
    DECLARE @token varchar(MAX);
    WHILE len(@foreach) > 0
    BEGIN
        -- set current loop token
        SET @token = left(@foreach, charindex(@delim, @foreach+@delim)-1)
        -- ======= DO WORK // ===========

        -- dynamic sql (parentheses are required): https://stackoverflow.com/a/989111/1037948
        SET @SQL = 'DELETE FROM [' + @token + ']; DBCC CHECKIDENT (''' + @token + ''',RESEED, 0);'; -- https://stackoverflow.com/a/11784890
        PRINT @SQL;
        EXEC (@SQL);

        -- ======= // END WORK ===========
        -- continue loop, chopping off token
        SET @foreach = stuff(@foreach, 1, charindex(@delim, @foreach+@delim), '')
    END

    -- ===== // END WORK =====
-- review and commit
SELECT @@TRANCOUNT as TransactionsPerformed, @@ROWCOUNT as LastRowsChanged;
COMMIT TRAN @TransactionName;

注意:

テーブルを削除する順序で宣言すること(つまり、最初に依存関係をkillすること)が役立つと思います。この回答に示されているように、特定の名前をループするのではなく、すべてのテーブルを

EXEC sp_MSForEachTable 'DELETE FROM ?; DBCC CHECKIDENT (''?'',RESEED, 0);';

他のスクリプトは実際には使用しませんでした。なぜなら、外部キーがあると機能しないと誰もが言ったからです。だから私はこれを試しました、そしてこれは私のためのトリックをしました。
Vivendi

1
DELETE 同じではありませんTRUNCATE。これにより、トランザクションログがいっぱいになります。
Dan Bechard、2015年

@ダン、おそらく良い点。先ほど触れたように、ここで他の回答を組み合わせただけです...
drzaus、2015年

@drzaus小規模/中規模のテーブルでは正常に機能しますが、削除コマンドがハードディスクをいっぱいにするトランザクションログをいっぱいにしたため、本番SQLサーバーをオフラインにしました。少なくとも、大きなテーブルでこれを試みる前に、トランザクションログが最大サイズであることを確認してください。
Dan Bechard、2015年

2

これらの答えのどれも私の場合のように機能しなかった場合、これを行います:

  1. 制約を削除
  2. nullを許可するようにすべての値を設定する
  3. テーブルを切り捨て
  4. 削除された制約を追加します。

幸運を!


それについてのSQLサンプル?
Kiquenet

2

自動インクリメントを削除してリセットします。

delete from tablename;

その後

ALTER TABLE tablename AUTO_INCREMENT = 1;

おかげで、これはうまくいきました。
ポリワール氏

1

唯一の方法は、切り捨てを行う前に外部キーを削除することです。また、データを切り捨てた後、インデックスを再作成する必要があります。

次のスクリプトは、すべての外部キー制約を削除するために必要なSQLを生成します。

DECLARE @drop NVARCHAR(MAX) = N'';

SELECT @drop += N'
ALTER TABLE ' + QUOTENAME(cs.name) + '.' + QUOTENAME(ct.name) 
    + ' DROP CONSTRAINT ' + QUOTENAME(fk.name) + ';'
FROM sys.foreign_keys AS fk
INNER JOIN sys.tables AS ct
  ON fk.parent_object_id = ct.[object_id]
INNER JOIN sys.schemas AS cs 
  ON ct.[schema_id] = cs.[schema_id];

SELECT @drop

次に、次のスクリプトは、外部キーを再作成するために必要なSQLを生成します。

DECLARE @create NVARCHAR(MAX) = N'';

SELECT @create += N'
ALTER TABLE ' 
   + QUOTENAME(cs.name) + '.' + QUOTENAME(ct.name) 
   + ' ADD CONSTRAINT ' + QUOTENAME(fk.name) 
   + ' FOREIGN KEY (' + STUFF((SELECT ',' + QUOTENAME(c.name)
   -- get all the columns in the constraint table
    FROM sys.columns AS c 
    INNER JOIN sys.foreign_key_columns AS fkc 
    ON fkc.parent_column_id = c.column_id
    AND fkc.parent_object_id = c.[object_id]
    WHERE fkc.constraint_object_id = fk.[object_id]
    ORDER BY fkc.constraint_column_id 
    FOR XML PATH(N''), TYPE).value(N'.[1]', N'nvarchar(max)'), 1, 1, N'')
  + ') REFERENCES ' + QUOTENAME(rs.name) + '.' + QUOTENAME(rt.name)
  + '(' + STUFF((SELECT ',' + QUOTENAME(c.name)
   -- get all the referenced columns
    FROM sys.columns AS c 
    INNER JOIN sys.foreign_key_columns AS fkc 
    ON fkc.referenced_column_id = c.column_id
    AND fkc.referenced_object_id = c.[object_id]
    WHERE fkc.constraint_object_id = fk.[object_id]
    ORDER BY fkc.constraint_column_id 
    FOR XML PATH(N''), TYPE).value(N'.[1]', N'nvarchar(max)'), 1, 1, N'') + ');'
FROM sys.foreign_keys AS fk
INNER JOIN sys.tables AS rt -- referenced table
  ON fk.referenced_object_id = rt.[object_id]
INNER JOIN sys.schemas AS rs 
  ON rt.[schema_id] = rs.[schema_id]
INNER JOIN sys.tables AS ct -- constraint table
  ON fk.parent_object_id = ct.[object_id]
INNER JOIN sys.schemas AS cs 
  ON ct.[schema_id] = cs.[schema_id]
WHERE rt.is_ms_shipped = 0 AND ct.is_ms_shipped = 0;

SELECT @create

生成されたスクリプトを実行してすべての外部キーを削除し、テーブルを切り捨ててから、生成されたスクリプトを実行してすべての外部キーを再作成します。

クエリはここから取得されます


0

SSMSでは、ダイアグラムを開いてキーを表示しました。キーを削除してファイルを切り詰めた後、更新してダイアグラムに戻り、IDボックスをクリアして復元することで更新を作成しました。ダイアグラムを保存すると、[作業中にデータベースが変更されました]ダイアログボックスではなく[保存]ダイアログボックスが表示され、[はい]をクリックするとキーが復元され、ダイアグラムのラッチされたコピーから復元されます。


0

これを何らかの頻度で実行している場合は、スケジュールでも、DMLステートメントを使用すること絶対にありません。トランザクションログへの書き込みコストは非常に高く、SIMPLE1つのテーブルを切り捨てるためにデータベース全体をリカバリモードに設定するのはばかげています。

最善の方法は、残念ながら困難または面倒な方法です。それは:

  • 制約を削除
  • テーブルを切り捨て
  • 制約を再作成する

これを行うための私のプロセスには、次の手順が含まれます。

  1. SSMSで問題のテーブルを右クリックし、[依存関係の表示]を選択します。
  2. 参照されているテーブル(ある場合)をメモします。
  3. オブジェクトエクスプローラーに戻り、Keysノードを展開して、外部キー(ある場合)をメモします。
  4. スクリプティングを開始します(ドロップ/トランケート/再作成)

このようなスクリプトは、およびブロック内で実行する必要begin tranありcommit tranます。


-3

最初にテーブルの制約を無効にする限り、子に外部キー制約がある親テーブルでTRUNCATEテーブルを使用できることがわかりました。例えば

子テーブルの外部キーCONSTRAINT child_par_ref、PARENT_TABLEを参照

ALTER TABLE CHILD_TABLE DISABLE CONSTRAINT child_par_ref;
TRUNCATE TABLE CHILD_TABLE;
TRUNCATE TABLE PARENT_TABLE;
ALTER TABLE CHILD_TABLE ENABLE CONSTRAINT child_par_ref;

1
これは、ALTER TABLEの有効なSQL Server構文ではありません。{ENABLE | 無効にする}制約。参照:msdn.microsoft.com/en-us/library/ms190273.aspx
jason_ruz 2014年

-3

最も簡単な方法:
1-phpmyadminに入力
2-左の列のテーブル名を
クリック3-操作(トップメニュー)を
クリック4-「テーブルを空にする(切り捨て)
」5-ボックスを無効にする「外部キーチェックを有効にする」
6-完了!

画像チュートリアルへのリンク
チュートリアル:http : //www.imageno.com/wz6gv1wuqajrpic.html
(申し訳ありませんが、ここに画像をアップロードするのに十分な評判がありません:P)


2
OPはMSSQLを述べました。あなたはMySQLだけに回答を与えました。
改訂

-4

あなたは試すことができDELETE FROM <your table >;ます。

サーバーは制限の名前とテーブルを表示し、そのテーブルを削除すると必要なものを削除できます。


6
質問の彼の2番目のフレーズを読んでください。彼はそれができると知っていますが、それは彼が望んでいることではありません
renanleandrof

-7
SET FOREIGN_KEY_CHECKS=0;
TRUNCATE table1;
TRUNCATE table2;
SET FOREIGN_KEY_CHECKS=1;

参照- 外部キー制約テーブルを切り捨てます

MYSQLで私のために働く


1
指定されたバージョン以外に、これに何か問題がありますか?それを使用することをお勧めしますか、それとも完全に回避しますか?
アンディアイバニーズ2013年

1
@AndyIbanez MySQLはMSSQLとは完全に異なる製品であり、MSSQLの異なるバージョンではありません。
Dan Bechard、2015年

1
その正解私はなぜ誰もが否定を与えるのか分かりません
sunil '18
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.