SQL Server 데이터베이스의 모든 테이블에서 모든 행을 삭제하는 방법은 무엇입니까?


답변:


264

참조 무결성이 설정되어 있으면 TRUNCATE가 작동하지 않습니다.

이 경우 작동합니다.

EXEC sp_MSForEachTable 'DISABLE TRIGGER ALL ON ?'
GO
EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
GO
EXEC sp_MSForEachTable 'DELETE FROM ?'
GO
EXEC sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'
GO
EXEC sp_MSForEachTable 'ENABLE TRIGGER ALL ON ?'
GO

1
실제로 이는 DDL 트리거에만 해당됩니다. 어떤 경우 : EXECP sp_MSForEachTable 'DISABLE TRIGGER ALL ON?'
Mark Rendle 2009

10
SQL Azure에서는 사용할 수 없음 :(
Akash Kava

Ok 약간 혼란스러워 (아마 도움이 될 수 있습니다) 데이터베이스 백업을 만들었고 약 10MB였습니다. 그런 다음 SQL 코드를 실행하여 데이터베이스를 비우고 내 생각에 대한 새로운 백업을 만들었습니다. 이메일로 다른 사람에게 보낼 데이터베이스가 비어 있지만 '빈'데이터베이스 백업이 이제 14MB입니까? 내가 뭘 잘못 했어?
Ben

1
알았어-백업 파일이 이미 존재하면 SSMS가 파일을 바꾸지 않고 추가하는 것처럼 보입니다 (이것을 몰랐습니다). 그래서 파일을 삭제
Ben

1
DB를 선택하려면 다음과 같이하십시오 USE [MyDataBase]. 어떻게 든 적응하면 위의 아이디어가 효과가 있습니까? ... SQL 서버가 유지하는 모든 DB를 삭제하고 싶지 않기 때문에.
סטנלי גרונן

20

최근 프로젝트에서 내 작업은 sql 문과 기본 키 및 외래 키와 같은 많은 제약 조건이있는 각 테이블을 사용하여 전체 데이터베이스를 정리하는 것이 었습니다. 데이터베이스에 1000 개가 넘는 테이블이 있으므로 각 테이블에 대해 삭제 쿼리를 작성할 수 없습니다.

sp_MSForEachTable 이라는 저장 프로 시저를 사용하면 단일 데이터베이스의 각 테이블에 대해 일부 코드를 쉽게 처리 할 수 ​​있습니다. 즉, 데이터베이스의 모든 테이블에 대해 단일 T-SQL 명령 또는 다른 T-SQL 명령을 처리하는 데 사용됩니다.

따라서 아래 단계에 따라 SQL Server 데이터베이스의 모든 테이블을 자릅니다.

1 단계-아래 SQL 쿼리를 사용하여 데이터베이스의 모든 제약 조건을 비활성화하십시오.

EXEC sys.sp_msforeachtable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'

2 단계 아래 sql 명령을 사용하여 데이터베이스의 각 테이블에서 삭제 또는 자르기 작업을 실행합니다.

EXEC sys.sp_msforeachtable 'DELETE FROM ?'

3 단계-아래 sql 문을 사용하여 데이터베이스에서 모든 제약 조건을 활성화합니다.

EXEC sys.sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'

1
의존성이없는 테이블을 처음으로 삭제하는 경우, 처음에 실패한 테이블을 삭제하는 두 번째 시간, 두 번째 시간에 삭제하는 세 번째 시간 등을 수행하기 위해 간단히 2 단계 mutliple 시간을 실행할 수 있습니다.

이 작업을 수행하는 방법에 대한 아이디어가 sql server azure있습니까?
Zapnologica

그것은 단지 일반 SQL을 사용하기 때문에이 방법 푸른에서도 작동합니다 sqlrelease.com/delete-all-rows-from-all-tables
야콥 Lithner

15

모든 행을 삭제하고 다음 스크립트로 수행했습니다.

DECLARE @Nombre NVARCHAR(MAX);
DECLARE curso CURSOR FAST_FORWARD 
FOR 
Select Object_name(object_id) AS Nombre from sys.objects where type = 'U'

OPEN curso
FETCH NEXT FROM curso INTO @Nombre

WHILE (@@FETCH_STATUS <> -1)
BEGIN
IF (@@FETCH_STATUS <> -2)
BEGIN
DECLARE @statement NVARCHAR(200);
SET @statement = 'DELETE FROM ' + @Nombre;
print @statement
execute sp_executesql @statement;
END
FETCH NEXT FROM curso INTO @Nombre
END
CLOSE curso
DEALLOCATE curso

도움이 되었기를 바랍니다!


일부 테이블을 제거하기 위해 선택을 조정해야했기 때문에 이것에 감사드립니다. 이것은 잘 작동했습니다.
돈 롤링

13

해결책은 다음과 같습니다.

  1. 제약 조건을 삭제합니다 ( 게시물 덕분에 )
  2. INFORMATION_SCHEMA.TABLES특정 데이터베이스에 대해 반복
  3. SELECTS 일부 검색 기준에 따른 테이블
  4. 해당 테이블에서 모든 데이터를 삭제합니다
  5. 구속 조건 다시 추가
  6. 같은 특정 테이블의 무시를 허용 sysdiagrams하고__RefactorLog

처음에 시도 EXECUTE sp_MSforeachtable 'TRUNCATE TABLE ?'했지만 다이어그램이 삭제되었습니다.

USE <DB name>;
GO

-- Disable all constraints in the database
EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"

declare @catalog nvarchar(250);
declare @schema nvarchar(250);
declare @tbl nvarchar(250);
DECLARE i CURSOR LOCAL FAST_FORWARD FOR select
                                        TABLE_CATALOG,
                                        TABLE_SCHEMA,
                                        TABLE_NAME
                                        from INFORMATION_SCHEMA.TABLES
                                        where
                                        TABLE_TYPE = 'BASE TABLE'
                                        AND TABLE_NAME != 'sysdiagrams'
                                        AND TABLE_NAME != '__RefactorLog'

OPEN i;
FETCH NEXT FROM i INTO @catalog, @schema, @tbl;
WHILE @@FETCH_STATUS = 0
    BEGIN
        DECLARE @sql NVARCHAR(MAX) = N'DELETE FROM [' + @catalog + '].[' + @schema + '].[' + @tbl + '];'
        /* Make sure these are the commands you want to execute before executing */
        PRINT 'Executing statement: ' + @sql
        -- EXECUTE sp_executesql @sql
        FETCH NEXT FROM i INTO @catalog, @schema, @tbl;
    END
CLOSE i;
DEALLOCATE i;

-- Re-enable all constraints again
EXEC sp_msforeachtable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"

이것은 훌륭하지만 dbo가 아닌 스키마를 고려하지는 않습니다.
유입 :

나는 비 dbo 스키마를 사용한 적이 없으므로 그것을 잡지 않을 것입니다. 그러나 왜 작동하지 않습니까? 스키마를 지정하지 않았으므로 기본값은 dbo입니까?
Zach Smith

예를 들어, test.Table1이라는 테이블이있는 경우 "test"는 스키마이며 "DELETE FROM Table1"을 실행하려고하면 삭제가 실패합니다. DELETE FROM test 여야합니다.
유입 :

2
@influent-이제 dbo가 아닌 스키마를 고려합니다
Zach Smith

불행히도 FK 제약 조건이 있으면 실패한 것 같습니다. ALTER TABLE제약 조건을 비활성화 하는 비트가 실패합니다.
Douglas Gaskell

8

제 경우에는 QUOTED_IDENTIFIER를 설정해야했습니다. 이로 인해 위의 Mark Rendle의 답변이 약간 수정되었습니다.

EXEC sp_MSForEachTable 'DISABLE TRIGGER ALL ON ?'
GO
EXEC sp_MSForEachTable 'ALTER TABLE ? NOCHECK CONSTRAINT ALL'
GO
EXEC sp_MSForEachTable 'SET QUOTED_IDENTIFIER ON; DELETE FROM ?'
GO
EXEC sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'
GO
EXEC sp_MSForEachTable 'ENABLE TRIGGER ALL ON ?'
GO

나를 위해 일했습니다-이 오류가 발생하기 전에 :DELETE failed because the following SET options have incorrect settings: 'QUOTED_IDENTIFIER'. Verify that SET options are correct for use with indexed views and/or indexes on computed columns and/or filtered indexes and/or query notifications and/or XML data type methods and/or spatial index operations.
DharmaTurtle

4
Set nocount on

Exec sp_MSForEachTable 'Alter Table ? NoCheck Constraint All'

Exec sp_MSForEachTable
'
If ObjectProperty(Object_ID(''?''), ''TableHasForeignRef'')=1
Begin
-- Just to know what all table used delete syntax.
Print ''Delete from '' + ''?''
Delete From ?
End
Else
Begin
-- Just to know what all table used Truncate syntax.
Print ''Truncate Table '' + ''?''
Truncate Table ?
End
'

Exec sp_MSForEachTable 'Alter Table ? Check Constraint All'

1

Rubens 제안과 같은 접근 방식을 사용하여 모든 테이블에서 모든 행을 삭제하거나 모든 테이블을 삭제하고 다시 만들 수 있습니다. 어쨌든 가장 쉬운 / 빠른 방법이 될 수 있도록 전체 DB 작성 스크립트를 사용하는 것이 좋습니다.


OP가 참조 무결성 및 트리거에 관심이있는 것 같습니다. 이 경우 최상의 해결책이 있습니다. 나는) = 내 대답을 떨어 뜨리고있어
루벤스 파리 아스에게

