簡體   English   中英

復制SQL Server 2008數據庫並重命名

[英]copy a SQL Server 2008 database and rename it

我有一個SQL Server 2008數據庫,我想復制並在服務器上創建一個新的數據庫(使用不同的名稱)。 我不關心維護數據,可以創建沒有數據的新數據庫。 我要做的是以下內容:

  • 創建舊數據庫的新數據庫維護結構
  • 設置新數據庫的名稱
  • 將所有varchar和char數據類型更改為nvarchar和nchar
  • 將所有文本數據類型更改為nvarchar(MAX)

順便說一句,我還有兩個問題不屬於我的任務,但我想考慮以下問題:

  • 如何將sql server數據庫升級到sql server 2012
  • 我需要在數據庫上進行任何准備工作,以確保我可以輕松升級它嗎?

這確實是多個問題的組合。


問題1和2

  • 創建舊數據庫的新數據庫維護結構
  • 設置新數據庫的名稱

最簡單的備份命令是:

BACKUP DATABASE dbname TO DISK = 'C:\some folder\dbname.bak' WITH INIT;
-- or WITH INIT, COMPRESSION if you are on Enterprise or Developer

現在要將其恢復為另一個數據庫,您需要知道文件名,因為它會嘗試將相同的文件放在同一個地方。 因此,如果您運行以下內容:

EXEC dbname.dbo.sp_helpfile;

您應該看到包含數據和日志文件的名稱和路徑的輸出。 構建還原時,您需要使用這些,但是將路徑替換為新數據庫的名稱,例如:

RESTORE DATABASE newname FROM DISK = 'C:\some folder\dbname.bak'
  WITH MOVE 'dbname' TO 'C:\path_from_sp_helpfile_output\newname_data.mdf',
  MOVE 'dbname_log' TO 'C:\path_from_sp_helpfile_output\newname_log.ldf';

您必須將dbnamenewname替換為您的實際數據庫名稱,並將C:\\some folderC:\\path_from_sp_helpfile_output\\替換為您的實際路徑。 除非我知道那些是什么,否則我無法在答案中得到更具體的解釋。


這是一個完整的repro:

CREATE DATABASE [DB-A];
GO

EXEC [DB-A].dbo.sp_helpfile;

部分結果:

name     fileid filename
-------- ------ ---------------------------------
DB-A     1      C:\Program Files\...\DB-A.mdf
DB-A_log 2      C:\Program Files\...\DB-A_log.ldf

現在我運行備份:

BACKUP DATABASE [DB-A] TO DISK = 'C:\dev\DB-A.bak' WITH INIT;

當然,如果克隆目標(在本例中為DB-B )已經存在,您將要刪除它:

USE [master];
GO
IF DB_ID('DB-B') IS NOT NULL
BEGIN
  ALTER DATABASE [DB-B] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
  DROP DATABASE [DB-B];
END
GO

現在,此還原將成功運行,為您提供DB-A的副本,重命名為DB-B:

RESTORE DATABASE [DB-B] FROM DISK = 'C:\dev\DB-A.bak'
  WITH MOVE 'DB-A'     TO 'C:\Program Files\...\DB-B.mdf',
       MOVE 'DB-A_log' TO 'C:\Program Files\...\DB-B_log.ldf';

問題3和4

  • 將所有varchar和char數據類型更改為nvarchar和nchar
  • 將所有文本數據類型更改為nvarchar(MAX)

重構是一個主要的痛苦,特別是如果這些列中的一些參與約束。 您可以通過這種方式構建一個非常基本的腳本,但是您需要更多的工業強度來處理所有這些變量。 這假設所有列都可以為空並且不參與約束。

DECLARE @sql NVARCHAR(MAX) = N'';

SELECT @sql += '
  ALTER TABLE ' + 
  QUOTENAME(OBJECT_SCHEMA_NAME(c.[object_id])) 
  + '.' + QUOTENAME(OBJECT_NAME(c.[object_id]))
  + ' ALTER COLUMN ' + QUOTENAME(c.name) + ' '
  + CASE t.name WHEN N'text' 
     THEN N'nvarchar(max)' 
     ELSE N'n' + t.name + '(' + RTRIM(c.max_length) + ')'
  END + ';'
FROM sys.columns AS c
INNER JOIN sys.types AS t
ON c.user_type_id = t.user_type_id
WHERE c.system_type_id IN (35, 167, 175)
AND OBJECTPROPERTY(c.[object_id], 'IsMsShipped') = 0;

PRINT @sql;
-- EXEC sp_executesql @sql;

您可以使用PRINT輸出來驗證腳本的前8K,當您認為它看起來不錯時,取消注釋EXEC

完成后,您將需要重建所有索引。

也就是說,像Tony建議的那樣編寫數據庫(或使用Red Gate的SQL Compare之類的工具 - 或其中一個替代方案 - 針對空數據庫)可能要容易得多,特別是如果其中一些列參與約束 -可能需要刪除並重新創建才能更改類型。


問題5和6

  • 如何將sql server數據庫升級到sql server 2012
  • 我需要在數據庫上進行任何准備工作,以確保我可以輕松升級它嗎?

您無法僅在2008實例上升級單個數據庫。 您要么就地升級,要么設置一個新實例(如Tony描述的那樣),然后遷移您的數據庫(最好使用備份/恢復 - 很多人會告訴您分離/附加,但這樣安全性要差得多)。 你應該做的准備工作包括:

升級后,您需要:

  • 將兼容級別設置為110
  • 更新所有統計信息

