I've been trying to make a copy of a SQL Server Database (2014) and the recommended way to do this using SQL Server Management Studio seems to be the following.
Right Click Database >
Tasks >
Generate Scripts >
Advanced (Schema and Data) (Single file per object)
Then I have to update the references to the database name to use the new database name.
This won't work for me though because some of the object files it outputs can be over a GB which means I can't open the file to change the database name.
Is there another way to create a copy of a database to a new database with a different name?
I use this script for that.
declare #nameSuffix varchar(50) = 'DB_NEW_NAME'
declare #path varchar(250) = 'C:\Program Files\Microsoft SQL Server\YOUR PATH\MSSQL\'
declare #backupfile varchar(250) = #path + 'Backup\' + #nameSuffix + '.bak'
declare #moveFile varchar(300) = #path + 'DATA\' + #nameSuffix + '.mdf'
declare #moveLogFile varchar(300) = #path + 'DATA\' + #nameSuffix + '_log.ldf'
backup database DB1
to disk = #backupfile
with init, noformat, skip, stats=10
use master
restore database DB_NEW_NAME
from disk = #backupfile
with replace,
recovery,
move 'DB1' to #moveFile,
move 'DB1_Log' to #moveLogFile
you can copy the database by:
right click database to be copied > tasks > copy database
the database wizard will guide you to create your new copy.
more resources here: https://msdn.microsoft.com/en-us/library/ms188664.aspx
Related
I am having a issue for restoring a partitioned database using the below script.
I have 7 partitions in the database.
here is the code .
declare #Sql varchar(max)
SET #Sql = 'RESTORE DATABASE [NEWS]
FILE = ''DEMO'',
FILEGROUP = ''DEMO''
FROM DISK = ''C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Backup\DEMO_clone.bak
WITH FILE = 1, NOUNLOAD, REPLACE, STATS = 10
GO
RESTORE LOG [NEWS]
FROM DISK = ''C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Backup\DEMO_clone.bak''
WITH RECOVERY
GO'''
EXEC (#Sql)
Its showing the error as incorrect syntax near '\'.
Anyone knows what is the issue is ?
GO is not a T-SQL command so you can't include it in a dynamic SQL script. GO is a batch separator interpreted by SQL Server client tools.
There is no need for the GO batch separators or dynamic SQL in here so I'm guessing the SQL in your question is actually built dynamically. There are also some other errors like misplaced quotes in your code. Below is the corrected version. I think you may need to add NORECOVERY to the RESTORE DATABASE too:
SET #Sql = 'RESTORE DATABASE [NEWS]
FILE = ''DEMO'',
FILEGROUP = ''DEMO''
FROM DISK = ''C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Backup\DEMO_clone.bak''
WITH FILE = 1, NOUNLOAD, REPLACE, STATS = 10;
RESTORE LOG [NEWS]
FROM DISK = ''C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\Backup\DEMO_clone.bak'';
';
I have database in SQL Server Managment Studio. I make a backup of my database using this script:
use mydatabase
BACKUP DATABASE mydatabase
TO DISK = 'D:\mydatabase\backup.BAK'
GO
BACKUP DATABASE mydatabase
TO DISK = 'E:\mydatabase\work.BAK'
GO
My problem is that the files backup.BAK and work.BAK have the same size. I check every byte and this files are not the same. Did anyone know why?
Depending on the size of your database, it may take a while to generate the backup. Depending on the activity, a lot can change in the database during this time. To create exact copies of your backup file, you should just copy the first backup file. You can do this in SQL, for example:
DECLARE #SourceFile AS VARCHAR(500);
DECLARE #DestinationFile AS VARCHAR(500);
DECLARE #Cmd AS VARCHAR(500);
BACKUP DATABASE mydatabase
TO DISK = 'D:\mydatabase\backup.BAK'
GO
SET #SourceFile = 'D:\mydatabase\backup.BAK'
SET #DestinationFile = 'E:\mydatabase\work.BAK'
SET #Cmd = 'COPY ' + #SourceFile + ' ' + #DestinationFile;
EXEC master.dbo.xp_cmdshell #Cmd;
I want to copy a database A into database B (same SQL Server) entirely - what would be the easiest SQL or utility command to do that? (database B should be 100% erased before the copy)
Note that it can be non-SQL thing, but in any case I need to run it as one-click. So some utility that does that is also acceptable as far as I can run copying with one click or from command line.
SQL Server 2008R2 or 2012.
Best, Askar
I made a soultion based on David's thoughts. It looks like this (Prod - source DB, Demo - destination copy)
DECLARE #backup varchar(300) = 'e:\Prod.bak';
DECLARE #logic_db_file varchar(300) = 'koe';
DECLARE #logic_log_file varchar(300) = 'koe_log';
DECLARE #out_db_file varchar(300) = 'c:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS\MSSQL\DATA\Demo.mdf';
DECLARE #out_log_file varchar(300) = 'c:\Program Files\Microsoft SQL Server\MSSQL11.SQLEXPRESS\MSSQL\DATA\Demo_log.ldf';
PRINT N'Backing up Production database.'
BACKUP DATABASE Prod
TO DISK = #backup WITH FORMAT;
PRINT N'Restoring FILELISTONLY, see log file for data.'
-- Restore the files to Demo
RESTORE FILELISTONLY
FROM DISK = #backup
PRINT N'Getting exclusive access to Demo'
Alter database Demo set single_user with rollback immediate
drop database Demo
PRINT N'Restoring backup to Test database'
RESTORE DATABASE Demo
FROM DISK = #backup
WITH REPLACE,
MOVE #logic_db_file TO #out_db_file,
MOVE #logic_log_file TO #out_log_file
GO
-- if you want you can do some SQL fixes to newly made DB
PRINT N'Changing normal users to demo users, if account type is OK'
USE Demo;
UPDATE USER_ACCOUNTS SET ACCOUNT_TYPE=3 WHERE (STATUS=1) AND (ACCOUNT_TYPE=1);
GO
I have used tsql to detach a database like this:
EXEC sp_detach_db #dbname = 'my_db'
I then made use of PHP to rename the physical files. I was able to rename the mdf file but not the ldf file! I even tried a dos command REN but that didn't work for the ldf file either!
I wanted to ask, is there something special about the physical log files that allow it not to be renamed?
Is there a better way of doing this?
Thanks all
Detach the Database, Rename the files, Attach it again.
Backup the original database
Drop the original database
Restore the original database from the backup, but with different name; the files of the restored database will be also automatically named taking into account new database name.
The "ALTER DATABASE (your database) MODIFY FILE" command will only rename the logical names. This post shows how to use xp_cmdshell to also rename the physical files: http://www.mssqltips.com/sqlservertip/1891/best-practice-for-renaming-a-sql-server-database/
Please note the following:
1. xp_cmdshell will be executed under the user which the SQL Server process runs as, and might not have the file system permissions required to rename the database files
2. For security reasons, remember to disable xp_xmdshell
The following is an example of how the renaming can be done based on the mentioned blog post. It will replace the database MyDB with the database NewMyDB. The original MyDB (renamed to MyDB_OLD) will be left detached.
-- Enable xp_cmdshell:
sp_configure 'show advanced options', 1
RECONFIGURE WITH OVERRIDE
GO
sp_configure 'xp_cmdshell', 1
RECONFIGURE WITH OVERRIDE
GO
-- Get physical file names:
declare #MyDBOriginalFileName nvarchar(300) = (select physical_name FROM sys.master_files where name = 'MyDB')
declare #MyDBLogOriginalFileName nvarchar(300) = (select physical_name FROM sys.master_files where name = 'MyDB_log')
declare #NewMyDBOriginalFileName nvarchar(300) = (select physical_name FROM sys.master_files where name = 'NewMyDB')
declare #NewMyDBLogOriginalFileName nvarchar(300) = (select physical_name FROM sys.master_files where name = 'NewMyDB_log')
declare #Command nvarchar(500)
declare #Sql nvarchar(2000)
IF (EXISTS (select * from sys.databases where name = 'NewMyDB')
AND EXISTS (select * from sys.databases where name = 'MyDB'))
BEGIN
USE master
ALTER DATABASE MyDB SET SINGLE_USER WITH ROLLBACK IMMEDIATE
ALTER DATABASE NewMyDB SET SINGLE_USER WITH ROLLBACK IMMEDIATE
-- Set new database name
ALTER DATABASE MyDB MODIFY NAME = MyDB_OLD
ALTER DATABASE NewMyDB MODIFY NAME = MyDB
-- Update logical names
ALTER DATABASE MyDB_OLD MODIFY FILE (NAME=N'MyDB', NEWNAME=N'MyDB_OLD')
ALTER DATABASE [MyDB] MODIFY FILE (NAME=N'NewMyDB', NEWNAME=N'MyDB')
EXEC master.dbo.sp_detach_db #dbname = N'MyDB_Old'
EXEC master.dbo.sp_detach_db #dbname = N'MyDB'
-- Rename physical files
SET #Command = 'RENAME "' + #MyDBOriginalFileName + '" "MyDB_OLD.mdf"'; PRINT #Command
EXEC xp_cmdshell #Command
SET #Command = 'RENAME "' + #MyDBLogOriginalFileName + '" "MyDB_OLD_log.mdf"'; PRINT #Command
EXEC xp_cmdshell #Command
SET #Command = 'RENAME "' + #NewMyDBOriginalFileName + '" "MyDB.mdf"'; PRINT #Command
EXEC xp_cmdshell #Command
SET #Command = 'RENAME "' + #NewMyDBLogOriginalFileName + '" "MyDB_log.mdf"'; PRINT #Command
EXEC xp_cmdshell #Command
-- Attach with new file names
declare #NewMyDBFileNameAfterRename nvarchar(300) = replace(#NewMyDBOriginalFileName, 'NewMyDB', 'MyDB')
declare #NewMyDBLogFileNameAfterRename nvarchar(300) = replace(#NewMyDBOriginalFileName, 'NewMyDB_log', 'MyDB_log')
SET #Sql = 'CREATE DATABASE MyDB ON ( FILENAME = ''' + #NewMyDBFileNameAfterRename + '''), ( FILENAME = ''' + #NewMyDBLogFileNameAfterRename + ''') FOR ATTACH'
PRINT #Sql
EXEC (#Sql)
ALTER DATABASE MyDB SET MULTI_USER
END
-- Disable xp_cmdshell for security reasons:
GO
sp_configure 'show advanced options', 1
RECONFIGURE WITH OVERRIDE
GO
sp_configure 'xp_cmdshell', 0
RECONFIGURE WITH OVERRIDE
GO
You can do it using an ALTER DATABASE statement - like this:
ALTER DATABASE database_name
MODIFY FILE ( NAME = logical_file_name,
FILENAME = ' new_path/os_file_name_with_extension ' )
You need to modify each file separately, e.g. if you have multiple data files, you need to modify each of those.
For details, see the Technet documentation on this topic.
The simplest way to rename SQL server physical database files is:
Open and connect to the SQL server where the database you wanted to rename is located.
Execute the following script in the query window in order to change the physical and logical names. Remember to replace all the "OldDatabaseName" with the new name of the database ("NewDatabaseName") you want to change its name to. Replace all NewDatabaseName with the new name you want to set for your database
use OldDatabaseName
ALTER DATABASE OldDabaseName MODIFY FILE (NAME='OldDatabaseName', FILENAME='C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA\NewDatabaseName.mdf');
ALTER DATABASE OldDatabaseName MODIFY FILE (NAME='OldDatabaseName_log', FILENAME='C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA\NewDatabaseName_log.ldf');
ALTER DATABASE OldDatabaseName MODIFY FILE (NAME = OldDatabaseName, NEWNAME = NewDatabaseName);
ALTER DATABASE OldDatabaseName MODIFY FILE (NAME = OldDatabaseName_log, NEWNAME = NewDatabaseName_log);
And then Right click on the OldDatabaseName, select Tasks and then choose Take Offline
Go to the location (C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\DATA\...) where the physical files are located and rename them to the NewDatabaseName you specified in number 2. Remember to check the absolute path of these files to be used on your computer.
Go back to Microsoft SQL Server Management Studio. Right click on the OldDatabaseName, select Tasks and then choose Bring Online.
Finally, go ahead and rename your OldDatabaseName to the NewDatabaseName. You are done :-)
Detach (right click on database)
Rename both files (ldf and mdf) :
C:\Program Files\Microsoft SQL Server\MSSQL15.MSSQLSERVER\MSSQL\DATA
Attach (right click on "Databases" top folder)
I have a SQL database that I am currently converting from an Access database. One of the features of the Access database is to 'Copy DB' and is used when working in a 'dev' site - it copies all of the production data by physically copying the production file into the dev site. In this way, all production data and structure and queries and everything is duplicated into the dev version. This only needs to be done occasionally when we are testing why something is occurring and we don't want to play in production data; not rare, but not frequent either - perhaps once or twice a month. I'm wondering what have other people done to accomplish this when working in SQL?
I'm thinking that I could do a DB backup followed by a restore to the DEV version, but I don't want this backup to interfere with normal backup processes. Is there any way to do this from one DB straight to another instead of going to the file system, and have the backup seem like it never happened (i.e. the REAL backup will still back up all items that really needed to be backed up)?
What other options are there? I have SQL Compare and SQL Data Compare from Red Gate, but I need to expose this functionality to certain users (with high privs and access to the DEV site), and they don't have it.
Ok well after looking around a bit, I've come to the conclusion that I do have to go thru the file system, but there is a way to do a backup/restore without affecting the normal backup process by using 'Copy Only' mode. Here's script to do it:
BACKUP DATABASE [ProductionDB]
TO DISK = N'D:\ProductionDBToDevTransfer.bak'
WITH
COPY_ONLY,
NOFORMAT,
INIT,
NAME = N'DB-Full Backup',
SKIP,
NOREWIND,
NOUNLOAD,
STATS = 10
RESTORE DATABASE [DevDB]
FROM DISK = N'D:\ProductionDBToDevTransfer.bak'
WITH
FILE = 1,
MOVE N'ProductionDB' TO N'D:\Microsoft\SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\DevDB.mdf',
MOVE N'ProductionDB_log' TO N'D:\Microsoft\SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\DevDB_log.ldf',
NOUNLOAD,
REPLACE,
STATS = 10
Take particular note of the MOVE statements in the RESTORE command... by default, the RESTORE will restore files to the originally backed up physical files, NOT the Dev DB files, despite the fact that you are restoring to the DEV db... I ALMOST found out the hard way, when I did the restore, and SSMS complained that the files were in use by ANOTHER db... OMG, how non-intuitive.
The script above works, but doesn't change the logical file name for the copied server. So, if you try and run it again to reverse the process it will fail in the MOVE statements.
I modified the script a little and came up with the following which seems to work for me. I'm new to this, so be careful!
DECLARE #SOURCEDB nvarchar(100)
DECLARE #SOURCEDBLOG nvarchar(100)
DECLARE #DESTINATIONDB nvarchar(100)
DECLARE #DESTINATIONDBLOG nvarchar(100)
DECLARE #BACKUPDIR nvarchar(100)
DECLARE #BACKUPFILE nvarchar(100)
DECLARE #BACKUPNAME nvarchar(100)
DECLARE #SQLDATADIR nvarchar(100)
DECLARE #SQLDATABACKUPFILE nvarchar(100)
DECLARE #SQLDATABACKUPLOGFILE nvarchar(100)
--CHANGE THESE VALUES TO MATCH YOUR SYSTEM
SET #SOURCEDB = N'test'
SET #DESTINATIONDB = N'test-backup'
SET #BACKUPDIR = N'C:\SHARED\'
SET #SQLDATADIR = N'C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Data\'
--CALCULATED VALUES
SET #SOURCEDBLOG = #SOURCEDB + N'_log'
SET #DESTINATIONDBLOG = #DESTINATIONDB + N'_log'
SET #BACKUPFILE = #BACKUPDIR + #SOURCEDB + N'-to-' + #DESTINATIONDB + N'.bak'
SET #BACKUPNAME = #SOURCEDB + N'-Full Backup'
SET #SQLDATABACKUPFILE = #SQLDATADIR + #DESTINATIONDB + N'.mdf'
SET #SQLDATABACKUPLOGFILE = #SQLDATADIR + #DESTINATIONDBLOG + N'.ldf'
--BACKUP THE DATABASE
BACKUP DATABASE #SOURCEDB
TO DISK = #BACKUPFILE
WITH
COPY_ONLY,
NOFORMAT,
INIT,
NAME = #BACKUPNAME,
SKIP,
NOREWIND,
NOUNLOAD,
STATS = 10
--RESTORE THE BACKUP TO THE NEW DATABASE NAME
RESTORE DATABASE #DESTINATIONDB
FROM DISK = #BACKUPFILE
WITH
FILE = 1,
MOVE #SOURCEDB TO #SQLDATABACKUPFILE,
MOVE #SOURCEDBLOG TO #SQLDATABACKUPLOGFILE,
NOUNLOAD,
REPLACE,
STATS = 10
--UPDATE THE LOGICAL FILE NAMES
DECLARE #TEMPLATE varchar(500)
DECLARE #SCRIPT varchar(500)
SET #TEMPLATE = N'ALTER DATABASE [{DBNAME}] MODIFY FILE (NAME = [{OLD}], NEWNAME = [{NEW}])'
SET #SCRIPT = REPLACE(REPLACE(REPLACE(#TEMPLATE, '{DBNAME}', #DESTINATIONDB),'{OLD}',#SOURCEDB),'{NEW}',#DESTINATIONDB)
EXEC(#SCRIPT)
SET #SCRIPT = REPLACE(REPLACE(REPLACE(#TEMPLATE, '{DBNAME}', #DESTINATIONDB),'{OLD}',#SOURCEDBLOG),'{NEW}',#DESTINATIONDBLOG)
EXEC(#SCRIPT)
You can restore a database directly from another database.
If you're using SQL Management Studio, select "From database" instead of "From device" in the Restore Database dialog box.
You generally want to restore a whole database from a backup. Trying to do it directly from a live running prod database could cause locking issues for your users. You can do this using SSIS, but it is neither a simple nor quick thing to set up properly.
Another possibility is if you can turn off prod for a time being (only if you have a time period when users are not inthe database). Then detach the database. Detach the dev database and delete it. Copy the file to the dev server and attach both databases again. This can be faster than a restore, but it is a rare environment now that doesn't have 24 hour data access on production.
Incidentally it is very much preferable to have dev and prod on separate servers.
And if you are restoring to dev, you need to make sure any dev changes that have not yet been committed to prod are scripted, so they can be run immediately after the restore. It's best if you script any and all database changes and store them in source control. That makes it easier to do this.
We do an on-demand backup of the production data, and then restore the backup on the dev machine.