FOREIGN KEY 제약 조건에서 참조하고 있으므로 테이블을자를 수 없습니까?


459

MSSQL2005를 사용하여 자식 테이블 (FK 관계의 기본 키가있는 테이블)을 먼저 자르면 외래 키 제약 조건으로 테이블을자를 수 있습니까?

나도 할 수 있다는 것을 안다

  • DELETEwhere 절을 사용 하지 않고 RESEEDidentity를 사용하십시오.
  • FK를 제거하고 테이블을 자르고 FK를 다시 작성하십시오.

부모 앞에서 자식 테이블을 자르면 위의 옵션 중 하나를 수행하지 않아도 괜찮을 것이라고 생각했지만이 오류가 발생합니다.

테이블 'TableName'이 FOREIGN KEY 제약 조건에 의해 참조되므로 잘라낼 수 없습니다.

답변:


379

옳은; FK 제약 조건이있는 테이블은자를 수 없습니다.

일반적으로 내 프로세스는 다음과 같습니다.

  1. 구속 조건 삭제
  2. 테이블 자르기
  3. 구속 조건을 다시 작성하십시오.

(물론 거래에서 모두.)

물론 이것은 자식이 이미 잘린 경우에만 적용됩니다 . 그렇지 않으면 나는 내 데이터의 모양에 전적으로 의존하여 다른 경로를 간다. (여기에 들어갈 변수가 너무 많습니다.)

원래의 포스터가 왜 그런지 결정했습니다. 자세한 내용 은 이 답변 을 참조하십시오.


73
"DELETE FROM"은 자동 증가 열을 재설정하지 않습니다. 잘립니다. 그것들은 기능적으로 동등하지 않습니다.
robross0606

35
대량의 데이터를 삭제하는 경우 자르기는 종종 정확하게 수행하려는 작업입니다. 백만 행을 자르시겠습니까? 10 억? 1ms ... @ M07, "원격에서 삭제하는 것이 더 깨끗합니다"라고 말하지 마십시오. 원격으로 정확하지 않기 때문입니다.
ctb

1
큰 데이터를 삭제 한 후 사용자는 디스크 공간을 확보하기 위해 테이블과 로그 파일을 축소해야합니다.
무하마드 Yousaf 술라 리아

2
Magic Shrink 버튼 (또는 스크립트)은 99 %의 시간을 권장하지 않습니다.
Tom Stickel

1
어떻게 하시겠습니까? 요청 예?
jeromej

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

매우 느리기 때문에 수백만 개 이상의 레코드를 보유하고 있다면 이것이 원하는 것은 아닙니다.


제약 조건을 비활성화하고 활성화하는 것보다 유용하고 빠른 방법이었습니다.
sensei

데이터가 적은 테이블에서만 작동합니다. @Pure
Dhanuka777에

1
이것은 스키마 테스트가 끝났을 때 유용합니다
ohmusama

3
당신이 오류를 얻을 수 있습니다 나는이 길을가는 제안하지 것이다 : 참조 제약 조건과 충돌 DELETE 문을
sksallaj

나를 위해 일하지 않았다. DELETE 문이 REFERENCE 제한 조건과 충돌했습니다.
emirhosseini

192

때문에 TRUNCATE TABLEA는 DDL 명령 , 그것은 테이블의 레코드가 자식 테이블의 레코드에 의해 참조되고 있는지 여부를 확인할 수 없습니다.

데이터베이스가 다른 레코드에 의해 참조되고 있지 않은지 확인할 수 있기 때문에 이것이 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이 모두 1 대신 ID 2에서 시작된 후 다시 시드 된 새 값 = 1을 사용하는 경우 Technet ( technet.microsoft.com/en-us/library/ms176057%28SQL.90%29.aspx ) 행이없는 경우 DBCC CHECKIDENT를 실행 한 후 삽입 된 첫 번째 행은 new_reseed_value를 ID로 사용합니다. 그렇지 않으면 삽입 된 다음 행은 new_reseed_value + 현재 증분 값을 사용합니다.
Zoran P.

@ZoranP. 저장 프로 시저의 변형을 참조하십시오 github.com/reduardo7/TableTruncate
에두아르도 쿠 오모

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

1
@TicoFortes Post가 업데이트되었습니다.
Eduardo Cuomo

1
이것은 좋은 접근 방식이 아닙니다. 이 질문에 대한 동일한 답변의 700 가지 다른 버전에서 언급했듯이. 트랜잭션 로깅을 제한하기 위해 데이터베이스가 단순 복구 모드에 있지 않으면.
pimbrouwers

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

4
이 코드 조각에 감사드립니다. 그러나 비활성화 된 FK를 확인하기 위해 추가 로직을 추가해야합니다. 그렇지 않으면 현재 비활성화 된 제약 조건을 활성화합니다.
Andre Figueiredo

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