2
나는) = 그것을 잘라내는 것을 의미
루벤스 파리 아스에게

0

일부 요구 사항의 경우 특정 테이블을 건너 뛰어야 할 수도 있습니다. 테이블 목록을 필터링하기 위해 몇 가지 추가 조건을 추가하기 위해 아래 스크립트를 작성했습니다. 아래 스크립트에는 사전 삭제 횟수와 사후 삭제 횟수도 표시됩니다.

        IF OBJECT_ID('TEMPDB..#TEMPRECORDCOUNT') IS NOT NULL 
        DROP TABLE #TEMPRECORDCOUNT 

        CREATE TABLE #TEMPRECORDCOUNT 
            (    TABLENAME NVARCHAR(128)
                ,PREDELETECOUNT BIGINT
                ,POSTDELETECOUNT BIGINT
            ) 

        INSERT INTO #TEMPRECORDCOUNT (TABLENAME, PREDELETECOUNT, POSTDELETECOUNT)

        SELECT   O.name TableName
                ,DDPS.ROW_COUNT PREDELETECOUNT
                ,NULL  FROM sys.objects O 

        INNER JOIN (

                    SELECT OBJECT_ID, SUM(row_count) ROW_COUNT 
                    FROM SYS.DM_DB_PARTITION_STATS
                    GROUP BY OBJECT_ID
                   ) DDPS ON DDPS.OBJECT_ID = O.OBJECT_ID
        WHERE O.type = 'U' AND O.name NOT LIKE 'OC%' AND O.schema_id = 1

        DECLARE @TableName NVARCHAR(MAX);
        DECLARE TableDeleteCursor CURSOR FAST_FORWARD 
        FOR 
        SELECT TableName from #TEMPRECORDCOUNT

        OPEN TableDeleteCursor
        FETCH NEXT FROM TableDeleteCursor INTO @TableName

        WHILE (@@FETCH_STATUS <> -1)
        BEGIN
        IF (@@FETCH_STATUS <> -2)
        BEGIN
        DECLARE @STATEMENT NVARCHAR(MAX);
        SET @STATEMENT = ' DISABLE TRIGGER ALL ON ' + @TableName + 
                         '; ALTER TABLE ' + @TableName + ' NOCHECK CONSTRAINT ALL' +
                         '; DELETE FROM ' + @TableName +
                         '; ALTER TABLE ' + @TableName + ' CHECK CONSTRAINT ALL' +
                         '; ENABLE TRIGGER ALL ON ' + @TableName;
        PRINT @STATEMENT
        EXECUTE SP_EXECUTESQL @STATEMENT;
        END
        FETCH NEXT FROM TableDeleteCursor INTO @TableName
        END
        CLOSE TableDeleteCursor
        DEALLOCATE TableDeleteCursor

        UPDATE T 
         SET T.POSTDELETECOUNT = I.ROW_COUNT 
         FROM #TEMPRECORDCOUNT T 
         INNER JOIN (
                        SELECT O.name TableName, DDPS.ROW_COUNT ROW_COUNT  
                        FROM sys.objects O 
                        INNER JOIN (

                                SELECT OBJECT_ID, SUM(row_count) ROW_COUNT 
                                FROM SYS.DM_DB_PARTITION_STATS
                                GROUP BY OBJECT_ID
                               ) DDPS ON DDPS.OBJECT_ID = O.OBJECT_ID
                        WHERE O.type = 'U' AND O.name NOT LIKE 'OC%' AND O.schema_id = 1

                    ) I ON I.TableName COLLATE DATABASE_DEFAULT = T.TABLENAME 

        SELECT * FROM #TEMPRECORDCOUNT 
        ORDER BY TABLENAME ASC

