Как удалить все строки из всех таблиц в базе данных SQL Server?

163

Как удалить все строки из всех таблиц в базе данных SQL Server?

Михал Повага
источник
См. Codeguru.com/forum/showthread.php?t=458182 и прокрутите вниз ...
Wim ten Brink
4
по каплям база данных будет удалена, я просто хочу сбросить данные

Ответы:

264

Обратите внимание, что TRUNCATE не будет работать, если вы установили ссылочную целостность.

В этом случае это будет работать:

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
На самом деле, это только для триггеров DDL. В каком случае: EXECP sp_MSForEachTable 'ОТКЛЮЧИТЬ ТРИГГЕР ВСЕ НА?'
Марк Рендл
10
Недоступно в SQL Azure :(
Акаш Кава
Хорошо, я немного сбит с толку (может быть, вы можете помочь) Я сделал резервную копию своей базы данных, и это было около 10 МБ, затем я запустил ваш код SQL выше, чтобы очистить базу данных, и я сделал новую резервную копию того, что я думал, что пустую базу данных для отправки кому-либо еще по электронной почте, но моя «пустая» резервная копия базы данных теперь была 14 МБ? Что я сделал не так?
Бен
1
Понятно - если файл резервной копии уже существует, то похоже, что SSMS добавляет к нему, а не заменяет его (я этого не осознавал). Поэтому я удалил файл, и теперь «пустой» файл резервной копии базы данных составляет всего 3,7 МБ
Бен,
1
Что делать, если я хочу выбрать БД, что-то вроде USE [MyDataBase]:? Сработает ли приведенная выше идея, если она будет адаптирована каким-либо образом? ... Потому что я не хочу удалять все базы данных, хранящиеся на сервере SQL.
סטנלי גרונן
20

В моем недавнем проекте моей задачей было очистить всю базу данных с помощью оператора sql, и каждая таблица имела много ограничений, таких как первичный ключ и внешний ключ. В базе данных более 1000 таблиц, поэтому невозможно написать запрос на удаление для каждой таблицы.

Используя хранимую процедуру с именем sp_MSForEachTable, которая позволяет нам легко обрабатывать некоторый код для каждой таблицы в одной базе данных. Это означает, что он используется для обработки одной команды T-SQL или разных команд T-SQL для каждой таблицы в базе данных.

Поэтому выполните следующие шаги для усечения всех таблиц в базе данных SQL Server:

Шаг 1. Отключите все ограничения для базы данных, используя приведенный ниже SQL-запрос:

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

Шаг 2. Выполните операцию удаления или усечения для каждой таблицы базы данных, используя следующую команду sql:

EXEC sys.sp_msforeachtable 'DELETE FROM ?'

Шаг 3. Включите все ограничения для базы данных, используя следующую инструкцию sql:

EXEC sys.sp_MSForEachTable 'ALTER TABLE ? CHECK CONSTRAINT ALL'
е-techpulse
источник
1
Вы можете просто выполнить шаг 2 несколько раз, чтобы в первый раз он удалял таблицы без зависимостей, во второй раз удалить эти таблицы не удалось в первый раз, в третий раз удалить не удалось во второй раз и т. Д.
какие-либо идеи о том, как это сделать sql server azure?
Zapnologica
Этот подход будет работать и в Azure, так как он использует только простой SQL: sqlrelease.com/delete-all-rows-from-all-tables
Jakob Lithner
15

Я должен был удалить все строки и сделал это с помощью следующего скрипта:

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

Надеюсь это поможет!

Гонза Овьедо
источник
Спасибо за это, потому что мне нужно было настроить select для устранения некоторых таблиц. Это хорошо сработало для этого.
Дон Роллинг
13

Вот решение, которое:

  1. Удаляет ограничения (благодаря этому посту)
  2. Итерирует INFORMATION_SCHEMA.TABLESдля конкретной базы данных
  3. SELECTS таблицы на основе некоторых критериев поиска
  4. Удаляет все данные из этих таблиц
  5. Повторно добавляет ограничения
  6. Позволяет игнорировать определенные таблицы, такие как sysdiagramsи__RefactorLog

Сначала я пытался EXECUTE sp_MSforeachtable 'TRUNCATE TABLE ?', но это удалило мои диаграммы.

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"
Зак Смит
источник
Это замечательно, но не учитывает схемы не-dbo.
влиятельный
Я никогда не использовал схемы, не относящиеся к dbo, поэтому я бы этого не понял. Но почему это не работает? Я нигде не указываю схему, поэтому она по умолчанию только для dbo?
Зак Смит
Если у вас есть таблица, например, с именем test.Table1, где «test» - схема, ваши удаления будут неудачными, если вы попытаетесь выполнить «DELETE FROM Table1». Это должно быть DELETE FROM test.Table1.
влиятельный
2
@influent - теперь он принимает во внимание не-dbo схемы
Зак Смит
К сожалению, это кажется неудачным, если есть ограничения FK. ALTER TABLEБит для отключения ограничений не удается.
Дуглас Гаскелл
8

В моем случае мне нужно было включить QUOTED_IDENTIFIER. Это привело к небольшому изменению ответа Марка Рендла выше:

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
Уильям Джокуш
источник
Работал на меня - до того, как я получил эту ошибку: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
источник
1

Вы можете удалить все строки из всех таблиц, используя подход, предложенный Рубенсом, или просто удалить и заново создать все таблицы. Всегда хорошая идея иметь полные сценарии создания БД, так что это может быть самый простой / быстрый способ.

AdaTheDev
источник
Кажется, OP обеспокоен ссылочной целостностью и триггерами; В этом случае у вас есть лучшее решение. Я опускаю свой ответ =)
Рубенс Фариас
2
Я имел в виду обрезать его =)
Рубенс Фариас
0

Для некоторых требований мы могли бы пропустить определенные таблицы. Я написал скрипт ниже, чтобы добавить некоторые дополнительные условия для фильтрации списка таблиц. Приведенный ниже скрипт также отображает количество удалений до и после удаления.

        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

Этот ответ основан на ответе Зака ​​Смита путем сброса столбца идентификаторов. :

  1. Отключение всех ограничений
  2. Итерация по всем таблицам, кроме тех, которые вы решили исключить
  3. Удаляет все строки из таблицы
  4. Сбрасывает столбец идентификаторов, если он существует
  5. Разрешает все ограничения

Вот запрос:

-- 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"
Морская рыба
источник
По той или иной причине это в большинстве случаев дает сбой, так как выдает ошибки ограничения FK.
Дуглас Гаскелл
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
источник
-3

если вы хотите удалить всю таблицу, вы должны следовать следующей инструкции SQL

Delete  FROM TABLE Where PRIMARY_KEY_ is Not NULL;
malej
источник