我有一个 MS SQL Server 2008 Express 系统,其中包含一个我想“复制和重命名”(用于测试目的)的数据库,但我不知道实现此目的的简单方法。
我注意到在 R2 版本的 SQL Server 中有一个复制数据库向导,但遗憾的是我无法升级。
有问题的数据库围绕着一个演出。我试图将要复制到新数据库中的数据库的备份还原,但没有成功。
安装 Microsoft SQL Management Studio,您可以从 Microsoft 网站免费下载: 版本 2008 Microsoft SQL Management Studio 2008 是 SQL Server 2008 Express 的一部分,具有高级服务版本 2012 单击下载按钮并检查 ENU\x64\SQLManagementStudio_x64_ENU.exe 版本 2014 单击下载按钮并检查 MgmtStudio 64BIT\SQLManagementStudio_x64_ENU.exe 打开 Microsoft SQL Management Studio。将原始数据库备份到 .BAK 文件(db -> 任务 -> 备份)。使用新名称(克隆)创建空数据库。请注意下面的注释,因为这是可选的。单击以克隆数据库并打开恢复对话框(见图) 选择设备并添加步骤 3 中的备份文件。将目标更改为测试数据库 更改数据库文件的位置,它必须与原始文件不同。您可以直接在文本框中输入,只需添加后缀。 (注意:顺序很重要。选择复选框,然后更改文件名。)检查 WITH REPLACE 和 WITH KEEP_REPLICATION
右键单击要克隆的数据库,单击 Tasks
,单击 Copy Database...
。按照向导操作,您就完成了。
您可以尝试分离数据库,在命令提示符下将文件复制到新名称,然后附加两个数据库。
在 SQL 中:
USE master;
GO
EXEC sp_detach_db
@dbname = N'OriginalDB';
GO
在命令提示符下(为了这个示例,我简化了文件路径):
copy c:\OriginalDB.mdf c:\NewDB.mdf
copy c:\OriginalDB.ldf c:\NewDB.ldf
再次在 SQL 中:
USE master;
GO
CREATE DATABASE OriginalDB
ON (FILENAME = 'C:\OriginalDB.mdf'),
(FILENAME = 'C:\OriginalDB.ldf')
FOR ATTACH;
GO
CREATE DATABASE NewDB
ON (FILENAME = 'C:\NewDB.mdf'),
(FILENAME = 'C:\NewDB.ldf')
FOR ATTACH;
GO
select * from OriginalDB.sys.sysfiles
查找数据库文件的位置。
.mdf
文件上显示 Permission denied
。我现在不需要它,我只需要原始数据库的备份,所以我以后可以用它覆盖原始数据库,我只是好奇为什么会出现这样的错误。
exec sp_helpdb @dbname='TEMPDB';
事实证明,我曾错误地尝试从备份中恢复。
最初我创建了一个新数据库,然后尝试在此处恢复备份。我应该做的以及最终起作用的是打开恢复对话框并在目标字段中输入新数据库的名称。
所以,简而言之,从备份中恢复就可以了。
感谢所有反馈和建议的家伙
这是我使用的脚本。有点棘手,但它有效。在 SQL Server 2012 上测试。
DECLARE @backupPath nvarchar(400);
DECLARE @sourceDb nvarchar(50);
DECLARE @sourceDb_log nvarchar(50);
DECLARE @destDb nvarchar(50);
DECLARE @destMdf nvarchar(100);
DECLARE @destLdf nvarchar(100);
DECLARE @sqlServerDbFolder nvarchar(100);
SET @sourceDb = 'db1'
SET @sourceDb_log = @sourceDb + '_log'
SET @backupPath = 'E:\DB SQL\MSSQL11.MSSQLSERVER\MSSQL\Backup\' + @sourceDb + '.bak' --ATTENTION: file must already exist and SQL Server must have access to it
SET @sqlServerDbFolder = 'E:\DB SQL\MSSQL11.MSSQLSERVER\MSSQL\DATA\'
SET @destDb = 'db2'
SET @destMdf = @sqlServerDbFolder + @destDb + '.mdf'
SET @destLdf = @sqlServerDbFolder + @destDb + '_log' + '.ldf'
BACKUP DATABASE @sourceDb TO DISK = @backupPath
RESTORE DATABASE @destDb FROM DISK = @backupPath
WITH REPLACE,
MOVE @sourceDb TO @destMdf,
MOVE @sourceDb_log TO @destLdf
SET @sourceDb_log = (SELECT files.name FROM sys.databases dbs INNER JOIN sys.master_files files ON dbs.database_id=files.database_id WHERE dbs.name=@sourceDb AND files.type=1)
和具有类似查询的 @sourceDb_data 的单独变量(替换为 files.type=0
)。 !
Msg 137, Level 15, State 2, Line 25 Must declare the scalar variable "@destDb".
原来我在变量声明及其用法之间放置了 GO
语句,我们不能这样做,请参阅:stackoverflow.com/a/55347161/6184866
'@'
:SET @backupPath = 'E:\tmp\' + @sourceDb + '.bak' --ATTENTION: file must already exist and SQL Server must have access to it.
此外,您可以将备份文件夹设置为:` E:\DB SQL\ MSSQL11.MSSQLSERVER\MSSQL\Backup\ ` 以避免设置安全访问权限。
这里提到的所有解决方案都不适合我——我使用的是 SQL Server Management Studio 2014。
相反,我不得不取消选中“选项”屏幕中的“恢复前进行尾日志备份”复选框:在我的版本中,默认情况下它被选中并阻止完成恢复操作。取消选中后,还原操作继续进行,没有问题。
https://i.stack.imgur.com/Q0N5U.png
使用 MS SQL Server 2012,您需要执行 3 个基本步骤:
首先,生成仅包含源数据库结构的 .sql 文件 右键单击源数据库,然后任务然后生成脚本按照向导并在本地保存 .sql 文件其次,将源数据库替换为 .sql 中的目标数据库文件 右键单击目标文件,选择 New Query 和 Ctrl-H 或(编辑 - 查找和替换 - 快速替换)最后,填充数据 右键单击目标数据库,然后选择任务和导入数据数据源下拉设置为".net framework data provider for SQL server" + 在 DATA ex 下设置连接字符串文本字段:Data Source=Mehdi\SQLEXPRESS;Initial Catalog=db_test;User ID=sa;Password=sqlrpwrd15 对目标执行相同操作检查表您要传输或选中“来源:...”之外的复选框以检查所有这些
你完成了。
来自 SSMS:
- 将原始数据库备份到 .BAK 文件(your_source_db -> 任务 -> 备份)。
2 - 右键单击“数据库”和“恢复数据库”
3 - 设备 > ...(按钮)> 添加 > 选择 your_source_db.bak
4 - 在“常规”选项卡的“目标”部分中,将“数据库”中的 your_source_db 重命名为 new_name_db
5 - 在“文件”选项卡中,勾选“将所有文件重新定位到文件夹”,
在“恢复为”列中重命名两个法线以与 new_name_db (.mdf, _log.ldf) 保持一致
- 在“选项”选项卡的“恢复选项”部分,勾选两个第一个选项(“覆盖...”、“保留...”)和“恢复状态”:“恢复时恢复”
还要确保在“尾日志备份”部分选项未选中,以避免将源数据库保持在“恢复状态”!
https://i.stack.imgur.com/aqpmj.png
如果数据库不是很大,您可以查看 SQL Server Management Studio Express 中的“脚本数据库”命令,这些命令位于资源管理器中数据库项本身的上下文菜单中。
您可以选择要编写的全部内容;当然,您需要对象和数据。然后,您将把整个脚本保存到一个文件中。然后您可以使用该文件重新创建数据库;只需确保顶部的 USE
命令设置为正确的数据库即可。
在 SQL Server 2008 R2 中,将数据库作为文件备份到文件夹中。然后选择出现在“数据库”文件夹中的恢复选项。在向导中,输入您希望在目标数据库中使用的新名称。并选择从文件中恢复并使用您刚刚创建的文件。我只是做到了,而且速度非常快(我的数据库很小,但仍然如此)巴勃罗。
解决方案,基于此评论: https://stackoverflow.com/a/22409447/2399045 。只需设置设置:数据库名称、临时文件夹、数据库文件文件夹。运行后,您将获得名称为“sourceDBName_yyyy-mm-dd”格式的数据库副本。
-- Settings --
-- New DB name will have name = sourceDB_yyyy-mm-dd
declare @sourceDbName nvarchar(50) = 'MyDbName';
declare @tmpFolder nvarchar(50) = 'C:\Temp\'
declare @sqlServerDbFolder nvarchar(100) = 'C:\Databases\'
-- Execution --
declare @sourceDbFile nvarchar(50);
declare @sourceDbFileLog nvarchar(50);
declare @destinationDbName nvarchar(50) = @sourceDbName + '_' + (select convert(varchar(10),getdate(), 121))
declare @backupPath nvarchar(400) = @tmpFolder + @destinationDbName + '.bak'
declare @destMdf nvarchar(100) = @sqlServerDbFolder + @destinationDbName + '.mdf'
declare @destLdf nvarchar(100) = @sqlServerDbFolder + @destinationDbName + '_log' + '.ldf'
SET @sourceDbFile = (SELECT top 1 files.name
FROM sys.databases dbs
INNER JOIN sys.master_files files
ON dbs.database_id = files.database_id
WHERE dbs.name = @sourceDbName
AND files.[type] = 0)
SET @sourceDbFileLog = (SELECT top 1 files.name
FROM sys.databases dbs
INNER JOIN sys.master_files files
ON dbs.database_id = files.database_id
WHERE dbs.name = @sourceDbName
AND files.[type] = 1)
BACKUP DATABASE @sourceDbName TO DISK = @backupPath
RESTORE DATABASE @destinationDbName FROM DISK = @backupPath
WITH REPLACE,
MOVE @sourceDbFile TO @destMdf,
MOVE @sourceDbFileLog TO @destLdf
DECLARE @DynamicSQL [nvarchar](2000);
SET @DynamicSQL = CONCAT('ALTER DATABASE [', @DestinationDBName, '] MODIFY FILE (NAME = ''', @SourceDBName, ''', NEWNAME = ''', @DestinationDBName, ''');');
SET @DynamicSQL = CONCAT(@DynamicSQL, 'ALTER DATABASE [', @DestinationDBName, '] MODIFY FILE (NAME = ''', CONCAT(@SourceDBName, '_log'), ''', NEWNAME = ''', CONCAT(@DestinationDBName, '_log'), ''');');
EXECUTE (@DynamicSQL);
基于 Joe 回答的脚本(分离、复制文件、附加两者)。
以管理员帐户运行管理工作室。
这不是必需的,但可能在执行时访问被拒绝错误。
配置 sql server 以执行 xp_cmdshel
EXEC sp_configure 'show advanced options', 1
GO
RECONFIGURE
GO
EXEC sp_configure 'xp_cmdshell', 1
GO
RECONFIGURE
GO
运行脚本,但之前在 @dbName 和 @copyDBName 变量中输入您的数据库名称。
USE master;
GO
DECLARE @dbName NVARCHAR(255) = 'Products'
DECLARE @copyDBName NVARCHAR(255) = 'Products_branch'
-- get DB files
CREATE TABLE ##DBFileNames([FileName] NVARCHAR(255))
EXEC('
INSERT INTO ##DBFileNames([FileName])
SELECT [filename] FROM ' + @dbName + '.sys.sysfiles')
-- drop connections
EXEC('ALTER DATABASE ' + @dbName + ' SET OFFLINE WITH ROLLBACK IMMEDIATE')
EXEC('ALTER DATABASE ' + @dbName + ' SET SINGLE_USER')
-- detach
EXEC('EXEC sp_detach_db @dbname = ''' + @dbName + '''')
-- copy files
DECLARE @filename NVARCHAR(255), @path NVARCHAR(255), @ext NVARCHAR(255), @copyFileName NVARCHAR(255), @command NVARCHAR(MAX) = ''
DECLARE
@oldAttachCommand NVARCHAR(MAX) =
'CREATE DATABASE ' + @dbName + ' ON ',
@newAttachCommand NVARCHAR(MAX) =
'CREATE DATABASE ' + @copyDBName + ' ON '
DECLARE curs CURSOR FOR
SELECT [filename] FROM ##DBFileNames
OPEN curs
FETCH NEXT FROM curs INTO @filename
WHILE @@FETCH_STATUS = 0
BEGIN
SET @path = REVERSE(RIGHT(REVERSE(@filename),(LEN(@filename)-CHARINDEX('\', REVERSE(@filename),1))+1))
SET @ext = RIGHT(@filename,4)
SET @copyFileName = @path + @copyDBName + @ext
SET @command = 'EXEC master..xp_cmdshell ''COPY "' + @filename + '" "' + @copyFileName + '"'''
PRINT @command
EXEC(@command);
SET @oldAttachCommand = @oldAttachCommand + '(FILENAME = "' + @filename + '"),'
SET @newAttachCommand = @newAttachCommand + '(FILENAME = "' + @copyFileName + '"),'
FETCH NEXT FROM curs INTO @filename
END
CLOSE curs
DEALLOCATE curs
-- attach
SET @oldAttachCommand = LEFT(@oldAttachCommand, LEN(@oldAttachCommand) - 1) + ' FOR ATTACH'
SET @newAttachCommand = LEFT(@newAttachCommand, LEN(@newAttachCommand) - 1) + ' FOR ATTACH'
-- attach old db
PRINT @oldAttachCommand
EXEC(@oldAttachCommand)
-- attach copy db
PRINT @newAttachCommand
EXEC(@newAttachCommand)
DROP TABLE ##DBFileNames
另一种使用导入/导出向导来解决问题的方法是,首先创建一个空数据库,然后选择源数据库作为您的服务器的源,然后在目标中选择与目标数据库相同的服务器(使用空数据库您首先创建),然后点击完成
它将创建所有表并将所有数据传输到新数据库中,
您可以只创建一个新数据库,然后转到任务,导入数据,然后将要复制的数据库中的所有数据导入刚刚创建的数据库。
该程序以不同的名称将数据库复制到同一台服务器。我依靠这个网站上给出的例子进行了一些改进。
-- Copies a database to the same server
-- Copying the database is based on backing up the original database and restoring with a different name
DECLARE @sourceDb nvarchar(50);
DECLARE @destDb nvarchar(50);
DECLARE @backupTempDir nvarchar(200)
SET @sourceDb = N'Northwind' -- The name of the source database
SET @destDb = N'Northwind_copy' -- The name of the target database
SET @backupTempDir = N'c:\temp' -- The name of the temporary directory in which the temporary backup file will be saved
-- --------- ---
DECLARE @sourceDb_ROWS nvarchar(50);
DECLARE @sourceDb_LOG nvarchar(50);
DECLARE @backupPath nvarchar(400);
DECLARE @destMdf nvarchar(100);
DECLARE @destLdf nvarchar(100);
DECLARE @sqlServerDbFolder nvarchar(100);
Declare @Ret as int = -1
Declare @RetDescription nvarchar(200) = ''
-- Temporary backup file name
SET @backupPath = @backupTempDir+ '\TempDb_' + @sourceDb + '.bak'
-- Finds the physical location of the files on the disk
set @sqlServerDbFolder = (SELECT top(1) physical_name as dir
FROM sys.master_files where DB_NAME(database_id) = @sourceDb );
-- Clears the file name and leaves the directory name
set @sqlServerDbFolder = REVERSE(SUBSTRING(REVERSE(@sqlServerDbFolder), CHARINDEX('\', REVERSE(@sqlServerDbFolder)) + 1, LEN(@sqlServerDbFolder))) + '\'
-- Finds the logical name for the .mdf file
set @sourceDb_ROWS = (SELECT f.name LogicalName FROM sys.master_files f INNER JOIN sys.databases d ON d.database_id = f.database_id
where d.name = @sourceDb and f.type_desc = 'ROWS' )
-- Finds the logical name for the .ldf file
set @sourceDb_LOG = (SELECT f.name LogicalName FROM sys.master_files f INNER JOIN sys.databases d ON d.database_id = f.database_id
where d.name = @sourceDb and f.type_desc = 'LOG' )
-- Composes the names of the physical files for the new database
SET @destMdf = @sqlServerDbFolder + @destDb + N'.mdf'
SET @destLdf = @sqlServerDbFolder + @destDb + N'_log' + N'.ldf'
-- If the source name is the same as the target name does not perform the operation
if @sourceDb <> @destDb
begin
-- Checks if the target database already exists
IF Not EXISTS (SELECT name FROM master.dbo.sysdatabases WHERE name = @destDb)
begin
-- Checks if the source database exists
IF EXISTS (SELECT name FROM master.dbo.sysdatabases WHERE name = @sourceDb) and (@sqlServerDbFolder is not null)
begin
-- Opens the permission to run xp_cmdshell
EXEC master.dbo.sp_configure 'show advanced options', 1
RECONFIGURE WITH OVERRIDE
EXEC master.dbo.sp_configure 'xp_cmdshell', 1
RECONFIGURE WITH OVERRIDE
-- If the temporary backup directory does not exist it creates it
declare @md as nvarchar(100) = N'if not exist ' + @backupTempDir + N' md ' +@backupTempDir
exec xp_cmdshell @md, no_output
-- Creates a backup to the source database to the temporary file
BACKUP DATABASE @sourceDb TO DISK = @backupPath
-- Restores the database with a new name
RESTORE DATABASE @destDb FROM DISK = @backupPath
WITH REPLACE,
MOVE @sourceDb_ROWS TO @destMdf,
MOVE @sourceDb_LOG TO @destLdf
-- Deletes the temporary backup file
declare @del as varchar(100) = 'if exist ' + @backupPath +' del ' +@backupPath
exec xp_cmdshell @del , no_output
-- Close the permission to run xp_cmdshell
EXEC master.dbo.sp_configure 'xp_cmdshell', 0
RECONFIGURE WITH OVERRIDE
EXEC master.dbo.sp_configure 'show advanced options', 0
RECONFIGURE WITH OVERRIDE
set @ret = 1
set @RetDescription = 'The ' +@sourceDb + ' database was successfully copied to ' + @destDb
end
else
begin
set @RetDescription = 'The source database '''+ @sourceDb + ''' is not exists.'
set @ret = -3
end
end
else
begin
set @RetDescription = 'The target database '''+ @destDb + ''' already exists.'
set @ret = -4
end
end
else
begin
set @RetDescription = 'The target database ''' +@destDb + ''' and the source database '''+ @sourceDb + ''' have the same name.'
set @ret = -5
end
select @ret as Ret, @RetDescription as RetDescription
<head>
<title>Copy Database</title>
</head>
<body>
<?php
$servername = "localhost:xxxx";
$user1 = "user1";
$pw1 = "pw1";
$db1 = "db1";
$conn1 = new mysqli($servername,$user1,$pw1,$db1);
if($conn1->connect_error) {
die("Conn1 failed: " . $conn1->connect_error);
}
$user2 = "user2";
$pw2 = "pw2";
$db2 = "db2";
$conn2 = new mysqli($servername,$user2,$pw2,$db2);
if($conn2->connect_error) {
die("Conn2 failed: " . $conn2->connect_error);
}
$sqlDB1 = "SELECT * FROM table1";
$resultDB1 = $conn1->query($sqlDB1);
if($resultDB1->num_rows > 0) {
while($row = $resultDB1->fetch_assoc()) {
$sqlDB2 = "INSERT INTO table2 (col1, col2) VALUES ('" . $row["tableRow1"] . "','" . $row["tableRow2"] . "')";
$resultDB2 = $conn2->query($sqlDB2);
}
}else{
echo "0 results";
}
$conn1->close();
$conn2->close();
?>
</body>
how to ask good question
部分stackoverflow.com/help/how-to-ask,您可以在此处获得导览并赠送一枚徽章stackoverflow.com/tour
不定期副业成功案例分享