Jak usunąć wszystkie wiersze ze wszystkich tabel w bazie danych SQL Server?

163

Jak usunąć wszystkie wiersze ze wszystkich tabel w bazie danych SQL Server?

Michał Powaga
źródło
Zobacz codeguru.com/forum/showthread.php?t=458182 i przewiń w dół ...
Wim ten Brink
4
przez drop baza danych zostanie usunięta Chcę tylko zresetować dane

Odpowiedzi:

264

Zauważ, że TRUNCATE nie zadziała, jeśli masz zestaw integralności referencyjnej.

W takim przypadku zadziała:

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
źródło
1
Właściwie to tylko dla wyzwalaczy DDL. W takim przypadku: EXECP sp_MSForEachTable „DISABLE TRIGGER ALL ON?”
Mark Rendle
10
Niedostępne w SQL Azure :(
Akash Kava
Ok, jestem trochę zdezorientowany (może możesz pomóc) Zrobiłem kopię zapasową mojej bazy danych i było to około 10 MB, następnie uruchomiłem powyższy kod SQL, aby opróżnić moją bazę danych i wykonałem nową kopię zapasową tego, co uważałem za pusta baza danych do wysłania do kogoś innego w e-mailu, ale moja „pusta” kopia zapasowa bazy danych ma teraz 14 MB? Co zrobiłem źle?
Ben
1
Rozumiem - jeśli plik kopii zapasowej już istnieje, wygląda na to, że SSMS dołącza do niego zamiast go zastępować (nie zdawałem sobie z tego sprawy). Usunąłem więc plik i teraz „pusty” plik kopii zapasowej bazy danych ma tylko 3,7 MB
Ben
1
A jeśli chcę wybrać DB, coś takiego USE [MyDataBase]:? Czy powyższy pomysł zadziałałby, gdyby był w jakiś sposób dostosowany? ... Ponieważ nie chcę usuwać wszystkich baz danych przechowywanych przez serwer SQL.
סטנלי גרונן
20

W moim ostatnim projekcie moim zadaniem było wyczyszczenie całej bazy danych za pomocą instrukcji sql, a każda tabela miała wiele ograniczeń, takich jak klucz podstawowy i klucz obcy. W bazie danych znajduje się ponad 1000 tabel, więc nie jest możliwe zapisanie zapytania usuwającego dla każdej tabeli.

Korzystając z procedury składowanej o nazwie sp_MSForEachTable która pozwala nam łatwo przetwarzać kod dla każdej tabeli w jednej bazie danych. Oznacza to, że jest używany do przetwarzania pojedynczego polecenia T-SQL lub różnych poleceń T-SQL dla każdej tabeli w bazie danych.

Dlatego wykonaj poniższe kroki, aby obciąć wszystkie tabele w bazie danych programu SQL Server:

Krok 1 - Wyłącz wszystkie ograniczenia w bazie danych, używając poniższego zapytania sql:

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

Krok 2 - Wykonaj operację usuwania lub obcięcia na każdej tabeli bazy danych za pomocą poniższej komendy sql:

EXEC sys.sp_msforeachtable 'DELETE FROM ?'

Krok 3 - Włącz wszystkie ograniczenia w bazie danych, używając poniższej instrukcji sql:

EXEC sys.sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'
e-techpulse
źródło
1
Możesz po prostu wykonać krok 2 wiele razy, aby po raz pierwszy usunąć tabele bez zależności, drugi raz, aby usunąć te tabele nie powiódł się za pierwszym razem, trzeci raz, aby usunąć błąd za drugim razem, itd.
jakieś pomysły, jak to zrobić sql server azure?
Zapnologica,
To podejście będzie działać również na platformie
Jakob Lithner
15

Musiałem usunąć wszystkie wiersze i zrobiłem to z następnym skryptem:

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

Mam nadzieję że to pomoże!

Gonza Oviedo
źródło
Dzięki za to, ponieważ musiałem dostosować wybór, aby wyeliminować niektóre tabele. To działało dobrze.
Don Rolling
13

Oto rozwiązanie, które:

  1. Zrzuca ograniczenia (dzięki temu wpisowi)
  2. Iteruje przez INFORMATION_SCHEMA.TABLESokreśloną bazę danych
  3. SELECTS tabele w oparciu o pewne kryteria wyszukiwania
  4. Usuwa wszystkie dane z tych tabel
  5. Ponownie dodaje wiązania
  6. Pozwala na ignorowanie niektórych tabel, takich jak sysdiagramsi__RefactorLog

Początkowo próbowałem EXECUTE sp_MSforeachtable 'TRUNCATE TABLE ?', ale to spowodowało usunięcie moich diagramów.

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
źródło
To jest świetne, ale nie bierze pod uwagę schematów innych niż dbo.
wpływowy
Nigdy nie używałem schematów innych niż dbo, więc nie łapałbym tego. Ale dlaczego to nie działa? Nigdzie nie określam schematu, więc czy domyślnie jest to tylko dbo?
Zach Smith,
Jeśli masz na przykład tabelę o nazwie test.Table1, gdzie „test” jest schematem, usuwanie nie powiedzie się, jeśli spróbujesz wykonać polecenie „DELETE FROM Table1”. Należy go USUNĄĆ Z testu. Tabela 1.
wpływowy
2
@influent - teraz bierze pod uwagę schematy inne niż dbo
Zach Smith
Niestety wydaje się to nie powieść, jeśli istnieją ograniczenia FK. ALTER TABLENieco aby wyłączyć ograniczeń zawiedzie.
Douglas Gaskell
8

W moim przypadku musiałem włączyć QUOTED_IDENTIFIER. Doprowadziło to do niewielkiej modyfikacji powyższej odpowiedzi Marka Rendle'a:

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
źródło
U mnie 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.
zadziałało
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
źródło
1

Możesz usunąć wszystkie wiersze ze wszystkich tabel, stosując podejście takie, jak sugerował Rubens, lub po prostu upuścić i ponownie utworzyć wszystkie tabele. Zawsze dobrze jest mieć pełne skrypty do tworzenia bazy danych, więc może to być najłatwiejsza / najszybsza metoda.

AdaTheDev
źródło
wydaje się, że OP jest zaniepokojony referencyjną integralnością i wyzwalaczami; w tym przypadku masz najlepsze rozwiązanie. Upuszczam odpowiedź =)
Rubens Farias
2
Miałem na myśli skrócenie tego =)
Rubens Farias
0

W przypadku niektórych wymagań może być konieczne pominięcie niektórych tabel. Napisałem poniższy skrypt, aby dodać dodatkowe warunki do filtrowania listy tabel. Poniższy skrypt wyświetli również liczbę przed usunięciem i liczbę po usunięciu.

        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
źródło
0

Ta odpowiedź opiera się na odpowiedzi Zacha Smitha, resetując również kolumnę tożsamości :

  1. Wyłączanie wszystkich ograniczeń
  2. Iterowanie po wszystkich tabelach oprócz tych, które zdecydujesz się wykluczyć
  3. Usuwa wszystkie wiersze z tabeli
  4. Resetuje kolumnę tożsamości, jeśli taka istnieje
  5. Ponownie włącza wszystkie ograniczenia

Oto zapytanie:

-- 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"
Ryba morska
źródło
Z jakiegoś powodu to najczęściej kończy się niepowodzeniem, ponieważ generuje błędy ograniczenia 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
źródło
-3

jeśli chcesz usunąć całą tabelę, musisz wykonać następną instrukcję SQL

Delete  FROM TABLE Where PRIMARY_KEY_ is Not NULL;
malejący
źródło