1
어떻게에서이 응답 다른 하나 주어졌다, 1 년 전에는?
Ofer Zelig

17

글쎄, 내가 사용한 매우 간단한 솔루션의 를 찾지 못했기 때문에 다음과 같습니다.

  1. 외래 키를 삭제하십시오.
  2. 테이블 자르기
  3. 외래 키 재 작성

여기 간다:

1) 실패의 원인이되는 외래 키 이름을 찾으십시오 (예 : ID테이블에서 필드가있는 FK_PROBLEM_REASON 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

1
이것은 나를 위해 작동하지 않지만 그 정신을 좋아해서 몇 가지 사항을 수정했습니다. 저장 키를 사용하여 외래 키가 채워지는 방식을 변경하고 원본 스크립트를 다시 만들면 모든 참조 테이블이 잘립니다. 참조 할 때 잘못 될 수 있습니다 외래 키 참조도 있으므로 테이블을자를 수 없습니다. 이 버전에서는 매개 변수로 지정된 테이블 만 잘립니다.이 스크립트를 호출하기 전에 참조 된 모든 테이블을 수동으로 잘 려야합니다.이 스레드에 업데이트 된 tolution을 여기에 게시했습니다. stackoverflow.com/a/13249209/157591
Peter Szanto

1
@alphadogg 이러한 참조 동작을 찾을 수있는 방법이 있습니까? 나는 인터넷 주위를 파고 있었고 찾을 수없는 것 같습니다. 원한다면 공식적인 질문으로 게시 할 수 있습니다.
마이클 - 클레이 셔키는 어디

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
이것이 잘 작동하더라도 트랜잭션 로그는 하나의 레코드 만 트랜잭션 로그에 넣는 테이블 자르기 대 테이블의 레코드 수만큼 증가합니다. 대부분의 테이블에 큰 문제는 아니지만 수백만 행 이상이 있으면 문제가 될 수 있습니다.
David

8

만약 내가 제대로 이해하고, 당신이 원하는 해야 할 것은 깨끗한 환경이 통합 테스트를 포함하는 DB에 설정해야 할 것입니다.

내 접근 방식은 전체 스키마를 삭제하고 나중에 다시 만드는 것입니다.

원인:

  1. 이미 "스키마 생성"스크립트가있을 것입니다. 테스트 격리를 위해 재사용하는 것은 쉽습니다.
  2. 스키마를 만드는 것은 매우 빠릅니다.
  3. 이 접근 방식을 사용하면 각 조명기가 새로운 스키마 (임시 이름으로)를 작성하도록 스크립트를 설정하는 것이 매우 쉽습니다. 그런 다음 테스트 픽스처를 병렬로 시작하여 테스트 스위트의 가장 느린 부분을 훨씬 빠르게 만들 수 있습니다 .

1
모든 스키마를 '절단'하고 삭제하지는 않습니다. 통합 테스트의 설정 방법에서 수행하고 싶습니다. 통합 테스트 내에서 DB 생성 스크립트를 호출하는 것은 ...가는 첫 번째 솔루션이 아닙니다.
ripper234

8
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 서버
Cocowalla

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? CHECK CHECK CONSTRAINT ALL '을 선택하십시오.
Andriy M

20
-1 : 방금 질문 한대로 truncate 명령으로이 기능이 전혀 작동하지 않음을 확인했습니다. 참조 stackoverflow.com/questions/3843806/...
린 무너져

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

truncate가 작동하지 않았습니다. 삭제 + reseed가 가장 좋은 방법입니다. delete + reseed를 수행하기 위해 많은 수의 테이블을 반복 해야하는 일부 사용자가있는 경우 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

그래서 다음과 같은 방법으로하고, 그들을 파라미터하려 쓰기 작업을 수행 할 수 있습니다 A의를 실행 Query document또는 유용합니다 SP쉽게 그들과 함께 .

A) 삭제

경우 테이블이 기록되지 수백만을 가지고 이 잘 작동 되지 않은 바꿔 명령이 있습니다 :

---------------------------------------------------------------
------------------- 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) 자르기

경우 테이블이 기록의 수백만이있다 또는 당신은 어떤 문제가되지가 알터 명령 당신의 코드에를, 다음이 하나를 사용합니다 :

--   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

나는 이것이 작동하지 않는다고 위에서 생각한 것 같아? 아마도 최신 버전일까요?
Coops

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;

노트 :

테이블을 삭제하려는 순서대로 선언하는 것이 여전히 도움이된다고 생각합니다 (즉, 종속성을 먼저 종료). 이 답변 에서 볼 수 있듯이 루프 특정 이름 대신 모든 테이블을 다음과 같이 대체 할 수 있습니다

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

