Перемещение таблиц в другую базу данных SQL2008 (включая индексы, триггеры и т. Д.)

16

Мне нужно переместить целую кучу (более 100) больших (миллионы строк) таблиц из одной базы данных SQL2008 в другую.

Первоначально я просто использовал Мастер импорта / экспорта, но во всех таблицах назначения отсутствовали первичные и внешние ключи, индексы, ограничения, триггеры и т. Д. (Столбцы идентификаторов также были преобразованы в простые INT, но я думаю, что просто пропустил флажок в мастер).

Какой правильный способ сделать это?

Если бы это была всего лишь пара таблиц, я бы вернулся к источнику, написал сценарий определения таблицы (со всеми индексами и т. Д.), А затем запустил части сценария создания индекса в месте назначения. Но с таким количеством таблиц это кажется непрактичным.

Если бы данных было не так много, я мог бы использовать мастер «Создание сценариев ...» для составления сценария источника, включая данные, но сценарий длиной 72 метра просто не кажется хорошей идеей!

BradC
источник
И это не все таблицы в базе данных?
Четверг
@thursdaysgeek: Это почти все таблицы, но в целевой базе уже более 100 таблиц. Так что просто восстановить из резервной копии с другим именем не вариант. Думайте об этом как о «объединении этих двух больших баз данных».
BradC

Ответы:

14

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

mrdenny
источник
9

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

Отчасти мы были разочарованы тем, что «Мастер импорта / экспорта DTS» в SQL 2000 делает это почти тривиально простым, выбрав «Копировать объекты и данные»:

Мастер импорта DTS

Эта третья опция включает в себя возможность включения индексов / триггеров и т. Д.

Расширенные настройки

Этот параметр был удален из мастера импорта SQL 2005/2008 . Почему? Без понятия:

Мастер импорта 2008

В 2005/2008 году вы, очевидно, должны были вручную создать пакет служб SSIS в BIDS и использовать задачу переноса объектов SQL Server , которая содержит все те же параметры, которые были в мастере 2000:

Задача SSIS Transfer для объектов SQL Server

BradC
источник
Просто хотел опубликовать, что я использовал этот метод SSIS для другой аналогичной задачи, и он работал отлично!
BradC
8

Я хотел бы написать сценарий для таблицы или использовать инструменты сравнения (например, Red Gate) для генерации таблиц в целевой базе данных. Без индексов или ограничений пока.

Затем я хотел бы рассмотреть возможность восстановления базы данных с другим именем на том же сервере и сделать

 INSERT newdb.dbo.newtable SELECT * FROM olddb.dbo.oldtable

.. для каждой таблицы, с SET IDENTITY INSERT ON, если требуется

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

Это зависит от вашего уровня комфорта с SSIS (ответ mrdenny) или от того, предпочитаете ли вы сырой SQL.

ГБН
источник
6

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

Мэриан
источник
4

Я тот, кто совершенно не знаком с SSIS.

Когда исходные таблицы не имеют идентичных столбцов

  1. создать пустую базу данных на целевом сервере
  2. создать связанный сервер с исходным сервером на целевом сервере
  3. запустите приведенный ниже скрипт в исходной базе данных, чтобы сгенерировать операторы select * into ...
  4. запустить сгенерированный скрипт из целевой базы данных
  5. первичные ключи скриптов, индексы, триггеры, функции и процедуры из исходной базы данных
  6. создать эти объекты сгенерированным скриптом

Теперь T-SQL для генерации операторов Select * в ...

SET NOCOUNT ON

declare @name sysname
declare @sql varchar(255)

declare db_cursor cursor for
select name from sys.tables order by 1
open db_cursor

fetch next from db_cursor into @name
while @@FETCH_STATUS = 0
begin
    Set @sql = 'select * into [' + @name + '] from [linked_server].[source_db].[dbo].[' + @name + '];'
    print @sql

    fetch next from db_cursor into @name
end

close db_cursor
deallocate db_cursor

Это создает строку для каждой таблицы, чтобы скопировать как

select * into [Table1] from [linked_server].[source_db].[dbo].[Table1];

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

