Restore database from backup file, where file name matches reg expression - sql

I am doing the below using SQL Server / T-SQL :
RESTORE DATABASE UAT
FROM DISK = 'E:\Databases\backup\MY_LIVE_20120720_070001.bak'
WITH REPLACE
But I want to be able to use a file location that ignores the numbers in the file name (which represent the date) in my backup file. There will only ever be one 'MY_LIVE_****.bak' but its number string will change each day.
The goal is to restore my UAT instance from live each week, using the latest backup - of which there will be only file matching that string prefix, but the numbers/date will change each week.

You can use xp_cmdshell to do a dir for your file. Note, however, that xp_cmdshell is normally disabled for good reasons. Given this is UAT, that may not be an issue.
See here for more http://www.sqlusa.com/bestpractices2005/dir/

ALTER DATABASE UAT
SET SINGLE_USER WITH
ROLLBACK IMMEDIATE
declare #fileName varchar(56);
SELECT #filename = physical_device_name
FROM msdb.dbo.backupmediafamily
WHERE media_set_id =(
SELECT TOP 1 media_set_id
FROM msdb.dbo.backupset
WHERE database_name='MY_LIVE'
ORDER BY backup_start_date DESC)
ALTER DATABASE UAT
SET SINGLE_USER WITH
ROLLBACK IMMEDIATE
----Restore Database
RESTORE DATABASE UAT
FROM DISK = #fileName
WITH REPLACE
/*If there is no error in statement before database will be in multiuser
mode.
If error occurs please execute following command it will convert
database in multi user.*/
ALTER DATABASE ASLA_DEV SET MULTI_USER
GO

Related

How can i use master db in stored procedures

