Você pode usar os métodos Alterar arquivo, Modificar arquivo ou Desanexar / anexar.
Nota: Ambos exigirão algum tempo de inatividade, portanto, isso deve ser feito durante a janela de manutenção.
Isso pressupõe que você tenha a mesma estrutura de diretórios na nova unidade, por exemplo, C: \ data \ e D: \ Data.
- usando o banco de dados Alter com o método Modify (preferido)
SET NOCOUNT ON
DECLARE @datafile VARCHAR(255)
,@logfile VARCHAR(255)
,@dbid TINYINT
,@SQLText VARCHAR(max)
,@dbname VARCHAR(255)
,@sqltext1 VARCHAR(max)
,@SQLText2 VARCHAR(max)
--2. Prepare for modify
IF EXISTS (
SELECT 1
FROM tempdb..sysobjects
WHERE NAME LIKE '%#filetable%'
)
BEGIN
DROP TABLE #filetable
END
CREATE TABLE #filetable (
mdf VARCHAR(255)
,ldf VARCHAR(255)
,dbid TINYINT
,dbname VARCHAR(100)
,fileid TINYINT
,logicalname SYSNAME
)
--
INSERT #filetable (
mdf
,dbid
,fileid
,logicalname
)
SELECT physical_name
,database_id
,data_space_id
,NAME
FROM sys.master_files
WHERE data_space_id = 1
INSERT #filetable (
ldf
,dbid
,fileid
,logicalname
)
SELECT physical_name
,database_id
,data_space_id
,NAME
FROM sys.master_files
WHERE data_space_id = 0
UPDATE u
SET u.dbname = s.NAME
FROM #filetable u
INNER JOIN master..sysdatabases s ON u.dbid = s.dbid
UPDATE #filetable
SET mdf = replace(mdf, 'C:', 'D:')
,ldf = replace(ldf, 'C:', 'D:')
FROM #filetable
SELECT @dbid = min(dbid)
FROM #filetable
WHERE dbid > 4
WHILE @dbid IS NOT NULL
BEGIN
SELECT @SQLText = 'alter database [' + dbname + '] MODIFY FILE (Name = ' + logicalname + ' , FileName = N''' + ldf + ''');'
FROM #filetable
WHERE dbid = convert(VARCHAR, @dbid)
AND fileid = 0 -- Log file
PRINT @SQLText
--Exec(@SQLText)
SELECT @SQLText2 = 'alter database [' + dbname + '] MODIFY FILE (Name = ' + logicalname + ' , FileName = N''' + mdf + ''');'
FROM #filetable
WHERE dbid = convert(VARCHAR, @dbid)
AND fileid = 1 -- data file
PRINT @SQLText2
--Exec(@SQLText)
SELECT @dbid = min(dbid)
FROM #filetable
WHERE dbid > 4
AND dbid > @dbid
END
--- usando o método Old Detach / Attach (não é o preferido, mas ainda assim as pessoas o usam .. infelizmente eu o usei recentemente em um servidor que não é um produto).
DECLARE @datafile VARCHAR(255)
,@logfile VARCHAR(255)
,@dbid TINYINT
,@SQLText VARCHAR(8000)
,@dbname VARCHAR(255)
,@SQLText2 VARCHAR(8000)
--2. Detach All Local Databases and prepare for Attach
IF EXISTS (
SELECT 1
FROM tempdb..sysobjects
WHERE NAME LIKE '%#filetable%'
)
BEGIN
DROP TABLE #filetable
END
CREATE TABLE #filetable (
mdf VARCHAR(255)
,ldf VARCHAR(255)
,dbid TINYINT
,dbname VARCHAR(100)
,fileid TINYINT
)
--
INSERT #filetable (
mdf
,dbid
,fileid
)
SELECT physical_name
,database_id
,data_space_id
FROM sys.master_files
WHERE data_space_id = 1
INSERT #filetable (
ldf
,dbid
,fileid
)
SELECT physical_name
,database_id
,data_space_id
FROM sys.master_files
WHERE data_space_id = 0
UPDATE u
SET u.dbname = s.NAME
FROM #filetable u
INNER JOIN master..sysdatabases s ON u.dbid = s.dbid
UPDATE #filetable
SET mdf = replace(mdf, 'C:', 'D:')
,ldf = replace(ldf, 'C:', 'D:')
FROM #filetable
SELECT @dbid = min(dbid)
FROM #filetable
WHERE dbid > 4
WHILE @dbid IS NOT NULL
BEGIN
SELECT @SQLText = 'alter database [' + dbname + ']'
FROM #filetable
WHERE dbid = convert(VARCHAR, @dbid)
SELECT @SQLText = @SQLText + CHAR(10) + ' set single_user with rollback immediate;'
SELECT @SQLText = @SQLText + CHAR(10) + ' exec master..sp_detach_db ' + dbname
FROM #filetable
WHERE dbid = convert(VARCHAR, @dbid)
PRINT @SQLText
--Exec(@SQLText)
SELECT @SQLText2 = 'exec master..sp_attach_db ''' + dbname + ''''
FROM #filetable
WHERE dbid = @dbid
SELECT @SQLText2 = @SQLText2 + ',''' + mdf + ''''
FROM #filetable
WHERE dbid = @dbid
AND mdf IS NOT NULL
SELECT @SQLText2 = @SQLText2 + ',''' + ldf + ''''
FROM #filetable
WHERE dbid = @dbid
AND ldf IS NOT NULL
PRINT @SQLText2
--Exec(@SQLText)
SELECT @dbid = min(dbid)
FROM #filetable
WHERE dbid > 4
AND dbid > @dbid
END
DROP TABLE #filetable