Как вы усекаете все таблицы в базе данных с помощью TSQL?

У меня есть тестовая среда для базы данных, я хочу, чтобы перезагрузить данные в начале цикла тестирования. Меня не интересует перестройка всей базы данных - просто "переустановка" данных.

каков наилучший способ удалить все данные из всех таблиц с помощью TSQL? Существуют системные хранимые процедуры, представления и т. д. что можно использовать? Я не хочу вручную создавать и поддерживать операторы truncate table для каждой таблицы - я бы предпочел, чтобы это было активный.

17 ответов


для SQL 2005,

EXEC sp_MSForEachTable 'TRUNCATE TABLE ?'

еще пара ссылок для 2000 и 2005/2008..


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

-- disable all constraints
EXEC sp_MSForEachTable "ALTER TABLE ? NOCHECK CONSTRAINT all"

-- delete data in all tables
EXEC sp_MSForEachTable "DELETE FROM ?"

-- enable all constraints
exec sp_MSForEachTable "ALTER TABLE ? WITH CHECK CHECK CONSTRAINT all"

подробнее об отключении ограничений и триггеров здесь

Если в некоторых таблицах есть столбцы идентификаторов, мы можем захотеть их переустановить

EXEC sp_MSForEachTable "DBCC CHECKIDENT ( '?', RESEED, 0)"

обратите внимание, что поведение RESEED отличается между новой таблицей и той, в которую ранее были вставлены некоторые данные из бол:

DBCC CHECKIDENT ('table_name', RESEED, newReseedValue)

текущее значение идентификатора установлено в в newReseedValue. Если нет строк был вставлен в таблицу, так как он создана, вставлена первая строка после выполнения инструкции DBCC checkident, будет будет использовать newReseedValue как личность. В противном случае следующая строка будет вставлена используйте newReseedValue + 1. Если значение из newReseedValue меньше максимальное значение в столбце идентификаторов , сообщение 2627 будет сгенерирована ошибка на последующих ссылках на таблицу.

спасибо Роберт для указания на то, что отключение ограничений не позволяет использовать усечение, ограничения должны быть удалены, а затем воссозданы


вот король папа скриптов очистки базы данных. Он очистит все таблицы и правильно их переустановит:

SET QUOTED_IDENTIFIER ON;
EXEC sp_MSforeachtable 'SET QUOTED_IDENTIFIER ON; ALTER TABLE ? NOCHECK CONSTRAINT ALL'  
EXEC sp_MSforeachtable 'SET QUOTED_IDENTIFIER ON; ALTER TABLE ? DISABLE TRIGGER ALL'  
EXEC sp_MSforeachtable 'SET QUOTED_IDENTIFIER ON; DELETE FROM ?'  
EXEC sp_MSforeachtable 'SET QUOTED_IDENTIFIER ON; ALTER TABLE ? CHECK CONSTRAINT ALL'  
EXEC sp_MSforeachtable 'SET QUOTED_IDENTIFIER ON; ALTER TABLE ? ENABLE TRIGGER ALL' 
EXEC sp_MSforeachtable 'SET QUOTED_IDENTIFIER ON;

IF NOT EXISTS (
    SELECT
        *
    FROM
        SYS.IDENTITY_COLUMNS
        JOIN SYS.TABLES ON SYS.IDENTITY_COLUMNS.Object_ID = SYS.TABLES.Object_ID
    WHERE
        SYS.TABLES.Object_ID = OBJECT_ID(''?'') AND SYS.IDENTITY_COLUMNS.Last_Value IS NULL
)
AND OBJECTPROPERTY( OBJECT_ID(''?''), ''TableHasIdentity'' ) = 1

    DBCC CHECKIDENT (''?'', RESEED, 0) WITH NO_INFOMSGS'

наслаждайтесь, но будьте осторожны!