0

이 답변은 ID 열도 재설정하여 Zach Smith의 답변을 기반 으로합니다.

  1. 모든 제약 조건 비활성화
  2. 제외하기로 선택한 테이블을 제외한 모든 테이블을 반복
  3. 테이블에서 모든 행을 삭제합니다
  4. 존재하는 경우 식별 컬럼을 재설정합니다
  5. 모든 제약 조건을 다시 활성화

다음은 쿼리입니다.

-- Disable all constraints in the database
EXEC sp_msforeachtable "ALTER TABLE ? NOCHECK CONSTRAINT all"

declare @catalog nvarchar(250);
declare @schema nvarchar(250);
declare @tbl nvarchar(250);
DECLARE i CURSOR LOCAL FAST_FORWARD FOR select
                                        TABLE_CATALOG,
                                        TABLE_SCHEMA,
                                        TABLE_NAME
                                        from INFORMATION_SCHEMA.TABLES
                                        where
                                        TABLE_TYPE = 'BASE TABLE'
                                        AND TABLE_NAME != 'sysdiagrams'
                                        AND TABLE_NAME != '__RefactorLog'
                                        -- Optional
                                        -- AND (TABLE_SCHEMA = 'dbo')

OPEN i;
FETCH NEXT FROM i INTO @catalog, @schema, @tbl;
WHILE @@FETCH_STATUS = 0
    BEGIN
        DECLARE @sql NVARCHAR(MAX) = N'DELETE FROM [' + @catalog + '].[' + @schema + '].[' + @tbl + '];'
        /* Make sure these are the commands you want to execute before executing */
        PRINT 'Executing statement: ' + @sql
        --EXECUTE sp_executesql @sql

        -- Reset identity counter if one exists
        IF ((SELECT OBJECTPROPERTY( OBJECT_ID(@catalog + '.' + @schema + '.' + @tbl), 'TableHasIdentity')) = 1)
        BEGIN
            SET @sql = N'DBCC CHECKIDENT ([' + @catalog + '.' + @schema + '.' + @tbl + '], RESEED, 0)'
            PRINT 'Executing statement: ' + @sql
            --EXECUTE sp_executesql @sql
        END     

        FETCH NEXT FROM i INTO @catalog, @schema, @tbl;
    END
