Làm cách nào để xóa tất cả các hàng khỏi tất cả các bảng trong cơ sở dữ liệu SQL Server?


Câu trả lời:


264

Lưu ý rằng TRUNCATE sẽ không hoạt động nếu bạn có bất kỳ bộ toàn vẹn tham chiếu nào.

Trong trường hợp đó, điều này sẽ hoạt động:

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
Trên thực tế, đó chỉ là kích hoạt DDL. Trong trường hợp nào: EXECP sp_MSForEachTable 'DIIGABLE TRIGGER ALL ON?'
Đánh dấu Rendle

10
Không khả dụng trong SQL Azure :(
Akash Kava

Ok tôi hơi bối rối (có lẽ bạn có thể giúp đỡ) Tôi đã tạo một bản sao lưu cơ sở dữ liệu của mình và nó có dung lượng khoảng 10 MB, sau đó tôi chạy mã SQL của bạn ở trên để làm trống cơ sở dữ liệu của tôi và tôi đã tạo một bản sao lưu mới của những gì tôi nghĩ là cơ sở dữ liệu trống để gửi cho người khác trong email nhưng sao lưu cơ sở dữ liệu 'trống' của tôi bây giờ là 14 MB? Tôi đã làm gì sai?
Bến

1
Có nó - nếu một tập tin sao lưu đã tồn tại thì có vẻ như SSMS nối vào nó thay vì thay thế nó (tôi đã không nhận ra điều này). Vì vậy, tôi đã xóa tệp và bây giờ tệp sao lưu cơ sở dữ liệu 'trống' chỉ còn 3,7 MB
Ben

1
Nếu tôi muốn chọn DB, thì sao : USE [MyDataBase]? Ý tưởng trên có hoạt động không, nếu được điều chỉnh bằng cách nào đó? ... Bởi vì tôi không muốn xóa tất cả các DB được giữ bởi máy chủ SQL.
סטנלי גרונן

20

Trong dự án gần đây, nhiệm vụ của tôi là dọn dẹp toàn bộ cơ sở dữ liệu bằng cách sử dụng câu lệnh sql và mỗi bảng có nhiều ràng buộc như Khóa chính và Khóa ngoài. Có hơn 1000 bảng trong cơ sở dữ liệu để không thể viết truy vấn xóa trên mỗi bảng.

Bằng cách sử dụng một thủ tục được lưu trữ có tên sp_MSForEachTable , cho phép chúng ta dễ dàng xử lý một số mã đối với từng bảng trong một cơ sở dữ liệu. Điều đó có nghĩa là nó được sử dụng để xử lý một lệnh T-SQL hoặc một lệnh T-SQL khác nhau đối với mọi bảng trong cơ sở dữ liệu.

Vì vậy, hãy làm theo các bước dưới đây để cắt bớt tất cả các bảng trong Cơ sở dữ liệu SQL Server:

Bước 1- Vô hiệu hóa tất cả các ràng buộc trên cơ sở dữ liệu bằng cách sử dụng truy vấn sql bên dưới:

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

Bước 2- Thực hiện thao tác Xóa hoặc cắt bớt trên mỗi bảng của cơ sở dữ liệu bằng cách sử dụng lệnh sql bên dưới:

EXEC sys.sp_msforeachtable 'DELETE FROM ?'

Bước 3- Kích hoạt tất cả các ràng buộc trên cơ sở dữ liệu bằng cách sử dụng câu lệnh sql bên dưới:

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

1
Bạn chỉ có thể thực hiện bước 2 lần đột biến để lần đầu tiên xóa các bảng không phụ thuộc, lần thứ hai xóa các bảng đó không thành công lần thứ nhất, lần thứ 3 để xóa faild trong lần thứ 2, v.v.

bất kỳ ý tưởng về làm thế nào để làm điều này trên sql server azure?
Zapnologica

Cách tiếp cận này cũng sẽ hoạt động trong Azure vì nó chỉ sử dụng SQL đơn giản: sqlrelease.com/delete-all-rows-from-all-tables
Jakob Lithner

15

Tôi đã phải xóa tất cả các hàng và thực hiện nó với tập lệnh tiếp theo:

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

Hi vọng điêu nay co ich!


Cảm ơn vì điều này, vì tôi cần phải điều chỉnh lựa chọn để loại bỏ một số bảng. Điều này làm việc tốt cho điều đó.
Don lăn

13

Đây là một giải pháp:

  1. Giọt hạn chế (nhờ bài này )
  2. Lặp lại thông qua INFORMATION_SCHEMA.TABLEScho một cơ sở dữ liệu cụ thể
  3. SELECTS bảng dựa trên một số tiêu chí tìm kiếm
  4. Xóa tất cả dữ liệu khỏi các bảng đó
  5. Thêm các ràng buộc
  6. Cho phép bỏ qua các bảng nhất định như sysdiagrams__RefactorLog

Tôi đã thử ban đầu EXECUTE sp_MSforeachtable 'TRUNCATE TABLE ?', nhưng điều đó đã xóa sơ đồ của tôi.

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"

Điều này thật tuyệt nhưng nó không tính đến các lược đồ phi dbo.
có ảnh hưởng

Tôi chưa bao giờ sử dụng các lược đồ không dbo, vì vậy tôi sẽ không nắm bắt được điều đó. Nhưng tại sao nó không hoạt động? Tôi không chỉ định lược đồ ở bất cứ đâu nên nó chỉ mặc định là dbo?
Zach Smith

Nếu bạn có một bảng, ví dụ, được gọi là test.Table1, trong đó "test" là lược đồ, việc xóa của bạn sẽ thất bại nếu cố gắng thực hiện "XÓA TỪ Bảng1". Nó cần phải được XÓA TỪ test.Table1.
ảnh hưởng

2
@influent - bây giờ cần có các lược đồ không phải là dbo
Zach Smith

Thật không may, điều này dường như thất bại nếu có các ràng buộc FK. Các ALTER TABLEbit để vô hiệu hóa các ràng buộc không thành công.
Douglas Gaskell

8

Trong trường hợp của tôi, tôi cần đặt QUOTED_IDENTIFIER. Điều này dẫn đến một sửa đổi nhỏ trong câu trả lời của Mark Rendle ở trên:

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

Làm việc cho tôi - trước khi tôi gặp lỗi này: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

Bạn có thể xóa tất cả các hàng khỏi tất cả các bảng bằng cách sử dụng phương pháp như Rubens đã đề xuất hoặc bạn chỉ có thể thả và tạo lại tất cả các bảng. Luôn luôn là một ý tưởng tốt để có các tập lệnh tạo db đầy đủ vì vậy đó có thể là phương pháp dễ nhất / nhanh nhất.


dường như OP quan tâm đến tính toàn vẹn tham chiếu và kích hoạt; trường hợp này, giải pháp tốt nhất của bạn. Tôi đang bỏ câu trả lời của mình =)
Rubens Farias

2
Ý tôi là cắt ngắn nó =)
Rubens Farias

0

Đối với một số yêu cầu, chúng tôi có thể phải bỏ qua các bảng nhất định. Tôi đã viết kịch bản dưới đây để thêm một số điều kiện bổ sung để lọc danh sách các bảng. Kịch bản dưới đây cũng sẽ hiển thị số lần xóa trước và số lần xóa bài.

        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

Câu trả lời này được xây dựng dựa trên câu trả lời của Zach Smith bằng cách đặt lại cột danh tính :

  1. Vô hiệu hóa tất cả các ràng buộc
  2. Lặp lại qua tất cả các bảng ngoại trừ những bảng bạn chọn để loại trừ
  3. Xóa tất cả các hàng khỏi bảng
  4. Đặt lại cột định danh nếu tồn tại
  5. Kích hoạt lại tất cả các ràng buộc

Đây là truy vấn:

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

Vì lý do này hay lý do khác, điều này chủ yếu là thất bại vì nó ném lỗi ràng buộc 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

nếu bạn muốn xóa toàn bộ bảng, bạn phải làm theo hướng dẫn SQL tiếp theo

Delete  FROM TABLE Where PRIMARY_KEY_ is Not NULL;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.