sql - 复制 SQL Server 2008 数据库并重命名

标签 sql database sql-server-2008 sql-server-2012

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

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

顺便说一句,我还有 2 个问题,这些问题不属于我的任务,但我想考虑以下问题:

  • 如何将sql server数据库升级到sql server 2012
  • 是否需要对数据库执行任何准备工作以确保可以轻松升级它?

最佳答案

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


问题 1 和 2

  • Create the new database maintaining structure of old database
  • Set the name of the new database

最简单的备份命令是:

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 folder C:\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

  • Change all varchar and char datatypes to nvarchar and nchar
  • Change all text datatypes to 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's SQL Compare 之类的工具 - 或 one of its many alternatives - 针对空数据库)可能会容易得多,特别是如果其中一些列参与约束 - 这可能需要删除并重新创建才能更改类型。


问题 5 和 6

  • How can I upgrade the sql server database to sql server 2012
  • Is there any preparatory work I need to carry out on the database to ensure I can easily upgrade it?

您不能只升级 2008 实例上的单个数据库。您要么就地升级,要么设置一个新实例(如 Tony 所述),然后迁移您的数据库(最好使用备份/恢复——许多人会告诉您分离/附加,但这远不安全)。您应该做的准备工作包括:

升级后您需要:

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

关于sql - 复制 SQL Server 2008 数据库并重命名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12485966/

相关文章:

mysql - 在 SQL Select 上将 YYYYMMDD 日期格式化为文本

java - java中查询数据库最快的方法

sql - 删除SQL Server 2008中所有非系统对象的脚本

sql - MySQL - 如何在列内随机排列结果?

sql - 如何在删除命令上添加条件?

sql - 在 Liquibase 中可以在 splitstatements 上有一个空行吗?

sql - 按半年计算金额

sql - 为什么这个触发器不好?

database - 未知参数 "includeObjects"在命令行 liquiBase 中引发异常

sql - 如果数据保持不变,有没有办法为同一个 SQL 查询获得不同的结果?