самый простой способ сделать это -

  1. откройте SQL Management Studio
  2. перейдите к базе данных
  3. щелкните правой кнопкой мыши и выберите задачи - > создать сценарии (рис. 1)
  4. на экране " выбрать объекты "выберите опцию" выбрать конкретные объекты "и установите флажок" таблицы " (рис. 2)
  5. на следующем экране выберите "дополнительно" , а затем измените параметр" падение сценария и создание "на" падение сценария и создание " (рис. 3)
  6. Выберите, чтобы сохранить сценарий в новом окне редактора или файла и запустить при необходимости.

Это даст вам сценарий, который отбрасывает и воссоздает все ваши таблицы без необходимости беспокоиться об отладке или о том, включили ли вы все. Хотя это выполняет больше, чем просто усечение, результаты одинаковы. Просто имейте в виду, что ваши автоматически увеличивающиеся первичные ключи будут начинаться с 0, в отличие от усеченных таблиц, которые будут помнить последнее назначенное значение. Вы также можете выполнить это из кода, если у вас нет доступа к Management studio в PreProd или производственных средах.

1.

enter image description here

2.

enter image description here

3.

enter image description here


усечение всех таблиц будет работать, только если у вас нет связей внешнего ключа между вашими таблицами, так как SQL Server не позволит вам усечь таблицу с внешним ключом.

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

см.http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=65341 и http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=72957 для получения дополнительной информации.


альтернативным вариантом, который мне нравится использовать с MSSQL Server Deveploper или Enterprise, является создание моментального снимка базы данных сразу после создания пустой схемы. На этом этапе вы можете просто продолжить восстановление базы данных обратно в моментальный снимок.


Не делай этого! Действительно, не очень хорошая идея.

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

Если вы действительно хотите усечь их все (так что вы можете загрузить их, например, BCP), вы будете так же быстро удалить базу данных и создать новую с нуля, что будет иметь дополнительное преимущество, что вы точно знаете, где вы находитесь.


Если вы хотите сохранить данные в определенной таблице (т. е. в таблице статического поиска) при удалении/усечении данных в других таблицах в той же БД, вам нужен цикл с исключениями в нем. Это то, что я искал, когда наткнулся на этот вопрос.

sp_MSForEachTable кажется мне багги (т. е. несогласованное поведение с утверждениями IF), что, вероятно, поэтому его недокументировано MS.

declare @LastObjectID int = 0
declare @TableName nvarchar(100) = ''
set @LastObjectID = (select top 1 [object_id] from sys.tables where [object_id] > @LastObjectID order by [object_id])
while(@LastObjectID is not null)
begin
    set @TableName = (select top 1 [name] from sys.tables where [object_id] = @LastObjectID)

    if(@TableName not in ('Profiles', 'ClientDetails', 'Addresses', 'AgentDetails', 'ChainCodes', 'VendorDetails'))
    begin
        exec('truncate table [' + @TableName + ']')
    end 

    set @LastObjectID = (select top 1 [object_id] from sys.tables where [object_id] > @LastObjectID order by [object_id])
end

создайте пустую базу данных "шаблон", сделайте полную резервную копию. Когда вам нужно обновить, просто восстановите с помощью REPLACE. Быстрый, простой и надежный. И если пара таблиц здесь или там нуждаются в некоторых базовых данных(например, информация о конфигурации или просто основная информация, которая заставляет ваше приложение работать), она также обрабатывает это.


гораздо проще (и, возможно, даже быстрее) создать сценарий из вашей базы данных, а затем просто удалить и создать его из сценария.


самая сложная часть усечения всех таблиц-удаление и повторное добавление ограничений внешнего ключа.

следующий запрос создает операторы drop & create для каждого ограничения, относящегося к каждому имени таблицы в @myTempTable. Если вы хотите создать их для всех таблиц, вы можете просто использовать информационную схему для сбора этих имен таблиц.

DECLARE @myTempTable TABLE (tableName varchar(200))
INSERT INTO @myTempTable(tableName) VALUES
('TABLE_ONE'),
('TABLE_TWO'),
('TABLE_THREE')


-- DROP FK Contraints
SELECT 'alter table '+quotename(schema_name(ob.schema_id))+
  '.'+quotename(object_name(ob.object_id))+ ' drop constraint ' + quotename(fk.name) 
  FROM sys.objects ob INNER JOIN sys.foreign_keys fk ON fk.parent_object_id = ob.object_id
  WHERE fk.referenced_object_id IN 
      (
         SELECT so.object_id 
         FROM sys.objects so JOIN sys.schemas sc
         ON so.schema_id = sc.schema_id
         WHERE so.name IN (SELECT * FROM @myTempTable)  AND sc.name=N'dbo'  AND type in (N'U'))


 -- CREATE FK Contraints
 SELECT 'ALTER TABLE [PIMSUser].[dbo].[' +cast(c.name as varchar(255)) + '] WITH NOCHECK ADD CONSTRAINT ['+ cast(f.name as varchar(255)) +'] FOREIGN KEY (['+ cast(fc.name as varchar(255)) +'])
      REFERENCES [PIMSUser].[dbo].['+ cast(p.name as varchar(255)) +'] (['+cast(rc.name as varchar(255))+'])'
FROM  sysobjects f
      INNER JOIN sys.sysobjects c ON f.parent_obj = c.id
      INNER JOIN sys.sysreferences r ON f.id = r.constid
      INNER JOIN sys.sysobjects p ON r.rkeyid = p.id
      INNER JOIN sys.syscolumns rc ON r.rkeyid = rc.id and r.rkey1 = rc.colid
      INNER JOIN sys.syscolumns fc ON r.fkeyid = fc.id and r.fkey1 = fc.colid
WHERE 
      f.type = 'F'
      AND
      cast(p.name as varchar(255)) IN (SELECT * FROM @myTempTable)

затем я просто копирую операторы для запуска, но с небольшим усилием dev вы можете использовать курсор для динамического запуска.


это один способ сделать это... вероятно, есть 10 других, которые лучше / эффективнее, но похоже, что это делается очень редко, поэтому здесь идет...

получить список tables с sysobjects, затем цикл над теми, с курсором, вызывая sp_execsql('truncate table ' + @table_name) для каждого iteration.


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

это или сохранить резервную копию пустой БД и восстановить его поверх старого


перед усечением таблиц необходимо удалить все внешние ключи. Используйте это скрипт для создания окончательных сценариев для удаления и воссоздания всех внешних ключей в базе данных. Пожалуйста, установите переменную @action в "CREATE" или "DROP".


запустить закомментированный раздел после заполнения _TruncateList таблицы с таблицы усе, потом работать весь остальной скрипт. Таблица _ScriptLog должна быть очищена с течением времени, если вы делаете это много.

вы можете изменить это, если хотите сделать все таблицы, просто введите SELECT name в #TruncateList из sys.таблицы. Однако обычно вы не хотите делать их все.

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

/*
CREATE TABLE _ScriptLog 
(
    ID Int NOT NULL Identity(1,1)
    , DateAdded DateTime2 NOT NULL DEFAULT GetDate()
    , Script NVarChar(4000) NOT NULL
)

CREATE UNIQUE CLUSTERED INDEX IX_ScriptLog_DateAdded_ID_U_C ON _ScriptLog
(
    DateAdded
    , ID
)

CREATE TABLE _TruncateList
(
    TableName SysName PRIMARY KEY
)
*/
IF OBJECT_ID('TempDB..#DropFK') IS NOT NULL BEGIN
    DROP TABLE #DropFK
END

IF OBJECT_ID('TempDB..#TruncateList') IS NOT NULL BEGIN
    DROP TABLE #TruncateList
END

IF OBJECT_ID('TempDB..#CreateFK') IS NOT NULL BEGIN
    DROP TABLE #CreateFK
END

SELECT Scripts = 'ALTER TABLE ' + '[' + OBJECT_NAME(f.parent_object_id)+ ']'+
' DROP  CONSTRAINT ' + '[' + f.name  + ']'
INTO #DropFK
FROM .sys.foreign_keys AS f
INNER JOIN .sys.foreign_key_columns AS fc
ON f.OBJECT_ID = fc.constraint_object_id

SELECT TableName
INTO #TruncateList
FROM _TruncateList

SELECT Scripts = 'ALTER TABLE ' + const.parent_obj + '
    ADD CONSTRAINT ' + const.const_name + ' FOREIGN KEY (
            ' + const.parent_col_csv + '
            ) REFERENCES ' + const.ref_obj + '(' + const.ref_col_csv + ')
'
INTO #CreateFK
FROM (
    SELECT QUOTENAME(fk.NAME) AS [const_name]
        ,QUOTENAME(schParent.NAME) + '.' + QUOTENAME(OBJECT_name(fkc.parent_object_id)) AS [parent_obj]
        ,STUFF((
                SELECT ',' + QUOTENAME(COL_NAME(fcP.parent_object_id, fcp.parent_column_id))
                FROM sys.foreign_key_columns AS fcP
                WHERE fcp.constraint_object_id = fk.object_id
                FOR XML path('')
                ), 1, 1, '') AS [parent_col_csv]
        ,QUOTENAME(schRef.NAME) + '.' + QUOTENAME(OBJECT_NAME(fkc.referenced_object_id)) AS [ref_obj]
        ,STUFF((
                SELECT ',' + QUOTENAME(COL_NAME(fcR.referenced_object_id, fcR.referenced_column_id))
                FROM sys.foreign_key_columns AS fcR
                WHERE fcR.constraint_object_id = fk.object_id
                FOR XML path('')
                ), 1, 1, '') AS [ref_col_csv]
    FROM sys.foreign_key_columns AS fkc
    INNER JOIN sys.foreign_keys AS fk ON fk.object_id = fkc.constraint_object_id
    INNER JOIN sys.objects AS oParent ON oParent.object_id = fkc.parent_object_id
    INNER JOIN sys.schemas AS schParent ON schParent.schema_id = oParent.schema_id
    INNER JOIN sys.objects AS oRef ON oRef.object_id = fkc.referenced_object_id
    INNER JOIN sys.schemas AS schRef ON schRef.schema_id = oRef.schema_id
    GROUP BY fkc.parent_object_id
        ,fkc.referenced_object_id
        ,fk.NAME
        ,fk.object_id
        ,schParent.NAME
        ,schRef.NAME
    ) AS const
ORDER BY const.const_name

INSERT INTO _ScriptLog (Script)
SELECT Scripts
FROM #CreateFK

DECLARE @Cmd NVarChar(4000)
    , @TableName SysName

WHILE 0 < (SELECT Count(1) FROM #DropFK) BEGIN
    SELECT TOP 1 @Cmd = Scripts 
    FROM #DropFK

    EXEC (@Cmd)

    DELETE #DropFK WHERE Scripts = @Cmd
END

WHILE 0 < (SELECT Count(1) FROM #TruncateList) BEGIN
    SELECT TOP 1 @Cmd = N'TRUNCATE TABLE ' +  TableName
        , @TableName = TableName
    FROM #TruncateList

    EXEC (@Cmd)

    DELETE #TruncateList WHERE TableName = @TableName
END

WHILE 0 < (SELECT Count(1) FROM #CreateFK) BEGIN
    SELECT TOP 1 @Cmd = Scripts 
    FROM #CreateFK

    EXEC (@Cmd)

    DELETE #CreateFK WHERE Scripts = @Cmd
END

Это немного поздно, но это может помочь кому-то. Я создал процедуру иногда назад, которая делает следующее, используя T-SQL:

  1. сохранить все ограничения во временной таблице
  2. Снять Все Ограничения
  3. усечь все таблицы, за исключением некоторых таблиц, которые не нужны усечение
  4. воссоздать все трудности.

Я перечислил его в своем блоге здесь


выберите "Удалить из" +TABLE_NAME из INFORMATION_SCHEMA.Таблицы, где TABLE_TYPE= 'BASE TABLE'

где результат придет.

скопируйте и вставьте в окно запроса и выполните команду