Compleate 스크립트 ('템플릿'에서 복제 dB 증가 스크립트, 다음 복제 drop하여 DB를 적용) 일반적인 개발 작업에 대한 충분한 융통성이 있습니다. 참고 : 절차 adv.cloneDatabase
이 실행되기 전에 DB 'read_only, single_user'를 만들어야하며, xp_cmdshell을 실행할 권한이 필요하면 원본 상태를 반환해야합니다.
CREATE PROCEDURE adv.alterateFileNames(
@mdfFileName nvarchar(256),
@ldfFileName nvarchar(256),
@newMdfFileName nvarchar(256) OUTPUT,
@newLdfFileName nvarchar(256) OUTPUT
)
AS
BEGIN
DECLARE @path_data nvarchar(256)
DECLARE @ext_data nvarchar(4)
DECLARE @path_log nvarchar(256)
DECLARE @ext_log nvarchar(4)
-- respect file extensions
if (RIGHT(@mdfFileName , 4)='.mdf')
BEGIN
SET @path_data = SUBSTRING(@mdfFileName,0,LEN(@mdfFileName)-3)
SET @ext_data = '.mdf'
END
ELSE
BEGIN
SET @path_data = @mdfFileName
SET @ext_data = ''
END
if (RIGHT(@ldfFileName , 4)='.ldf')
BEGIN
SET @path_log = SUBSTRING(@ldfFileName,0,LEN(@ldfFileName)-3)
SET @ext_log = '.ldf'
END
ELSE
BEGIN
SET @path_log = @ldfFileName
SET @ext_log = ''
END
-- respect suffix counters like dbname_2 (that means add value to them)
DECLARE @iData int
DECLARE @data_suffix_index int = len(@path_data) - charindex('_', reverse(@path_data))
IF (@data_suffix_index < len(@path_data)-1 AND @data_suffix_index > 0)
BEGIN
DECLARE @data_suffix nvarchar(128) = substring(@path_data, @data_suffix_index+2, len(@path_data)[email protected]_suffix_index-1)
IF @data_suffix NOT LIKE '%[^0-9]%'
BEGIN
SET @path_data = SUBSTRING(@path_data,0,@data_suffix_index+1)
SET @iData = CAST(@data_suffix as int);
END
END
IF (@iData is null)
BEGIN
SET @path_data = @path_data
SET @iData = 0
END
DECLARE @iLog int
DECLARE @log_suffix_index int = len(@path_log) - charindex('_', reverse(@path_log))
IF (@log_suffix_index < len(@path_log)-1 AND @log_suffix_index > 0)
BEGIN
DECLARE @log_suffix nvarchar(128) = substring(@path_log, @log_suffix_index+2, len(@path_log) - @log_suffix_index-1)
IF @log_suffix NOT LIKE '%[^0-9]%'
BEGIN
SET @path_log = SUBSTRING(@path_log,0,@log_suffix_index+1)
SET @iLog = CAST(@log_suffix as int);
END
END
IF (@iLog is null)
BEGIN
SET @path_log = @path_log
SET @iLog = 0
END
WHILE 1=1
BEGIN
IF EXISTS(SELECT * FROM sys.master_files WHERE [email protected]_data+'_'+CAST(@iData AS varchar(6))[email protected]_data)
SET @[email protected]+1
ELSE
BEGIN
SET @path_data= @path_data+'_'+CAST(@iData AS varchar(6))[email protected]_data
BREAK
END
END
WHILE 1=1
BEGIN
IF EXISTS(SELECT * FROM sys.master_files WHERE [email protected]_log+'_'+CAST(@iLog AS varchar(6))[email protected]_log)
SET @[email protected]+1
ELSE
BEGIN
SET @path_log= @path_log+'_'+CAST(@iLog AS varchar(6))[email protected]_log
BREAK
END
END
SET @newMdfFileName = @path_data
SET @newLdfFileName = @path_log
END
GO
CREATE PROCEDURE adv.cloneDatabase
(
@databaseName sysname,
@newDatabaseName sysname
)
AS
BEGIN
SET NOCOUNT ON
IF NOT EXISTS (SELECT * FROM sys.databases WHERE name = @databaseName)
THROW 50000, 'Database doesn''t exist', 1;
IF NOT EXISTS (SELECT * FROM sys.databases WHERE name = @databaseName AND owner_sid<>0x01)
THROW 50000, 'Clonning of system database is not supported', 1;
IF NOT EXISTS (SELECT * FROM sys.databases WHERE name = @databaseName AND is_read_only=1)
THROW 50000, 'Clonning of not readonly database is not supported', 1;
IF NOT EXISTS (SELECT * FROM sys.databases WHERE name = @databaseName AND user_access=1 /*single user*/)
THROW 50000, 'Clonning of nor single_user database is not supported', 1;
-- collect file info
DECLARE @Files TABLE
(
[type] int, /*0,1,2,3,4*/
type_desc nvarchar(60), /*ROWS,LOG,FILESTREAM,FULLTEXT*/
name sysname,
physical_name nvarchar(260)
)
INSERT INTO @Files ([type], type_desc, name, physical_name)
SELECT [type], type_desc, f.name, physical_name
FROM sys.master_files f INNER JOIN sys.databases d ON f.database_id=d.database_id
WHERE [email protected]
-- test files
DECLARE @filesCount int
SELECT @filesCount = count(*) from @Files
IF (@filesCount<>2)
THROW 50000, 'The procedure doesn''t support complex file structures', 1;
DECLARE @mdfFileName nvarchar(260), @ldfFileName nvarchar(260)
SELECT @mdfFileName = physical_name FROM @Files WHERE type_desc='ROWS'
SELECT @ldfFileName = physical_name FROM @Files WHERE type_desc='LOG'
DECLARE @newMdfFileName nvarchar(260), @newLdfFileName nvarchar(260)
exec adv.alterateFileNames @mdfFileName, @ldfFileName, @[email protected] OUTPUT, @[email protected] OUTPUT
DECLARE @cmd1 nvarchar(4000)= 'copy /Y "@mdfFileName" "@newMdfFileName"'
DECLARE @cmd2 nvarchar(4000)= 'copy "@ldfFileName" "@newLdfFileName"'
SET @cmd1=replace(@cmd1,'@mdfFileName',@mdfFileName)
SET @cmd1=replace(@cmd1,'@newMdfFileName',@newMdfFileName)
SET @cmd2=replace(@cmd2,'@ldfFileName',@ldfFileName)
SET @cmd2=replace(@cmd2,'@newLdfFileName',@newLdfFileName)
DECLARE @OUTPUT TABLE (line text)
DECLARE @result INT
BEGIN TRY
INSERT INTO @OUTPUT (line) VALUES ('> '[email protected])
INSERT INTO @OUTPUT
exec @result =xp_cmdshell @cmd1
INSERT INTO @OUTPUT (line) VALUES ('> '[email protected])
IF (@result <> 0)
THROW 50000, 'Error copying mdf file',1
INSERT INTO @OUTPUT
exec @result =xp_cmdshell @cmd2
IF (@result <> 0)
THROW 50000, 'Error copying ldf file',1
END TRY
BEGIN CATCH
SELECT * FROM @OUTPUT WHERE line is not null;
THROW
END CATCH
DECLARE @createDatabaseSql nvarchar(max)
SET @createDatabaseSql = '
CREATE DATABASE '[email protected]+'
ON (FILENAME = '''[email protected]+'''),
(FILENAME = '''[email protected]+''')
FOR ATTACH;'
exec sp_executesql @stmt = @createDatabaseSql
END
GO