Я не использую вставку в ... выберите ... используя связанный сервер в этом случае, поскольку это не массовая техника. Я работаю над некоторыми сценариями PowerShell, похожими на [этот вопрос 1 , но я все еще работаю над обработкой ошибок. Действительно большие таблицы могут вызвать ошибки нехватки памяти, так как вся таблица загружается в память, прежде чем она будет отправлена ​​через SQLBulkCopy в базу данных.

Восстановление индексов и т. Д. Аналогично описанному выше. На этот раз я могу пропустить воссоздание первичных ключей.

bernd_k
источник
Если таблицы содержат столбцы идентификаторов, вы можете сделать то же самое в этом вопросе . Это избавит вас от ручной работы. Я все еще предпочитаю массовые пакеты вставки / службы SSIS, связанный сервер может быть не лучшим решением в широкой сети.
Marian
1
@Marian Пожалуйста, посмотрите на dba.stackexchange.com/questions/297/… если вы хотите продвигать SSIS. Я не пробовал SSIS, но мастер импорта экспорта тоже не удался (кроме связанного сервера).
bernd_k
Я бы с удовольствием помог, но у меня нет доступной коробки Oracle. Во всяком случае, из того, что мне удалось прочитать, нет поставщиков, которые будут поддерживать Oracle CLOB ..
Marian
Я согласен с вами в этом - иногда я перемещаю данные, но никогда не использую SSIS.
AK
2

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

Затем синхронизируйте данные из исходной базы данных с новой (все таблицы есть, но все они пусты), чтобы вставить записи в таблицы.

Для этого я использую ApexSQL Diff и ApexSQL Data Diff , но есть и другие подобные инструменты.

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

Вы можете просто создать сценарий INSERT INTO SQL (не удивляйтесь, если это несколько концертов) и выполнить его.

Поскольку в SQL Server Management Studio невозможно открыть даже такие большие сценарии, я использую sqlcmd или osql

Кэрол Бейкер Вест
источник
1

Как уже упоминалось @mrdenny -

  1. сначала выведите таблицы со всеми индексами, FK и т. д. и создайте пустые таблицы в целевой базе данных.

Вместо использования служб SSIS используйте BCP для вставки данных.

  1. bcp из данных, используя скрипт ниже. установите SSMS в текстовом режиме и скопируйте вывод, сгенерированный приведенным ниже сценарием, в файл bat.

    -- save below output in a bat file by executing below in SSMS in TEXT mode
    
    -- clean up: create a bat file with this command --> del D:\BCP\*.dat 
    
    select '"C:\Program Files\Microsoft SQL Server\100\Tools\Binn\bcp.exe" ' /* path to BCP.exe */
        +  QUOTENAME(DB_NAME())+ '.' /* Current Database */
        +  QUOTENAME(SCHEMA_NAME(SCHEMA_ID))+'.'            
        +  QUOTENAME(name)  
        +  ' out D:\BCP\'  /* Path where BCP out files will be stored */
        +  REPLACE(SCHEMA_NAME(schema_id),' ','') + '_' 
        +  REPLACE(name,' ','') 
        + '.dat -T -E -SServerName\Instance -n' /* ServerName, -E will take care of Identity, -n is for Native Format */
    from sys.tables
    where is_ms_shipped = 0 and name <> 'sysdiagrams'                       /* sysdiagrams is classified my MS as UserTable and we dont want it */
    /*and schema_name(schema_id) <> 'unwantedschema'    */                             /* Optional to exclude any schema  */
    order by schema_name(schema_id)
  2. Запустите файл bat, который сгенерирует файлы .dat в указанной вами папке.

  3. Запустите ниже скрипт на

    --- Execute this on the destination server.database from SSMS.
    
    --- Make sure the change the @Destdbname and the bcp out path as per your environment.
    
    declare @Destdbname sysname
    set @Destdbname = 'destinationDB' /* Destination Database Name where you want to Bulk Insert in */
    select 'BULK INSERT ' 
    /*Remember Tables must be present on destination database */ 
    + QUOTENAME(@Destdbname) + '.' 
    + QUOTENAME(SCHEMA_NAME(SCHEMA_ID)) 
    + '.' + QUOTENAME(name) 
    + ' from ''D:\BCP\' /* Change here for bcp out path */ 
    + REPLACE(SCHEMA_NAME(schema_id), ' ', '') + '_' + REPLACE(name, ' ', '') 
    + '.dat'' with ( KEEPIDENTITY, DATAFILETYPE = ''native'', TABLOCK )' 
    + char(10) 
    + 'print ''Bulk insert for ' + REPLACE(SCHEMA_NAME(schema_id), ' ', '') + '_' + REPLACE(name, ' ', '') + ' is done... ''' 
    + char(10) + 'go'
       from sys.tables
       where is_ms_shipped = 0
    and name <> 'sysdiagrams' /* sysdiagrams is classified my MS as UserTable and we dont want it */
    and schema_name(schema_id) <> 'unwantedschema' /* Optional to exclude any schema */
        order by schema_name(schema_id) 
  4. Запустите вывод, используя SSMS, чтобы вставить данные обратно в таблицы.

Это очень быстрый метод BCP, поскольку он использует собственный режим.

Кин Шах
источник