외래 키가 있으면 작동하지 않는다고 모든 사람들이 말했기 때문에 실제로 다른 스크립트를 시도하지 않았습니다. 그래서 나는 이것을 시도했고 이것은 나를 위해 트릭을했다.
Vivendi

1
DELETE 와 동일 하지 않습니다TRUNCATE . 트랜잭션 로그가 채워집니다.
Dan Bechard

@ Dan, 아마 좋은 지적이다. 내가 언급했듯이 여기에 다른 답변을 결합했습니다 ...
drzaus

@drzaus 소규모 / 중형 테이블에서는 제대로 작동하지만 트랜잭션 로그를 채우는 삭제 명령으로 인해 프로덕션 SQL 서버가 오프라인 상태가되어 하드 디스크가 가득 찼습니다. 최소한 큰 테이블에서이를 시도하기 전에 트랜잭션 로그가 최대 크기인지 확인하십시오.
Dan Bechard

2

내 경우처럼 이러한 답변 중 어느 것도 효과가 없다면 다음과 같이하십시오.

  1. 드롭 제약
  2. 널을 허용하도록 모든 값을 설정하십시오.
  3. 테이블 자르기
  4. 삭제 된 구속 조건을 추가하십시오.

행운을 빕니다!


그것에 대한 모든 SQL 샘플?
Kiquenet

2

자동 증분 삭제 후 재설정 :

delete from tablename;

그때

ALTER TABLE tablename AUTO_INCREMENT = 1;

고마워, 이것은 잘 작동했습니다.
Mr. Polywhirl

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에서 키를 보여주는 Diagram을 열었습니다. 키를 삭제하고 파일을 자른 후 새로 고친 다음 다이어그램에 다시 초점을 맞추고 ID 상자를 지우고 복원하여 업데이트를 작성했습니다. 다이어그램을 저장하면 "작업하는 동안 데이터베이스에서 변경되었습니다"대화 상자보다 저장 대화 상자가 나타납니다. 예를 클릭하면 키가 복원되어 다이어그램의 래치 된 사본에서 복원됩니다.


0

일정 빈도 로도이 작업을 수행하는 경우 절대적으로 절대 DML 문을 사용하지 않을 것입니다. 트랜잭션 로그에 쓰는 데 드는 비용은 매우 높으며 전체 데이터베이스를 SIMPLE복구 모드 로 설정하여 하나의 테이블을 자르는 것은 우스운 일입니다.

가장 좋은 방법은 불행히도 힘들거나 힘든 방법입니다. 그것은 :

  • 드롭 제약
  • 테이블 자르기
  • 구속 조건 재 작성

이 작업을 수행하는 프로세스에는 다음 단계가 포함됩니다.

  1. SSMS에서 해당 테이블을 마우스 오른쪽 단추로 클릭하고 종속성보기를 선택하십시오.
  2. 참조 된 표를 기록하십시오 (있는 경우).
  3. 개체 탐색기로 돌아가서 노드를 확장 하고 외래 키 (있는 경우)를 기록합니다
  4. 스크립팅 시작 (삭제 / 잘라 내기 / 다시 만들기)

이 특성의 스크립트는 및 블록 내에서 수행 해야 합니다 .begin trancommit 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

-3

가장 쉬운 방법 :
1-phpmyadmin에 입력
2-왼쪽 열에서 테이블 이름
클릭 3-작업 클릭 (최상위 메뉴)
4- "테이블 비우기 (TRUNCATE)
5-비활성화 상자"외래 키 검사 활성화 "
6-완료 !

이미지 링크 튜토리얼
튜토리얼 : http://www.imageno.com/wz6gv1wuqajrpic.html
(미안 해요, 내가 여기에 이미지를 업로드 할 수있는 충분한 명성이 없습니다 : P를)


2
OP는 MSSQL을 명시했습니다. 당신은 MySQL에게 독점적 인 답변을주었습니다.
개정

-4

시도해 볼 수 DELETE FROM <your table >;있습니다.

서버는 제한 및 테이블 이름을 표시하고 해당 테이블을 삭제하면 필요한 것을 삭제할 수 있습니다.


6
질문에 대한 두 번째 문구를 읽으십시오. 그는 그가 할 수 있다는 것을 알고 있지만 그것이 원하는 것이 아닙니다
renanleandrof

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

참조- 외래 키 제한 테이블 자르기

MYSQL에서 나를 위해 일하기


1
지정된 버전 이외의 다른 문제가 있습니까? 그것을 사용하거나 완전히 피하는 것이 좋습니다?
Andy Ibanez

1
@AndyIbanez MySQL은 다른 버전의 MSSQL이 아니라 MSSQL과 완전히 다른 제품입니다.
Dan Bechard

1
정답 나는 왜 모든 사람들이 부정적인 반응을하는지 모르겠다
sunil
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.