2012-05-31 2 views
3

Мы переносим один из наших серверов с SQL Server 2005 на SQL Server 2008. На этом сервере имеется около 50 небольших баз данных.Присоединить несколько баз данных с использованием T-SQL

путь миграции мы принимаем идет следующим образом:

  1. Создать новый сервер с SQL 2008
  2. Shutdown служб SQL Server на старом сервере и скопировать базы данных на новый старый сервер один
  3. Shutdown и переименовать новый сервер с тем же именем, что и старый.
  4. Вложить 50 баз данных

Есть ли быстрый способ с использованием T-SQL, чтобы прикрепить 50 баз данных на новый сервер?

Все файлы данных будут располагаться на E: \ DATA и журналы транзакций будут располагаться на E: \ TLOG

+2

Настоятельно рекомендую вам рассмотреть другой подход, чем отсоединить/прикрепить. Вот почему: http://dba.stackexchange.com/questions/18593/should-i-migrate-data-using-detach-copy-attach-or-through-backup-restore-replay –

ответ

5

Использование режима SQLCMD, вы можете легко скрипт так:

:setvar dbname YourDatabaseName 
:setvar dbfile N'E:\DATA\YourDatabase.mdf' 
:setvar logfile N'E:\TLOG\YourDatabase_log.ldf' 
USE [master] 
GO 

CREATE DATABASE $(dbname) ON 
(FILENAME = $(dbfile)), 
(FILENAME = $(logfile)) 
FOR ATTACH 
GO 

Это работает либо с sqlcmd.exe из командной строки (вы даже можете указать значения для переменных dbname, dbfile, logfile из командной строки), либо работает в SQL Server Management Studio, если вы включили Tools > Options > Query Execution > by default, open new queries in SQLCMD mode.

Подробнее о SQLCMD utility and all its parameters на MSDN.

PS: Конечно, этот подход с поддержкой сценарием SQLCMD также работает для резервного копирования/восстановления цикла :-) (в соответствии с рекомендациями Аароном)

PPS: если у вас есть хорошее именование, и файл данные всегда $(dbname).mdf и файл журнала всегда $(dbname)_log.ldf, вы можете также использовать эту сокращенную SQLCMD скрипт:

:setvar dbname YourDatabaseName 
USE [master] 
GO 

CREATE DATABASE $(dbname) ON 
(FILENAME = N'E:\DATA\$(dbfile).mdf'), 
(FILENAME = N'E:\TLOG\$(logfile)_log.ldf') 
FOR ATTACH 
GO 

, а затем просто вызовите из командной строки:

C:\> sqlcmd.exe -S yourserver -E -i attach.sql -v dbname=YourDb1 

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

PPPS: если вы хотите восстановить резервные копии, это просто немного сложнее:

:setvar dbname YourDatabaseName 
USE [master] 
GO 

RESTORE DATABASE $(dbname) 
FROM DISK = N'E:\Backup\$(dbname).bak' 
WITH FILE = 1, 
MOVE N'$(dbname)' TO N'E:\DATA\$(dbname).mdf', 
MOVE N'$(dbname)_Log' TO N'E:\TLOG\$(dbname)_Log.ldf', 
NOUNLOAD, REPLACE 
GO 

Это работает, до тех пор, как вы называете ваши .bak файлы так же, как ваше имя базы данных, и поместить их в фиксированное местоположение (я предположил, что здесь E:\Backup - при необходимости приспособитесь).

+0

Если я делаю резервное копирование/восстановление метод ... Могу ли я использовать созданный вами скрипт для восстановления базы данных? –

+0

@NeilHoff, я добавил ответ, который создает команды резервного копирования и восстановления с использованием динамического SQL. –

2

Чтобы повторно повторить мой комментарий, я предлагаю подход резервного копирования/восстановления, а не подход detach/attach (my reasons are outlined here).

И хотя мне нравится подход SQLCMD от @ marc_s, я предпочитаю напрямую извлекать этот материал из метаданных. Таким образом, я могу проверить все выходные данные, скопировать и вставить части, которые я хочу выполнить партиями, а не сразу, и т. Д.Что-то вроде:

DECLARE @bl VARCHAR(512) = '\\fileshare\folder\'; -- 'backup location 

SET NOCOUNT ON; 

SELECT 'BACKUP DATABASE ' + QUOTENAME(name) 
    + ' TO DISK = ''' + @bl + name + '.BAK'' WITH INIT; 
    ALTER DATABASE ' + QUOTENAME(name) + ' SET OFFLINE;' 
FROM sys.databases WHERE database_id > 4 -- AND other filter criteria 

SELECT 'RESTORE DATABASE ' + QUOTENAME(d.name) + ' FROM DISK=''' + @bl + d.name 
    + '.BAK'' WITH ' + STUFF((SELECT ',MOVE ''' + f.name + ''' 
    TO ''E:\DATA\' + f.name + '.mdf''' FROM master.sys.master_files AS f 
    WHERE f.database_id = d.database_id AND type_desc = 'ROWS' 
    FOR XML PATH('')), 1, 1, '') 
    +', '+ STUFF((SELECT ',MOVE ''' + f.name + ''' TO ''E:\TLOG\' + f.name + '.mdf''' 
    FROM master.sys.master_files AS f 
    WHERE f.database_id = d.database_id AND type_desc = 'LOG' 
    FOR XML PATH('')), 1, 1, '') + '; 
    ALTER DATABASE ' + QUOTENAME(d.name) + ' SET COMPATIBILITY_LEVEL = 100;' 
FROM sys.databases AS d WHERE database_id > 4 -- AND other filter criteria 

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

Для уточнения , вы бы сгенерировали оба набора команд на сервере 2005 года, скопируйте & там резервные команды (и, возможно, сразу же установите их в автономный режим), затем скопируйте & команды восстановления на сервере 2008 года.

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

+0

Но если OP переходит от одного сервера к отдельной серверной машине, нет никакого «общего» местоположения для представления «sys.databases» - правильно? –

+1

@marc_s Обе эти команды будут запускаться на текущем сервере 2005 года (что напоминает мне, чтобы вывести вариант сжатия). Команды резервного копирования будут выполняться на сервере 2005 года, команды восстановления будут выполняться на сервере 2008 года. Если файлы должны быть скопированы, потому что общий доступ к файлам для этих двух серверов отсутствует, то это незначительное изменение в разделах TO DISK и FROM DISK инструкции. Какое другое общее местоположение необходимо? –

Смежные вопросы