Як видалити всі рядки з усіх таблиць у базі даних SQL Server?


Відповіді:


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 'DISABLE TRIGGER ALL ON?'
Марк Rendle

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'

1
Ви можете просто виконати послідовні кроки 2 кроку, щоб перший раз видалити таблиці з незалежністю, 2-й раз видалити ці таблиці не вдалося в перший раз, 3-й раз видалити помилку вдруге тощо

якісь ідеї, як це зробити sql server azure?
Zapnologica

Цей підхід буде працювати і в Azure, оскільки він використовує лише звичайний SQL: sqlrelease.com/delete-all-rows-from-all-tables
Якоб Літнер

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

Сподіваюся, це допомагає!


Дякую за це, тому що мені потрібно було змінити вибір, щоб усунути деякі таблиці. Це добре спрацювало для цього.
Дон

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". Це повинно бути ВИДАЛЕНО ВІД тесту. Таблиця1.
впливовий

2
@influent - тепер він враховує схеми, що не стосуються dbo,
Зах Сміт

На жаль, це здається невдалим, якщо є обмеження у ФК. 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'

1

Ви можете видалити всі рядки з усіх таблиць, використовуючи такий підхід, як запропоновано Рубенсом, або ви можете просто скинути і відтворити всі таблиці. Завжди гарною ідеєю є повний сценарій створення db так чи інакше, щоб це був найпростіший / швидкий метод.


здається, що ОП стурбована референтною цілісністю та спрацьовує; у цьому випадку, ви отримали найкраще рішення. Я відкидаю свою відповідь =)
Рубенс Фаріас

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; 

-3

якщо ви хочете видалити всю таблицю, ви повинні слідувати наступній інструкції SQL

Delete  FROM TABLE Where PRIMARY_KEY_ is Not NULL;
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.