CLOSE i;
DEALLOCATE i;

-- Re-enable all constraints again
EXEC sp_msforeachtable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"

어떤 이유로 든 FK 제약 조건 오류가 발생하여 대부분 실패합니다.
Douglas Gaskell

0
--Load tables to delete from
SELECT 
DISTINCT
' Delete top 1000000 from <DBName>.<schema>.' + c.TABLE_NAME + ' WHERE <Filter Clause Here>' AS query,c.TABLE_NAME AS TableName, IsDeleted=0, '<InsertSomeDescriptorHere>' AS [Source]--,t.TABLE_TYPE, c.*
            INTO dbo.AllTablesToDeleteFrom
            FROM INFORMATION_SCHEMA.TABLES AS t
            INNER JOIN information_schema.columns c ON c.TABLE_NAME = t.TABLE_NAME 
    WHERE c.COLUMN_NAME = '<column name>'
           AND c.TABLE_SCHEMA = 'dbo'
           AND c.TABLE_CATALOG = '<DB Name here>'
           AND t.TABLE_TYPE='Base table'
           --AND t.TABLE_NAME LIKE '<put filter here>'

            DECLARE @TableSelect NVARCHAR(1000)= '';
            DECLARE @Table NVARCHAR(1000)= '';
            DECLARE @IsDeleted INT= 0;
            DECLARE @NumRows INT = 1000000;
            DECLARE @Source NVARCHAR(50)='';


            WHILE ( @IsDeleted = 0 )
                BEGIN
                --This grabs one table at a time to be deleted from. @TableSelect has the sql to execute. it is important to order by IsDeleted ASC
                --because it will pull tables to delete from by those that have a 0=IsDeleted first. Once the loop grabs a table with IsDeleted=1 then this will pop out of loop

                    SELECT TOP 1
                            @TableSelect = query,
                            @IsDeleted = IsDeleted,
                            @Table = TableName,
                            @Source=[a].[Source]
                    FROM    dbo.AllTablesToDeleteFrom a
                    WHERE a.[Source]='SomeDescriptorHere'--use only if needed
                    ORDER BY a.IsDeleted ASC;--this is required because only those records returned with IsDeleted=0 will run through loop

                    --SELECT  @Table; can add this in to  monitor what table is being deleted from

                    WHILE ( @NumRows = 1000000 )--only delete a million rows at a time?

                    BEGIN 
                    EXEC sp_executesql @TableSelect;
                    SET @NumRows = @@ROWCOUNT;
                    --IF @NumRows = 1000000 --can do something here if needed
                    --One wants this loop to continue as long as a million rows is deleted. Once < 1 million rows is deleted it pops out of loop
                    --and grabs next table to delete
                    --    BEGIN
                    --SELECT  @NumRows;--can add this in to see current number of deleted records for table
                            INSERT  INTO dbo.DeleteFromAllTables
                                    ( tableName,
                                      query,
                                      cnt,
                                      [Source]
                                    )
                            SELECT  @Table,
                                    @TableSelect,
                                    @NumRows,
                                    @Source;
                     --   END; 
                END; 



SET @NumRows = 1000000;

UPDATE  a
SET     a.IsDeleted = 1
FROM    dbo.AllTablesToDeleteFrom a
WHERE   a.TableName = @Table;
--flag this as deleted so you can move on to the next table to delete from

END; 

-3

전체 테이블을 삭제하려면 다음 SQL 명령어를 따라야합니다.

Delete  FROM TABLE Where PRIMARY_KEY_ is Not NULL;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.