¿Cómo eliminar todas las filas de todas las tablas en una base de datos de SQL Server?

Respuestas:

264

Tenga en cuenta que TRUNCATE no funcionará si tiene un conjunto de integridad referencial.

En ese caso, esto funcionará:

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
fuente
1
En realidad, eso es solo para los desencadenantes DDL. En cuyo caso: EXECP sp_MSForEachTable 'DISABLE TRIGGER ALL ON?'
Mark Rendle
10
No disponible en SQL Azure :(
Akash Kava
Ok, estoy un poco confundido (tal vez usted pueda ayudar) Hice una copia de seguridad de mi base de datos y tenía aproximadamente 10 MB, luego ejecuté su código SQL anterior para vaciar mi base de datos e hice una nueva copia de seguridad de lo que pensé que era base de datos vacía para enviar a otra persona en un correo electrónico, pero mi copia de seguridad de la base de datos 'vacía' ahora tenía 14 MB ¿Qué hice mal?
Ben
1
Lo tengo: si ya existe un archivo de copia de seguridad, parece que SSMS se agrega a él en lugar de reemplazarlo (no me di cuenta de esto). Así que eliminé el archivo y ahora el archivo de copia de seguridad de la base de datos 'vacío' es de solo 3.7 MB
Ben
1
¿Qué pasa si quiero elegir el DB, algo como USE [MyDataBase]:? ¿Funcionaría la idea anterior, si se adapta de alguna manera? ... Porque no quiero eliminar todos los DB guardados por el servidor SQL.
גלי גרונן
20

En mi proyecto reciente, mi tarea consistía en limpiar una base de datos completa utilizando la instrucción sql y cada tabla tenía muchas restricciones, como la clave primaria y la clave externa. Hay más de 1000 tablas en la base de datos, por lo que no es posible escribir una consulta de eliminación en todas y cada una de las tablas.

Mediante el uso de un procedimiento almacenado llamado sp_MSForEachTable que nos permite procesar fácilmente algún código en todas y cada una de las tablas de una sola base de datos. Significa que se usa para procesar un solo comando T-SQL o diferentes comandos T-SQL en cada tabla de la base de datos.

Siga los pasos a continuación para truncar todas las tablas en una base de datos de SQL Server:

Paso 1- Desactive todas las restricciones en la base de datos utilizando la consulta sql a continuación:

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

Paso 2- Ejecute una operación Eliminar o truncar en cada tabla de la base de datos utilizando el siguiente comando sql:

EXEC sys.sp_msforeachtable 'DELETE FROM ?'

Paso 3- Habilite todas las restricciones en la base de datos utilizando la siguiente instrucción sql:

EXEC sys.sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'
e-techpulse
fuente
1
Simplemente puede ejecutar el paso 2 veces mutliple de manera que por primera vez se elimina tablas con los no dependencias, segundo tiempo para eliminar esas tablas fallaron en la primera vez, tercera vez en faild de eliminación en segundo tiempo, etc
alguna idea sobre cómo hacer esto sql server azure?
Zapnologica
Este enfoque también funcionará en Azure, ya que solo utiliza SQL simple: sqlrelease.com/delete-all-rows-from-all-tables
Jakob Lithner
15

Tuve que eliminar todas las filas y lo hice con el siguiente 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

¡Espero que esto ayude!

Gonza Oviedo
fuente
Gracias por esto, porque necesitaba ajustar la selección para eliminar algunas tablas. Esto funcionó bien para eso.
Don Rolling
13

Aquí hay una solución que:

  1. Elimina restricciones (gracias a esta publicación)
  2. Itera a través INFORMATION_SCHEMA.TABLESde una base de datos particular
  3. SELECTS tablas basadas en algunos criterios de búsqueda
  4. Elimina todos los datos de esas tablas.
  5. Vuelve a agregar restricciones
  6. Permite ignorar ciertas tablas como sysdiagramsy__RefactorLog

Al principio lo intenté EXECUTE sp_MSforeachtable 'TRUNCATE TABLE ?', pero eso eliminó mis diagramas.

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
fuente
Esto es genial, pero no tiene en cuenta los esquemas que no son dbo.
influyente el
Nunca he usado esquemas que no sean dbo, así que no lo entendería. ¿Pero por qué no funciona? No estoy especificando el esquema en ninguna parte, ¿solo se usa de forma predeterminada dbo?
Zach Smith
Si tiene una tabla, por ejemplo, llamada test.Table1, donde "test" es el esquema, sus eliminaciones fallarán si intenta ejecutar "DELETE FROM Table1". Tiene que ser DELETE FROM test.Table1.
influyente
2
@influent - ahora tiene en cuenta los esquemas no dbo
Zach Smith
Desafortunadamente, esto parece fallar si hay restricciones FK. El ALTER TABLEbit para deshabilitar las restricciones falla.
Douglas Gaskell el
8

En mi caso, necesitaba configurar QUOTED_IDENTIFIER. Esto llevó a una ligera modificación de la respuesta de Mark Rendle anterior:

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
fuente
Trabajó para mí, antes de recibir este error: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'
yadavr
fuente
1

Puede eliminar todas las filas de todas las tablas utilizando un enfoque como el sugerido por Rubens, o simplemente puede soltar y volver a crear todas las tablas. Siempre es una buena idea tener los scripts de creación de db completos de todos modos, por lo que puede ser el método más fácil / rápido.

AdaTheDev
fuente
Parece que OP está preocupado por la integridad referencial y los desencadenantes; En este caso, tienes la mejor solución. Estoy dejando caer mi respuesta =)
Rubens Farias
2
Quise decir truncarlo =)
Rubens Farias
0

Para algunos requisitos, es posible que tengamos que omitir ciertas tablas. Escribí el siguiente script para agregar algunas condiciones adicionales para filtrar la lista de tablas. El siguiente script también mostrará el conteo previo a la eliminación y el conteo posterior a la eliminación.

        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
Balasubramanian S
fuente
0

Esta respuesta se basa en la respuesta de Zach Smith al restablecer también la columna de identidad :

  1. Deshabilitar todas las restricciones
  2. Iterando a través de todas las tablas excepto aquellas que elige excluir
  3. Elimina todas las filas de la tabla.
  4. Restablece la columna de identidad si existe
  5. Rehabilita todas las restricciones

Aquí está la consulta:

-- 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"
Pescado de mar
fuente
Por una razón u otra, esto falla principalmente, ya que arroja errores de restricción FK.
Douglas Gaskell el
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
fuente
-3

si desea eliminar toda la tabla, debe seguir las siguientes instrucciones SQL

Delete  FROM TABLE Where PRIMARY_KEY_ is Not NULL;
malej
fuente