Comment supprimer toutes les lignes de toutes les tables d'une base de données SQL Server?

163

Comment supprimer toutes les lignes de toutes les tables d'une base de données SQL Server?

Michał Powaga
la source
Voir codeguru.com/forum/showthread.php?t=458182 et faites défiler vers le bas ...
Wim ten Brink
4
par drop la base de données sera supprimée je veux juste réinitialiser les données

Réponses:

264

Notez que TRUNCATE ne fonctionnera pas si vous avez défini une intégrité référentielle.

Dans ce cas, cela fonctionnera:

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
Mark Rendle
la source
1
En fait, ce n'est que pour les déclencheurs DDL. Dans quel cas: EXECP sp_MSForEachTable 'DISABLE TRIGGER ALL ON?'
Mark Rendle
10
Non disponible dans SQL Azure :(
Akash Kava
Ok, je suis un peu confus (peut-être que vous pouvez aider) J'ai fait une sauvegarde de ma base de données et c'était environ 10 Mo, puis j'ai exécuté votre code SQL ci-dessus pour vider ma base de données et j'ai fait une nouvelle sauvegarde de ce que je pensais être le base de données vide à envoyer à quelqu'un d'autre dans un e-mail mais ma sauvegarde de base de données «vide» était maintenant de 14 Mo? Qu'ai-je fait de mal?
Ben
1
Compris - si un fichier de sauvegarde existe déjà, il semble que SSMS l'ajoute au lieu de le remplacer (je ne m'en rendais pas compte). J'ai donc supprimé le fichier et maintenant le fichier de sauvegarde de la base de données `` vide '' ne fait que 3,7 Mo
Ben
1
Et si je veux choisir la DB, quelque chose comme USE [MyDataBase]:? L'idée ci-dessus fonctionnerait-elle, si elle était adaptée d'une manière ou d'une autre? ... Parce que je ne veux pas supprimer toutes les bases de données conservées par le serveur SQL.
סטנלי גרונן
20

Dans mon projet récent, ma tâche consistait à nettoyer une base de données entière en utilisant une instruction SQL et chaque table ayant de nombreuses contraintes telles que la clé primaire et la clé étrangère. Il y a plus de 1000 tables dans la base de données, il n'est donc pas possible d'écrire une requête de suppression sur chaque table.

En utilisant une procédure stockée nommée sp_MSForEachTable qui nous permet de traiter facilement du code pour chaque table dans une seule base de données. Cela signifie qu'il est utilisé pour traiter une seule commande T-SQL ou différentes commandes T-SQL sur chaque table de la base de données.

Suivez donc les étapes ci-dessous pour tronquer toutes les tables d'une base de données SQL Server:

Étape 1 - Désactivez toutes les contraintes sur la base de données en utilisant la requête SQL ci-dessous:

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

Étape 2 - Exécutez une opération Supprimer ou tronquer sur chaque table de la base de données en utilisant la commande sql ci-dessous:

EXEC sys.sp_msforeachtable 'DELETE FROM ?'

Étape 3 - Activez toutes les contraintes sur la base de données en utilisant l'instruction SQL ci-dessous:

EXEC sys.sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'
e-techpulse
la source
1
Vous pouvez simplement exécuter l'étape 2 plusieurs fois de manière à ce que la première fois qu'elle supprime les tables sans dépendances, la deuxième fois que la suppression de ces tables a échoué la première fois, la troisième fois que la suppression a échoué la deuxième fois, etc
des idées sur la façon de faire cela sql server azure?
Zapnologica
Cette approche fonctionnera également dans Azure car elle n'utilise que du SQL brut: sqlrelease.com/delete-all-rows-from-all-tables
Jakob Lithner
15

J'ai dû supprimer toutes les lignes et je l'ai fait avec le script suivant:

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

J'espère que cela t'aides!

Gonza Oviedo
la source
Merci pour celui-ci, car j'avais besoin de modifier la sélection pour éliminer certaines tables. Cela a bien fonctionné pour cela.
Don Rolling
13

Voici une solution qui:

  1. Supprime les contraintes (grâce à ce post)
  2. Itère INFORMATION_SCHEMA.TABLESpour une base de données particulière
  3. SELECTS tableaux basés sur certains critères de recherche
  4. Supprime toutes les données de ces tables
  5. Ajoute de nouveau des contraintes
  6. Permet d'ignorer certaines tables telles que sysdiagramset__RefactorLog

J'ai d'abord essayé EXECUTE sp_MSforeachtable 'TRUNCATE TABLE ?', mais cela a supprimé mes diagrammes.

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"
Zach Smith
la source
C'est génial mais cela ne prend pas en compte les schémas non-dbo.
influent le
Je n'ai jamais utilisé de schémas non dbo, donc je n'attraperais pas ça. Mais pourquoi ça ne marche pas? Je ne spécifie le schéma nulle part, alors est-il par défaut uniquement dbo?
Zach Smith
Si vous avez une table, par exemple, appelée test.Table1, où "test" est le schéma, vos suppressions échoueront si vous essayez d'exécuter "DELETE FROM Table1". Il doit être DELETE FROM test.Table1.
influent le
2
@influent - maintenant il prend en compte les schémas non-dbo
Zach Smith
Malheureusement, cela semble échouer s'il y a des contraintes FK. Le ALTER TABLEbit pour désactiver les contraintes échoue.
Douglas Gaskell
8

Dans mon cas, je devais activer QUOTED_IDENTIFIER. Cela a conduit à une légère modification de la réponse de Mark Rendle ci-dessus:

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
William Jockusch
la source
A travaillé pour moi - avant que 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.
j'obtienne
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'
yadavr
la source
1

Vous pouvez supprimer toutes les lignes de toutes les tables en utilisant une approche comme celle suggérée par Rubens, ou vous pouvez simplement supprimer et recréer toutes les tables. Toujours une bonne idée d'avoir les scripts de création de base de données complets de toute façon afin que ce soit la méthode la plus simple / la plus rapide.

AdaTheDev
la source
semble OP est préoccupé par l'intégrité référentielle et les déclencheurs; ce cas, votre meilleure solution. Je laisse tomber ma réponse =)
Rubens Farias
2
Je voulais dire le tronquer =)
Rubens Farias
0

Pour certaines exigences, nous devrons peut-être ignorer certaines tables. J'ai écrit le script ci-dessous pour ajouter des conditions supplémentaires pour filtrer la liste des tables. Le script ci-dessous affichera également le nombre de pré-suppression et de post-suppression.

        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
Balasubramanien S
la source
0

Cette réponse s'appuie sur la réponse de Zach Smith en réinitialisant également la colonne d'identité :

  1. Désactiver toutes les contraintes
  2. Parcourir toutes les tables sauf celles que vous choisissez d'exclure
  3. Supprime toutes les lignes du tableau
  4. Réinitialise la colonne d'identité s'il en existe une
  5. Réactive toutes les contraintes

Voici la requête:

-- 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"
Poisson de mer
la source
Pour une raison ou une autre, cela échoue la plupart du temps car il génère des erreurs de contrainte 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; 
jps
la source
-3

si vous souhaitez supprimer toute la table, vous devez suivre l'instruction SQL suivante

Delete  FROM TABLE Where PRIMARY_KEY_ is Not NULL;
malej
la source