วิธีลบแถวทั้งหมดออกจากตารางทั้งหมดในฐานข้อมูล SQL Server


163

วิธีลบแถวทั้งหมดออกจากตารางทั้งหมดในฐานข้อมูล SQL Server


ดูcodeguru.com/forum/showthread.php?t=458182และเลื่อนลง ...
Wim ten Brink

4
โดยฐานข้อมูลลดลงจะถูกลบออกฉันเพียงแค่ต้องการรีเซ็ตข้อมูล

คำตอบ:


264

โปรดทราบว่า TRUNCATE จะไม่ทำงานหากคุณมี Referential Integrity ใด ๆ

ในกรณีนี้สิ่งนี้จะทำงาน:

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 'ปิดใช้งานทริกเกอร์ ALL ON ON'
Mark Rendle

10
ไม่พร้อมใช้งานใน SQL Azure :(
Akash Kava

ตกลงฉันสับสนเล็กน้อย (บางทีคุณสามารถช่วยได้) ฉันทำสำเนาสำรองของฐานข้อมูลของฉันและมันเป็นประมาณ 10 MB จากนั้นฉันรันรหัส SQL ของคุณด้านบนเพื่อล้างฐานข้อมูลของฉันและฉันได้สำรองข้อมูลใหม่ของสิ่งที่ฉันคิดว่าเป็น ฐานข้อมูลว่างเปล่าที่จะส่งให้คนอื่นทางอีเมล แต่การสำรองฐานข้อมูล 'ว่าง' ของฉันตอนนี้คือ 14 MB? ฉันทำอะไรผิด?
เบ็น

1
รับมา - หากไฟล์สำรองมีอยู่แล้วดูเหมือนว่า SSMS จะต่อท้ายแทนที่จะแทนที่ (ฉันไม่ทราบเลย) ดังนั้นฉันจึงลบไฟล์และตอนนี้ไฟล์สำรองฐานข้อมูล 'ว่างเปล่า' เพียง 3.7 MB
Ben

1
ถ้าฉันต้องการเลือก DB จะเป็นUSE [MyDataBase]อย่างไร: ความคิดข้างต้นจะใช้งานได้หรือไม่หากได้รับการปรับแต่งหรือไม่ ... เพราะฉันไม่ต้องการลบฐานข้อมูลทั้งหมดที่เก็บไว้ในเซิร์ฟเวอร์ SQL
סטנליגרונן

20

ในโครงการล่าสุดของฉันงานของฉันคือการล้างฐานข้อมูลทั้งหมดโดยใช้คำสั่ง sql และแต่ละตารางมีข้อ จำกัด มากมายเช่นคีย์หลักและคีย์ต่างประเทศ มีฐานข้อมูลมากกว่า 1,000 ตารางในฐานข้อมูลดังนั้นจึงไม่สามารถเขียนแบบสอบถามลบในแต่ละตารางได้

โดยใช้กระบวนงานที่เก็บไว้ชื่อ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 ครั้งเพื่อที่ครั้งแรกมันจะลบตารางที่ไม่มีการอ้างอิงครั้งที่ 2 เพื่อลบตารางเหล่านั้นล้มเหลวในครั้งแรกครั้งที่ 3 เพื่อลบ faild ในครั้งที่ 2 ฯลฯ

ความคิดเห็นใด ๆ เกี่ยวกับวิธีการทำเช่นนี้sql server azure?
Zapnologica

วิธีการนี้จะทำงานยังอยู่ใน Azure ที่จะใช้เพียง 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

หวังว่านี่จะช่วยได้!


ขอบคุณสำหรับอันนี้เพราะฉันจำเป็นต้องปรับแต่งตัวเลือกเพื่อกำจัดตารางบางตัว สิ่งนี้ใช้ได้ดีสำหรับสิ่งนั้น
Don Rolling

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"

นี่ยอดเยี่ยม แต่ไม่คำนึงถึง schema ที่ไม่ใช่ dbo
มีอิทธิพล

ฉันไม่เคยใช้ schema ที่ไม่ใช่ dbo ดังนั้นฉันจะไม่จับมัน แต่ทำไมมันไม่ทำงาน ฉันไม่ได้ระบุสคีมาใด ๆ ดังนั้นจึงเริ่มต้นที่ dbo เท่านั้นหรือไม่
Zach Smith

หากคุณมีตารางตัวอย่างเช่นชื่อ test.Table1 โดยที่ "test" เป็นสกีมาการลบของคุณจะล้มเหลวหากพยายามเรียกใช้ "DELETE FROM Table1" จำเป็นต้องลบจาก test.Table1
มีอิทธิพล

2
@influent - ตอนนี้ใช้ schema ที่ไม่ใช่ 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

คุณสามารถลบแถวทั้งหมดออกจากตารางทั้งหมดโดยใช้วิธีการเช่นรูเบนส์ที่แนะนำหรือคุณสามารถวางและสร้างตารางทั้งหมดใหม่ได้ ความคิดที่ดีเสมอที่จะมีสคริปต์การสร้างฐานข้อมูลแบบเต็มอยู่แล้วเพื่อให้อาจเป็นวิธีที่ง่ายที่สุด / เร็วที่สุด


ดูเหมือนว่า OP จะเกี่ยวข้องกับ Referential Integrity และทริกเกอร์ กรณีนี้คุณมีทางออกที่ดีที่สุด ฉันทิ้งคำตอบของฉัน =)
Rubens Farias

2
ฉันหมายถึงการตัดทอนมัน =)
Rubens Farias

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

คำตอบนี้สร้างจากคำตอบของ 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.