Wie lösche ich alle Zeilen aus allen Tabellen in einer SQL Server-Datenbank?


Antworten:


263

Beachten Sie, dass TRUNCATE nicht funktioniert, wenn Sie eine referenzielle Integrität festgelegt haben.

In diesem Fall funktioniert dies:

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
Eigentlich ist das nur für DDL-Trigger. In welchem ​​Fall: EXECP sp_MSForEachTable 'TRIGGER ALL ON EIN deaktivieren?'
Mark Rendle

10
Nicht verfügbar in SQL Azure :(
Akash Kava

Ok, ich bin ein bisschen verwirrt (vielleicht können Sie helfen). Ich habe eine Sicherungskopie meiner Datenbank erstellt und es waren ungefähr 10 MB. Dann habe ich Ihren SQL-Code oben ausgeführt, um meine Datenbank zu leeren, und ich habe eine neue Sicherungskopie dessen erstellt, was ich für die hielt Leere Datenbank zum Senden an eine andere Person in einer E-Mail, aber meine 'leere' Datenbanksicherung war jetzt 14 MB groß? Was habe ich falsch gemacht?
Ben

1
Verstanden - wenn bereits eine Sicherungsdatei vorhanden ist, sieht es so aus, als würde SSMS daran angehängt, anstatt sie zu ersetzen (das habe ich nicht bemerkt). Also habe ich die Datei gelöscht und jetzt ist die 'leere' Datenbanksicherungsdatei nur noch 3,7 MB
Ben

1
Was ist, wenn ich die Datenbank auswählen möchte USE [MyDataBase]? Würde die obige Idee funktionieren, wenn sie irgendwie angepasst würde? ... Weil ich nicht alle vom SQL Server gespeicherten DBs löschen möchte.
גרונן גרונן

20

In meinem letzten Projekt bestand meine Aufgabe darin, eine gesamte Datenbank mithilfe der SQL-Anweisung zu bereinigen, wobei jede Tabelle viele Einschränkungen wie Primärschlüssel und Fremdschlüssel aufweist. Es gibt mehr als 1000 Tabellen in der Datenbank, so dass es nicht möglich ist, eine Löschabfrage für jede einzelne Tabelle zu schreiben.

Durch die Verwendung einer gespeicherten Prozedur mit dem Namen sp_MSForEachTable können wir auf einfache Weise Code für jede einzelne Tabelle in einer einzelnen Datenbank verarbeiten. Dies bedeutet, dass ein einzelner T-SQL-Befehl oder ein anderer T-SQL-Befehl für jede Tabelle in der Datenbank verarbeitet wird.

Führen Sie die folgenden Schritte aus, um alle Tabellen in einer SQL Server-Datenbank abzuschneiden:

Schritt 1 - Deaktivieren Sie alle Einschränkungen für die Datenbank mithilfe der folgenden SQL-Abfrage:

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

Schritt 2: Führen Sie eine Lösch- oder Kürzungsoperation für jede Tabelle der Datenbank aus, indem Sie den folgenden SQL-Befehl verwenden:

EXEC sys.sp_msforeachtable 'DELETE FROM ?'

Schritt 3: Aktivieren Sie alle Einschränkungen für die Datenbank mithilfe der folgenden SQL-Anweisung:

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

1
Sie können Schritt 2 einfach mehrfach ausführen, so dass beim ersten Löschen von Tabellen ohne Abhängigkeiten das zweite Mal das Löschen dieser Tabellen beim ersten Mal fehlgeschlagen ist, das dritte Mal das Löschen von Faild beim zweiten Mal usw.

Irgendwelche Ideen, wie man das macht sql server azure?
Zapnologica

Dieser Ansatz funktioniert auch in Azure, da nur einfaches SQL verwendet wird: sqlrelease.com/delete-all-rows-from-all-tables
Jakob Lithner

15

Ich musste alle Zeilen löschen und tat es mit dem nächsten Skript:

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

Hoffe das hilft!


Vielen Dank für diesen einen, da ich die Auswahl anpassen musste, um einige Tabellen zu entfernen. Das hat gut funktioniert.
Don Rolling

13

Hier ist eine Lösung, die:

  1. Löscht Einschränkungen (dank dieses Beitrags)
  2. Durchläuft INFORMATION_SCHEMA.TABLESeine bestimmte Datenbank
  3. SELECTS Tabellen basierend auf einigen Suchkriterien
  4. Löscht alle Daten aus diesen Tabellen
  5. Fügt Einschränkungen hinzu
  6. Ermöglicht das Ignorieren bestimmter Tabellen wie sysdiagramsund__RefactorLog

Ich habe es zunächst versucht EXECUTE sp_MSforeachtable 'TRUNCATE TABLE ?', aber dadurch wurden meine Diagramme gelöscht.

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"

Dies ist großartig, berücksichtigt jedoch keine Nicht-Dbo-Schemata.
Einfluss

Ich habe noch nie Nicht-Dbo-Schemata verwendet, daher würde ich das nicht verstehen. Aber warum funktioniert es nicht? Ich gebe nirgendwo ein Schema an. Wird standardmäßig nur dbo verwendet?
Zach Smith

Wenn Sie beispielsweise eine Tabelle mit dem Namen test.Table1 haben, in der "test" das Schema ist, schlagen Ihre Löschvorgänge fehl, wenn Sie versuchen, "DELETE FROM Table1" auszuführen. Es muss DELETE FROM test.Table1 sein.
Einfluss

2
@influent - jetzt berücksichtigt es Nicht-Dbo-Schemata
Zach Smith

Leider scheint dies zu scheitern, wenn es FK-Einschränkungen gibt. Das ALTER TABLEBit zum Deaktivieren von Einschränkungen schlägt fehl.
Douglas Gaskell

8

In meinem Fall musste ich QUOTED_IDENTIFIER aktivieren. Dies führte zu einer geringfügigen Änderung der obigen Antwort von 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

Arbeitete für mich - bevor ich diesen Fehler bekam: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

Sie können alle Zeilen aus allen Tabellen mit einem von Rubens vorgeschlagenen Ansatz löschen oder einfach alle Tabellen löschen und neu erstellen. Es ist immer eine gute Idee, die vollständigen Skripte zur Datenbankerstellung zu haben, damit dies die einfachste / schnellste Methode ist.


Anscheinend ist OP besorgt über referenzielle Integrität und Auslöser. In diesem Fall haben Sie die beste Lösung. Ich lasse meine Antwort fallen =)
Rubens Farias

2
Ich wollte es abschneiden =)
Rubens Farias

0

Für einige Anforderungen müssen wir möglicherweise bestimmte Tabellen überspringen. Ich habe das folgende Skript geschrieben, um einige zusätzliche Bedingungen zum Filtern der Tabellenliste hinzuzufügen. Das folgende Skript zeigt auch die Anzahl vor und nach dem Löschen an.

        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

Diese Antwort baut auf Zach Smiths Antwort auf, indem auch die Identitätsspalte zurückgesetzt wird :

  1. Alle Einschränkungen deaktivieren
  2. Durchlaufen aller Tabellen mit Ausnahme derjenigen, die Sie ausschließen möchten
  3. Löscht alle Zeilen aus der Tabelle
  4. Setzt die Identitätsspalte zurück, falls vorhanden
  5. Aktiviert alle Einschränkungen wieder

Hier ist die Abfrage:

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

Aus dem einen oder anderen Grund schlägt dies meistens fehl, da es FK-Einschränkungsfehler auslöst.
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

Wenn Sie die gesamte Tabelle löschen möchten, müssen Sie die nächste SQL-Anweisung befolgen

Delete  FROM TABLE Where PRIMARY_KEY_ is Not NULL;
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.