Come eliminare tutte le righe da tutte le tabelle in un database di SQL Server?


Risposte:


264

Nota che TRUNCATE non funzionerà se hai impostato l'integrità referenziale.

In tal caso, questo funzionerà:

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
In realtà, questo è solo per i trigger DDL. In tal caso: EXECP sp_MSForEachTable 'DISABLE TRIGGER ALL ON?'
Mark Rendle,

10
Non disponibile in SQL Azure :(
Akash Kava,

Ok sono un po 'confuso (forse puoi aiutare) Ho fatto un backup del mio database ed era di circa 10 MB, quindi ho eseguito il tuo codice SQL sopra per svuotare il mio database e ho fatto un nuovo backup di quello che pensavo fosse il database vuoto da inviare a qualcun altro in una e-mail ma il mio backup del database "vuoto" ora era di 14 MB? Cos'ho fatto di sbagliato?
Ben

1
Capito: se esiste già un file di backup, sembra che SSMS lo accoda invece di sostituirlo (non me ne sono reso conto). Quindi ho eliminato il file e ora il file di backup del database "vuoto" è solo 3,7 MB
Ben

1
E se volessi scegliere il DB, qualcosa del tipo USE [MyDataBase]:? L'idea di cui sopra funzionerebbe, se adattata in qualche modo? ... Perché non voglio cancellare tutti i DB conservati dal server SQL.
גלי גרונן

20

Nel mio recente progetto il mio compito era quello di pulire un intero database usando l'istruzione sql e ogni tabella aveva molti vincoli come chiave primaria e chiave esterna. Ci sono più di 1000 tabelle nel database, quindi non è possibile scrivere una query di eliminazione su ogni e sempre tabella.

Utilizzando una procedura memorizzata denominata sp_MSForEachTable che ci consente di elaborare facilmente del codice su ogni singola tabella in un singolo database. Significa che viene utilizzato per elaborare un singolo comando T-SQL o diversi comandi T-SQL su ogni tabella del database.

Quindi seguire i passaggi seguenti per troncare tutte le tabelle in un database di SQL Server:

Passaggio 1- Disabilitare tutti i vincoli sul database utilizzando la query sql di seguito:

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

Passaggio 2- Eseguire un'operazione di eliminazione o troncamento su ciascuna tabella del database utilizzando il comando sql seguente:

EXEC sys.sp_msforeachtable 'DELETE FROM ?'

Passaggio 3- Abilitare tutti i vincoli sul database utilizzando la seguente istruzione sql:

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

1
Puoi semplicemente eseguire il passaggio 2 volte più volte in modo che la prima volta elimini le tabelle senza dipendenze, la seconda volta per eliminare quelle tabelle non riuscite per la prima volta, la terza volta per eliminare il non riuscito in seconda volta, ecc.

qualche idea su come farlo sql server azure?
Zapnologica,

Questo approccio funzionerà anche in Azure poiché usa solo SQL semplice: sqlrelease.com/delete-all-rows-from-all-tables
Jakob Lithner

15

Ho dovuto eliminare tutte le righe e l'ho fatto con il prossimo script:

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

Spero che questo ti aiuti!


Grazie per questo, perché avevo bisogno di modificare la selezione per eliminare alcune tabelle. Questo ha funzionato bene per quello.
Don Rolling,

13

Ecco una soluzione che:

  1. Elimina vincoli (grazie a questo post)
  2. Scorre INFORMATION_SCHEMA.TABLESper un determinato database
  3. SELECTS tabelle basate su alcuni criteri di ricerca
  4. Elimina tutti i dati da quelle tabelle
  5. Aggiunge nuovamente i vincoli
  6. Consente di ignorare alcune tabelle come sysdiagramse__RefactorLog

Inizialmente ho provato EXECUTE sp_MSforeachtable 'TRUNCATE TABLE ?', ma questo ha cancellato i miei diagrammi.

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"

Questo è fantastico ma non tiene conto di schemi non dbo.
influente

Non ho mai usato schemi non dbo, quindi non lo prenderei. Ma perché non funziona? Non sto specificando lo schema da nessuna parte, quindi è predefinito solo il dbo?
Zach Smith,

Se hai una tabella, ad esempio, chiamata test.Table1, dove "test" è lo schema, le tue eliminazioni falliranno se provi a eseguire "DELETE FROM Table1". Deve essere DELETE FROM test.Table1.
influente il

2
@influent - ora prende in considerazione schemi non dbo
Zach Smith

Sfortunatamente questo sembra fallire se ci sono vincoli FK. Il ALTER TABLEbit per disabilitare i vincoli non riesce.
Douglas Gaskell,

8

Nel mio caso, dovevo attivare QUOTED_IDENTIFIER. Ciò ha portato a una leggera modifica della risposta di Mark Rendle sopra:

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

Ha funzionato per me - prima che ottenessi questo errore: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 il

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

Puoi eliminare tutte le righe da tutte le tabelle usando un approccio come suggerito da Rubens, oppure puoi semplicemente eliminare e ricreare tutte le tabelle. Sempre una buona idea avere comunque gli script di creazione di db completi in modo che possa essere il metodo più semplice / veloce.


sembra che OP sia preoccupato per l'integrità referenziale e per i trigger; in questo caso, hai la soluzione migliore. Sto lasciando cadere la mia risposta =)
Rubens Farias il

2
Intendevo troncarlo =)
Rubens Farias il

0

Per alcuni requisiti potremmo dover saltare alcune tabelle. Ho scritto lo script seguente per aggiungere alcune condizioni extra per filtrare l'elenco delle tabelle. Lo script seguente mostrerà anche il conteggio preeliminazione e il conteggio post eliminazione.

        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

Questa risposta si basa sulla risposta di Zach Smith ripristinando anche la colonna identità :

  1. Disabilitare tutti i vincoli
  2. Scorrendo tutte le tabelle tranne quelle che si sceglie di escludere
  3. Elimina tutte le righe dalla tabella
  4. Reimposta la colonna identità se esiste
  5. Riattiva tutti i vincoli

Ecco la query:

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

Per un motivo o per l'altro, ciò fallisce soprattutto perché genera errori di vincolo 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

se si desidera eliminare l'intera tabella, è necessario seguire le istruzioni SQL successive

Delete  FROM TABLE Where PRIMARY_KEY_ is Not NULL;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.