I'm trying to create restore db proc. I encountered a problem because i cannot use the command 'use master'. I have try with dynamic SQL but there is no result:
My code:
alter proc dbo.RestoreDB
(
#location as varchar(4000)
)
as
begin
declare #setMasterDb as varchar(400) = 'use master'
exec (#setMasterDb);
ALTER DATABASE [testDb] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
RESTORE DATABASE [testDb] FROM DISK = #location WITH FILE = 1, NOUNLOAD, REPLACE, STATS = 5
ALTER DATABASE [testDb] SET MULTI_USER
end
GO
Is there workaround?
Switching database contexts (USE someDBName) in the middle of a Stored Proc (or function) is not allowed. Also, you do not need to be pointed at the master db context to run a BACKUP/RESTORE, you can be pointed to almost any DB. To fix your issue, just remove your DB switching and point your query window any DB except the one you want to restore.
EDIT: Updated to point to any DB EXCEPT the one you're trying to restore. Thanks to #DMason for that comment.

SQL-Server: Error - Exclusive access could not be obtained because the database is in use

I am actually trying to make a script (in Sql Server 2008) to restore one database from one backup file. I made the following code and I am getting an error -
Msg 3101, Level 16, State 1, Line 3
Exclusive access could not be obtained because
the database is in use.
Msg 3013, Level 16, State 1, Line 3
RESTORE DATABASE is terminating abnormally.
How do I fix this problem ?
IF DB_ID('AdventureWorksDW') IS NOT NULL
BEGIN
RESTORE DATABASE [AdventureWorksDW]
FILE = N'AdventureWorksDW_Data'
FROM
DISK = N'C:\Program Files\Microsoft SQL Server\
MSSQL10_50.SS2008\MSSQL\Backup\AdventureWorksDW.bak'
WITH FILE = 1,
MOVE N'AdventureWorksDW_Data'
TO N'C:\Program Files\Microsoft SQL Server\
MSSQL10_50.SS2008\MSSQL\DATA\AdventureWorksDW.mdf',
MOVE N'AdventureWorksDW_Log'
TO N'C:\Program Files\Microsoft SQL Server\
MSSQL10_50.SS2008\MSSQL\DATA\AdventureWorksDW_0.LDF',
NOUNLOAD, STATS = 10
END
Set the path to restore the file.
Click "Options" on the left hand side.
Uncheck "Take tail-log backup before restoring"
Tick the check box - "Close existing connections to destination database".
Click OK.
I'll assume that if you're restoring a db, you don't care about any existing transactions on that db. Right? If so, this should work for you:
USE master
GO
ALTER DATABASE AdventureWorksDW
SET SINGLE_USER
--This rolls back all uncommitted transactions in the db.
WITH ROLLBACK IMMEDIATE
GO
RESTORE DATABASE AdventureWorksDW
FROM ...
...
GO
Now, one additional item to be aware. After you set the db into single user mode, someone else may attempt to connect to the db. If they succeed, you won't be able to proceed with your restore. It's a race! My suggestion is to run all three statements at once.
execute this query before restoring database:
alter database [YourDBName]
set offline with rollback immediate
and this one after restoring:
alter database [YourDBName]
set online
For me, the solution is:
Check Overwrite the existing database(WITH REPLACE) in optoins tab at left hand side.
Uncheck all other options.
Select source and destination database.
Click ok.
That's it.
taking original db to offline worked for me
Use the following script to find and kill all the opened connections to the database before restoring database.
declare #sql as varchar(20), #spid as int
select #spid = min(spid) from master..sysprocesses where dbid = db_id('<database_name>')
and spid != ##spid
while (#spid is not null)
begin
print 'Killing process ' + cast(#spid as varchar) + ' ...'
set #sql = 'kill ' + cast(#spid as varchar)
exec (#sql)
select
#spid = min(spid)
from
master..sysprocesses
where
dbid = db_id('<database_name>')
and spid != ##spid
end
print 'Process completed...'
Hope this will help...
I just restarted the sqlexpress service and then the restore completed fine
I think you just need to set the db to single user mode before attempting to restore, like below, just make sure you're using master
USE master
GO
ALTER DATABASE AdventureWorksDW
SET SINGLE_USER
Use Master
alter database databasename set offline with rollback immediate;
--Do Actual Restore
RESTORE DATABASE databasename
FROM DISK = 'path of bak file'
WITH MOVE 'datafile_data' TO 'D:\newDATA\data.mdf',
MOVE 'logfile_Log' TO 'D:\newDATA\DATA_log.ldf',replace
alter database databasename set online with rollback immediate;
GO
I experienced this issue when trying to restore a database on MS SQL Server 2012.
Here's what worked for me:
I had to first run the RESTORE FILELISTONLY command below on the backup file to list the logical file names:
RESTORE FILELISTONLY
FROM DISK = 'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\Backup\my_db_backup.bak'
This displayed the LogicalName and the corresponding PhysicalName of the Data and Log files for the database respectively:
LogicalName PhysicalName
com.my_db C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\com.my_db.mdf
com.my_db_log C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\com.my_db_log.ldf
All I had to do was to simply replace the LogicalName and the corresponding PhysicalName of the Data and Log files for the database respectively in my database restore script:
USE master;
GO
ALTER DATABASE my_db SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO
RESTORE DATABASE my_db
FROM DISK = 'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\Backup\my_db_backup.bak'
WITH REPLACE,
MOVE 'com.my_db' TO 'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\com.my_db.mdf',
MOVE 'com.my_db_log' TO 'C:\Program Files\Microsoft SQL Server\MSSQL12.MSSQLSERVER\MSSQL\DATA\com.my_db_log.ldf'
GO
ALTER DATABASE my_db SET MULTI_USER;
GO
And the Database Restore task ran successfully:
That's all.
I hope this helps
Setting the DB to single-user mode didn't work for me, but taking it offline, and then bringing it back online did work. It's in the right-click menu of the DB, under Tasks.
Be sure to check the 'Drop All Active Connections' option in the dialog.
Vinu M Shankar's solution worked for me.
But I had to check the: "Take tail-log backup before restoring" checkbox for mine to work.
Here's a way I am doing database restore from production to development:
NOTE: I am doing it via SSAS job to push production database to development daily:
Step1: Delete previous day backup in development:
declare #sql varchar(1024);
set #sql = 'DEL C:\ProdAEandAEXdataBACKUP\AE11.bak'
exec master..xp_cmdshell #sql
Step2: Copy production database to development:
declare #cmdstring varchar(1000)
set #cmdstring = 'copy \\Share\SQLDBBackup\AE11.bak C:\ProdAEandAEXdataBACKUP'
exec master..xp_cmdshell #cmdstring
Step3: Restore by running .sql script
SQLCMD -E -S dev-erpdata1 -b -i "C:\ProdAEandAEXdataBACKUP\AE11_Restore.sql"
Code that is within AE11_Restore.sql file:
RESTORE DATABASE AE11
FROM DISK = N'C:\ProdAEandAEXdataBACKUP\AE11.bak'
WITH MOVE 'AE11' TO 'E:\SQL_DATA\AE11.mdf',
MOVE 'AE11_log' TO 'D:\SQL_LOGS\AE11.ldf',
RECOVERY;
I got this error when there was not enough disk space to restore Db. Cleaning some space solved it.
Solution 1 : Re-start SQL services and try to restore DB
Solution 2 : Re-start system / server and try to restore DB
Solution 3 : Take back of current DB, Delete the current/destination DB and try to restore DB.
I got this error when unbeknownst to me, someone else was connected to the database in another SSMS session. After I signed them out the restore completed successfully.
In my case although i tried all of the above solutions, the thing that worked, was to restart SSMS.

restore sql server from .bak file Exclusive access could not be obtained

I am trying to restore my sql using bak file
I am getting error
Exclusive access could not be obtained because the database is in use
I tried
USE [master]
ALTER DATABASE myDB
SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
and run the query
USE [master] RESTORE DATABASE myDB
FROM DISK = 'C:\MyDatabase.bak' WITH FILE = 1, NOUNLOAD, STATS = 10
I also tried from restore wizard with same result.
Exclusive access could not be obtained because the database is in use.
Method 1
declare #sql as varchar(20), #spid as int
select #spid = min(spid) from master..sysprocesses where dbid = db_id('<database_name>') and spid != ##spid
while (#spid is not null)
begin
print 'Killing process ' + cast(#spid as varchar) + ' ...'
set #sql = 'kill ' + cast(#spid as varchar)
exec (#sql)
select
#spid = min(spid)
from
master..sysprocesses
where
dbid = db_id('<database_name>')
and spid != ##spid
end
print 'Process completed...'
Method 2
alter database database_name
set offline with rollback immediate
alter database database_name
set online
go
Don't need to write any query to solve this problem.
I had the same problem several times and solve it by this method:
when you are restoring database
Go to Option tab in Restore database window
Check (Overwrite the existing database (WITH REPLACE))
Check (Close existing connections to destination database)
Then click OK
Restore database is starting...
Anyone that has had the issues listed above, and none of the advice works.. Just turn off the Taillog backup under 'options'..
Setting (or leaving) this option on will attempt to take a tail-log of the source database itself (even if your source for the restore is just a file). So if the source database is in use (which if you are doing a copy of a production DB will normally be the case) then the restore fails.
I had this issue when I was trying to restore a production backup to a dev server that already had the database there. I wanted to restore as a copy, which I did by changing the target database name, but the issue was actually with the files. By default, it was trying to overwrite the files that were already there. I fixed the issue by checking the "Relocate all files to folder" in the "Files" page of the restore dialog and choosing a new directory so there wouldn't be file collisions.
None of the above solution did not work for me.
After many trials and errors, I stopped SQL Server Browser and then the restore completed successfully

How to create copy of production SQL database?

I'm looking for best practices, efficient way. I need to copy once per month my production database to development. So I'm thinking to automate this process if possible.
The size of database around 20GB with log file (full recovery mode).
Please let me know if I need to provide more details.
Hopefully you're making regular backups of your database anyway.
So you basically just need to take the newest backup and restore it on a different server (and maybe with a different database name).
At my workplace, we are using MS SQL Server and we are doing this as well:
Our main database is backed up every evening at 9 pm (full backup).
Every day at 11 pm, a SQL Server Agent job on another server takes the newest backup from the backup folder and restores it as OurMainDatabase_Yesterday.
Here is an example script for MS SQL Server:
ALTER DATABASE OurMainDatabase_Yesterday SET SINGLE_USER WITH ROLLBACK IMMEDIATE
USE master
EXEC sp_detach_db 'OurMainDatabase_Yesterday', 'true'
-- use today's backup from the main server
declare #BackupPath as nvarchar(500)
set #BackupPath = '\\MainServer\backup\OurMainDatabase\OurMainDatabase_backup_'
+ convert(varchar(10),getdate(),112) + '2100.BAK'
RESTORE DATABASE OurMainDatabase_Yesterday
FROM DISK = #BackupPath
WITH MOVE 'OurMainDatabase_Data'
TO 'F:\Data\OurMainDatabase_Yesterday_Data.mdf',
MOVE 'OurMainDatabase_Log'
TO 'G:\Logs\OurMainDatabase_Yesterday_Log.ldf',
REPLACE
ALTER DATABASE OurMainDatabase_Yesterday SET MULTI_USER

SQL Server 2000 to SQL Server 2008 R2 migration

I am using SQL Server 2000 including 77 databases, and I want to migrate them to the new SQL Server 2008 R2.
I can do this operation individually with attach or restore commands. Is there any script for migrating 77 databases to the new server installed SQL Server 2008 R2.
Thank you
You could write a script to backup in a loop and restore on another server
As long as the backup files are visible to both servers. This would allow a WITH MOVE option to allow for different drives/folders.
Backups are smaller than MDFs/LDFs too to less copying
You will need to produce your own script as you would really want to do more than backup and restore.
Other things you might like to do is run DBCC UpdateUsage, set the compatibility level, update the stats, run DBCC CheckDB with Data_Purity, change the page verify option to checksum. You may have replication and full text catalogues to deal with as well. All these things would probably need to go into your script.
You would need to setup a script that performs all/some/more of the things mentionned previously on a database and then extend your script to loop through all your databases. This can be done using a combination of batch files or powershell files and utilizing sqlcmd.
For example this is one script I run after restoring the backups onto the new server. This is called from a windows batch file via sqlcmd.
USE [master]
GO
ALTER DATABASE [$(DATABASENAME)] SET COMPATIBILITY_LEVEL = 100
ALTER DATABASE [$(DATABASENAME)] SET PAGE_VERIFY CHECKSUM WITH NO_WAIT
GO
Use [$(DATABASENAME)]
Go
Declare #DBO sysname
--who is the sa user
Select #DBO = name
from sys.server_principals
Where principal_id = 1
--assign sa the DB owner
exec ('sp_changedbowner ''' + #DBO +'''')
go
--fix the counts
dbcc updateusage (0)
go
--check the db include the column value integrity
dbcc checkdb(0) With Data_Purity, ALL_ERRORMSGS, NO_INFOMSGS
go
--make sure the stats are up to date
exec sp_updatestats
Go
You could use a software tool like Sql Compare.
Failing that I would script them individually.
You could run round the internal sysobjects table and build a combined script, but I wouldn't.