復制數據庫腳本的源。

USE master;

DECLARE
    @SourceDatabaseName AS SYSNAME = '<SourceDB>', 
    @TargetDatabaseName AS SYSNAME = '<TargetDB>'



-- ============================================
-- Define path where backup will be saved
-- ============================================
IF NOT EXISTS (SELECT 1 FROM sys.databases WHERE name = @SourceDatabaseName)
    RAISERROR ('Variable @SourceDatabaseName is not set correctly !', 20, 1) WITH LOG       

DECLARE @SourceBackupFilePath varchar(2000)
SELECT @SourceBackupFilePath = BMF.physical_device_name
FROM
    msdb.dbo.backupset B
    JOIN msdb.dbo.backupmediafamily BMF ON B.media_set_id = BMF.media_set_id
WHERE B.database_name = @SourceDatabaseName
ORDER BY B.backup_finish_date DESC

SET @SourceBackupFilePath = REPLACE(@SourceBackupFilePath, '.bak', '_clone.bak')

IF @SourceBackupFilePath IS NULL
        RAISERROR ('Could not determine file path for backup file!', 16, 1) WITH LOG



-- ============================================
-- Backup source database
-- ============================================
DECLARE @Sql NVARCHAR(MAX) 
SET @Sql = 'BACKUP DATABASE @SourceDatabaseName TO DISK = ''@SourceBackupFilePath'''
SET @Sql = REPLACE(@Sql, '@SourceDatabaseName', @SourceDatabaseName)
SET @Sql = REPLACE(@Sql, '@SourceBackupFilePath', @SourceBackupFilePath)
SELECT 'Performing backup...', @Sql as ExecutedSql
EXEC (@Sql)



-- ============================================
-- Automatically compose database files (.mdf and .ldf) paths
-- ============================================
DECLARE
          @LogicalDataFileName as NVARCHAR(MAX)
        , @LogicalLogFileName as NVARCHAR(MAX)
        , @TargetDataFilePath as NVARCHAR(MAX)
        , @TargetLogFilePath as NVARCHAR(MAX)

SELECT
        @LogicalDataFileName = name,
        @TargetDataFilePath = SUBSTRING(physical_name,1,LEN(physical_name)-CHARINDEX('\',REVERSE(physical_name))) + '\' + @TargetDatabaseName + '.mdf'
FROM sys.master_files
WHERE
        database_id = DB_ID(@SourceDatabaseName)        
        AND type = 0            -- datafile file

SELECT
        @LogicalLogFileName = name,
        @TargetLogFilePath = SUBSTRING(physical_name,1,LEN(physical_name)-CHARINDEX('\',REVERSE(physical_name))) + '\' + @TargetDatabaseName + '.ldf'
FROM sys.master_files
WHERE
        database_id = DB_ID(@SourceDatabaseName)        
        AND type = 1            -- log file     

SELECT  
    @LogicalDataFileName as LogicalDataFileName,
    @LogicalLogFileName as LogicalLogFileName,
    @TargetDataFilePath as TargetDataFilePath,
    @TargetLogFilePath as TargetLogFilePath                

IF @TargetDataFilePath IS NULL OR @TargetLogFilePath IS NULL
    RAISERROR ('Could not determine target paths!', 16, 1) WITH LOG



-- ============================================
-- Restore target database
-- ============================================
IF EXISTS (SELECT 1 FROM sys.databases WHERE name = @TargetDatabaseName)
    RAISERROR ('A database with the same name already exists!', 20, 1) WITH LOG        

SET @Sql = 'RESTORE DATABASE @TargetDatabaseName
FROM DISK = ''@SourceBackupFilePath'' 
WITH MOVE ''@LogicalDataFileName'' TO ''@TargetDataFilePath'',
MOVE ''@LogicalLogFileName'' TO ''@TargetLogFilePath''' 
SET @Sql = REPLACE(@Sql, '@TargetDatabaseName', @TargetDatabaseName)
SET @Sql = REPLACE(@Sql, '@SourceBackupFilePath', @SourceBackupFilePath)
SET @Sql = REPLACE(@Sql, '@LogicalDataFileName', @LogicalDataFileName)
SET @Sql = REPLACE(@Sql, '@TargetDataFilePath', @TargetDataFilePath)
SET @Sql = REPLACE(@Sql, '@LogicalLogFileName', @LogicalLogFileName)
SET @Sql = REPLACE(@Sql, '@TargetLogFilePath', @TargetLogFilePath)
SELECT 'Restoring...', @Sql as ExecutedSql
EXEC (@Sql)

嗯使用sql server腳本化數據庫結構,然后搜索並替換更改。 安裝2012並執行腳本。

我不知道2008年的任何東西在2012年都無法運行。如果你的2008 db被設置為仍然兼容2000,那么有一些問題,但是2008年的腳本應該直接解決它們。

至於升級,我從來沒有花很多時間進行內部升級,除了其他任何破壞性的東西,所以任何模糊不清的人都會對服務器進行完整的備份。 不要聽那些說不太可能出錯的人,根據我的經驗,這意味着你很可能成為一個不幸的人,因為你沒有把手伸得太緊。

我個人會安裝2012(最好是在另一台機器上)並簡單地恢復2008數據的備份。 然后設置compatitibility級別,修復用戶/登錄等。

如果你去的地方,你不能改變位數。 即32位2008至64位2012.要做到這一點,你首先必須切換到2008 64位,這是我更喜歡我的第一個建議的另一個原因。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM