2012-09-18 66 views
11

我有一个SQL Server 2008数据库,我想要复制并在服务器上创建一个新的数据库(使用不同的名称)。我不关心维护数据,可以创建新的数据库,但没有数据供初学者使用。我所希望做的是以下几点:复制SQL Server 2008数据库并重新命名它

  • 创建新的数据库维护旧的数据库结构
  • 将新的数据库
  • 更改的名称,将所有varchar和char数据类型为nvarchar和NCHAR
  • 更改所有文本的数据类型为nvarchar(MAX)

顺便说一句,我有2个更多的问题不属于我的任务的一部分,但要考虑以下几点:

  • 我怎样才能升级SQL Server数据库到SQL Server 2012
  • 是否有任何准备工作,我需要进行数据库,以确保我可以很容易地升级呢?

回答

29

这确实是多个问题的组合。


问题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\与您的实际路径。除非我知道这些是什么,否则我无法在答案中得到更具体的答案。


这是一个完整的摄制:

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-B DB-A的副本:

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; 

您可以使用打印输出来验证脚本的第一8K,当你认为它看起来不错,取消对EXEC

一旦完成,您将需要重建所有索引。

这就是说,脚本数据库托尼建议(或使用工具,如Red Gate's SQL Compare - 或one of its many alternatives - 对一个空数据库)很可能将更加容易,特别是当一些列的参与约束 - 这可能需要被删除并重新创建以改变类型。


质询5,6

  • 如何升级SQL Server数据库到SQL Server 2012
  • 是否有任何准备工作,我需要进行数据库来确保我可以轻松升级它吗?

您不能仅升级2008实例上的单个数据库。你要么就地升级,要么设置一个新的实例(如Tony所述),然后迁移你的数据库(最好使用备份/恢复 - 很多人会告诉你要分离/连接,但安全性要低得多)。准备工作你应该做的包括:

,并在升级之后你会想:

  • 将兼容性级别设置为110
  • 更新所有统计信息
+1

总之,beautimus!谢谢。 – MikeMalter

+0

哇...答案! – SFun28

-1

嗯,使用sql server脚本出数据库结构,然后做一个搜索和替换的变化。安装2012并执行脚本。

我不知道2008年的任何东西在2012年都无法使用。如果您的2008 db设置为仍然兼容2000,那么有几个问题,但2008年的脚本应该绕过它们直截了当。

至于升级,我从来没有很多时间进行就地升级,除了其他任何东西都具有破坏性,所以任何隐约理智的人都会完全备份服务器。不要听任何人说不可能出错,以我的经验来看,这意味着你很可能是不幸的人,因为你没有把你的手指压得太紧。

个人我'd安装2012(最好在另一台机器上),并简单地恢复2008年数据的备份。然后设置兼容性级别,修复用户/登录等。

如果你确实要去就地,你不能改变位。即32位2008年到64位2012年。要做到这一点,你首先必须切换到2008年64位,这是另一个更喜欢我的第一个建议的原因。

0

来源为script that copies a database

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) 
相关问题