Как вы усекаете все таблицы в базе данных, используя TSQL? - PullRequest
191 голосов
/ 01 октября 2008

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

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

Ответы [ 17 ]

400 голосов
/ 01 октября 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 отличается для новой таблицы и таблицы, в которую ранее были вставлены некоторые данные из BOL :

ПРОВЕРКА DBCC ('имя_таблицы', RESEED, newReseedValue)

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

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

175 голосов
/ 01 октября 2008

Для SQL 2005,

EXEC sp_MSForEachTable 'TRUNCATE TABLE ?'

Пара дополнительных ссылок для 2000 и 2005/2008 ..

52 голосов
/ 04 октября 2012

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

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;

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

43 голосов
/ 20 марта 2014

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

  1. открыть SQL Management Studio
  2. перейти к вашей базе данных
  3. Щелкните правой кнопкой мыши и выберите Задачи-> Создать сценарии (рис. 1)
  4. На экране «Выбор объектов» выберите параметр «Выбрать конкретные объекты» и отметьте «таблицы» (рис. 2)
  5. на следующем экране выберите «Дополнительно», а затем измените параметр «Сценарий DROP and CREATE» на «Сценарий DROP and CREATE» (рис. 3)
  6. Выберите, чтобы сохранить сценарий в новом окне редактора или в файле и запускать при необходимости.

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

1

enter image description here

2

enter image description here

3.

enter image description here

12 голосов
/ 01 октября 2008

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

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

Подробнее см. http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=65341 и http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=72957.

7 голосов
/ 11 августа 2009

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

6 голосов
/ 02 октября 2008

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

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

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

4 голосов
/ 21 августа 2013

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

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
3 голосов
/ 17 апреля 2014

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

Следующий запрос создает операторы 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)

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

3 голосов
/ 12 августа 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...