Переміщення таблиць до іншої бази даних SQL2008 (включаючи індекси, тригери тощо)


16

Мені потрібно перемістити цілу купу (100+) великих (мільйонів рядків) таблиць з однієї бази даних SQL2008 в іншу.

Я спочатку використовував майстра імпорту / експорту, але у всіх таблицях призначення були відсутні первинні та зовнішні ключі, індекси, обмеження, тригери тощо (стовпці ідентичності також були перетворені на звичайні INT, але я думаю, що я просто пропустив прапорець у майстер.)

Який правильний спосіб зробити це?

Якби це було лише кілька таблиць, я б повернувся до джерела, скрипт визначив визначення таблиці (з усіма індексами тощо), а потім запустив частини створення індексу сценарію за призначенням. Але з такою кількістю таблиць це здається недоцільним.

Якщо даних було не так багато, я б міг скористатися майстром "Створити скрипти ...", щоб скриптувати джерело, включаючи дані, але сценарій рядка в 72 м просто не здається гарною ідеєю!


І це не всі таблиці в базі даних?
четверггек

@th Thursdaysgeek: Його майже всі таблиці, але база даних вже має 100 таблиць. Тому просто відновити з резервної копії інше ім’я - це не варіант. Подумайте про це як в основному "об'єднайте ці дві великі бази даних разом".
BradC

Відповіді:


14

Скриптування таблиць та використання SSIS для передачі даних було б найбільш надійним та ефективним способом переміщення даних у нову базу даних.


9

Ми насправді зробили це, використовуючи багато ручних сценаріїв спільно з майстром імпорту, але сьогодні вранці я знайшов кращу відповідь, люб’язно надавши статтю в блозі Тібора Каразі .

Частина нашого розчарування полягала в тому, що SQL 2000 "майстер імпорту / експорту DTS" насправді робить це майже тривіально простим шляхом вибору "Копіювати об'єкти та дані":

Майстер імпорту DTS

Цей третій варіант - це той, який містить можливість включати індекси / тригери тощо:

Розширені опції

Цей параметр було видалено з майстра імпорту SQL 2005/2008 . Чому? Не маю уявлення:

Майстер імпорту 2008 року

У 2005/2008 роках вам, мабуть, доведеться вручну створити пакет SSIS в BIDS та використовувати завдання передачі об'єктів SQL Server , що містить усі ті самі параметри, що були у майстра 2000 року:

Завдання об’єктів SQL Server Transfer Transfer


Просто хотів опублікувати, що я використовував цей метод SSIS для іншого подібного завдання, і він чудово працював!
BradC

8

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

Тоді я б подумав відновити базу даних з іншим іменем на одному сервері і зробити це

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

.. для кожної таблиці з ВИМКНЕНОМ ІДЕНТИЧНОСТІ ВКЛЮЧЕНО, якщо потрібно

Тоді я б додав індекси та обмеження після завантаження даних.

Це залежить від рівня вашого комфорту за допомогою SSIS (відповідь mrdenny) або якщо ви віддаєте перевагу сирому SQL.


6

Я додам відповідь містера Денні: Скриптуйте схему таблиць, а потім використовуйте BCP для переміщення даних. Якщо ви не знайомі з SSIS, то використовувати BCP та партії слід легко. За мільйони рядків нічого не б'є BCP (об'ємна вставка) :).


4

Мені абсолютно незручно з SSIS.

Коли у вихідних таблиць немає стовпців ідентичності

  1. створити порожню базу даних на цільовому сервері
  2. створити зв'язаний сервер з вихідним сервером на цільовому сервері
  3. запустіть скрипт нижче у вихідній базі даних, щоб генерувати вибір * у ... операторах
  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];

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

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

Відтворення індексів і т. Д. Аналогічно вищевикладеному. Цього разу я можу пропустити відтворення первинних ключів.


У випадку, якщо таблиці містять стовпці ідентичності, ви можете зробити так, як у цьому питанні . Це заощадить певну ручну роботу. Я все ще віддаю перевагу пакетним пакетам вставок / SSIS, пов'язаний сервер може бути не гарним рішенням для широкої мережі.
Маріан

1
@Marian Якщо ви хочете просувати SSIS, подивіться на dba.stackexchange.com/questions/297/… Я не пробував SSIS, але майстер імпорту експорту теж не вдався (крім пов'язаного сервера).
bernd_k

Я б допоміг із задоволенням, але в мене немає жодної скриньки Oracle. У будь-якому випадку, з того, що мені вдалося прочитати, немає постачальників, які б підтримували Oracle CLOB ..
Marian

Я з вами з цього приводу - інколи переношу дані, але ніколи не використовую SSIS.
АК

2

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

Потім синхронізуйте дані з вихідної бази даних з новою (усі таблиці є, але всі вони порожні), щоб вставити записи в таблиці

Для цього я використовую 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 метод, оскільки він використовує Native mode.

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