Como excluir todas as linhas de todas as tabelas em um banco de dados do SQL Server?

163

Como excluir todas as linhas de todas as tabelas em um banco de dados do SQL Server?

Michał Powaga
fonte
Veja codeguru.com/forum/showthread.php?t=458182 e role para baixo ...
Wim ten Brink
4
por drop database será eliminado eu só quero repor os dados

Respostas:

264

Observe que TRUNCATE não funcionará se você tiver qualquer integridade referencial definida.

Nesse caso, isso 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
fonte
1
Na verdade, isso é apenas para gatilhos DDL. Nesse caso: EXECP sp_MSForEachTable 'DISABLE TRIGGER ALL ON?'
Mark Rendle
10
Não disponível no SQL Azure :(
Akash Kava 17/04
Ok, estou um pouco confuso (talvez você possa ajudar). Fiz um backup do meu banco de dados e ele tinha cerca de 10 MB. Depois, executei o código SQL acima para esvaziar o banco de dados e fiz um novo backup do que eu pensava ser o banco de dados vazio para enviar para outra pessoa em um email, mas meu backup do banco de dados 'vazio' agora tinha 14 MB? O que eu fiz errado?
Ben
1
Entendi - se um arquivo de backup já existe, parece que o SSMS anexa a ele em vez de substituí-lo (eu não percebi isso). Então eu apaguei o arquivo e agora o arquivo de backup do banco de dados 'vazio' tem apenas 3,7 MB
Ben
1
E se eu quiser escolher o banco de dados, algo como USE [MyDataBase]:? A idéia acima funcionaria, se adaptada de alguma forma? ... Porque eu não quero excluir todos os bancos de dados mantidos pelo servidor SQL.
סטנלי גרונן
20

Em meu projeto recente, minha tarefa era limpar um banco de dados inteiro usando a instrução sql e cada tabela com muitas restrições, como Chave Primária e Chave Estrangeira. Existem mais de 1000 tabelas no banco de dados, portanto, não é possível gravar uma consulta de exclusão em cada tabela.

Usando um procedimento armazenado chamado sp_MSForEachTable, que permite processar facilmente algum código em todas as tabelas em um único banco de dados. Isso significa que é usado para processar um único comando T-SQL ou um comando T-SQL diferente em todas as tabelas do banco de dados.

Portanto, siga as etapas abaixo para truncar todas as tabelas em um banco de dados do SQL Server:

Etapa 1 - Desative todas as restrições no banco de dados usando a consulta sql abaixo:

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

Etapa 2- Execute uma operação Excluir ou truncar em cada tabela do banco de dados usando o comando sql abaixo:

EXEC sys.sp_msforeachtable 'DELETE FROM ?'

Etapa 3- Habilite todas as restrições no banco de dados usando a instrução sql abaixo:

EXEC sys.sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'
e-techpulse
fonte
1
Você pode simplesmente executar o passo 2 vezes mutliple para que primeira vez que exclui as tabelas com os não dependências, 2ª vez para apagar essas tabelas falhou na primeira vez, 3ª vez para faild de exclusão no 2º tempo, etc
alguma idéia de como fazer isso sql server azure?
Zapnologica
Esta abordagem irá funcionar também no Azure, uma vez que usa apenas SQL simples: sqlrelease.com/delete-all-rows-from-all-tables
Jakob Lithner
15

Eu tive que excluir todas as linhas e fiz isso com o próximo 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 isto ajude!

Gonza Oviedo
fonte
Obrigado por este, porque eu precisava ajustar o select para eliminar algumas tabelas. Isso funcionou bem para isso.
Don Rolling
13

Aqui está uma solução que:

  1. Eliminar restrições (graças a este post)
  2. Repete INFORMATION_SCHEMA.TABLESpara um banco de dados específico
  3. SELECTS tabelas com base em alguns critérios de pesquisa
  4. Exclui todos os dados dessas tabelas
  5. Re-adiciona restrições
  6. Permite ignorar determinadas tabelas como sysdiagramse__RefactorLog

Inicialmente EXECUTE sp_MSforeachtable 'TRUNCATE TABLE ?', tentei , mas isso excluiu meus 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
fonte
Isso é ótimo, mas não leva em consideração os esquemas não-dbo.
Influente
Eu nunca usei esquemas que não sejam do dbo, então não entendi isso. Mas por que não funciona? Eu não estou especificando o esquema em nenhum lugar, então ele usa como padrão apenas o dbo?
Zach Smith
Se você tiver uma tabela, por exemplo, chamada test.Table1, em que "test" é o esquema, suas exclusões falharão se tentar executar "DELETE FROM Table1". Ele precisa ser DELETE FROM test.Table1.
influente
2
@influent - agora leva esquemas DBO não em conta
Zach Smith
Infelizmente, isso parece falhar se houver restrições de FK. O ALTER TABLEbit para desativar as restrições falha.
Douglas Gaskell
8

No meu caso, eu precisava ativar QUOTED_IDENTIFIER. Isso levou a uma ligeira modificação na resposta de Mark Rendle acima:

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
fonte
Trabalhou para mim - antes de receber este erro: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
fonte
1

Você pode excluir todas as linhas de todas as tabelas usando uma abordagem como sugerida por Rubens, ou simplesmente soltar e recriar todas as tabelas. Sempre é uma boa idéia ter os scripts de criação de banco de dados completos de qualquer maneira, para que esse seja o método mais fácil / rápido.

AdaTheDev
fonte
parece que o OP está preocupado com integridade referencial e gatilhos; Nesse caso, você tem a melhor solução. Eu estou largando minha resposta =)
Rubens Farias
2
Eu quis dizer truncando-lo =)
Rubens Farias
0

Para alguns requisitos, podemos ter que pular determinadas tabelas. Eu escrevi o script abaixo para adicionar algumas condições extras para filtrar a lista de tabelas. O script abaixo também exibirá a contagem de pré-exclusão e a contagem de pós-exclusão.

        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
fonte
0

Essa resposta se baseia na resposta de Zach Smith, redefinindo a coluna de identidade também:

  1. Desativando todas as restrições
  2. Iterando todas as tabelas, exceto aquelas que você optar por excluir
  3. Exclui todas as linhas da tabela
  4. Redefine a coluna de identidade, se houver uma
  5. Reativa todas as restrições

Aqui está a 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"
Seafish
fonte
Por um motivo ou outro, isso geralmente falha, pois gera erros de restrição do 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
fonte
-3

se você deseja excluir a tabela inteira, siga as próximas instruções SQL

Delete  FROM TABLE Where PRIMARY_KEY_ is Not NULL;
malej
fonte