sql server backup script - sql-server

I have made an attempt at writing a backup script for one of my very small sql server express 2008 database.
My requirements are to do a full backup every night, keep the last five backups. This is my attempt at writing one and would like to get feedback on whether i am doing it right?
Thanks for your assistance.
declare #backupfilename nvarchar(100)
set #backupfilename='c:\...location..\filename_'+convert(varchar(10),getdate(),112) + '.bak'
BACKUP DATABASE [dbname] TO DISK = #backupfilename
WITH RETAINDAYS = 5, NOFORMAT, NOINIT, NAME = N'Full Database Backup Name', NOSKIP,
NOREWIND, NOUNLOAD, STATS = 10
GO
declare #backupSetId as int
select #backupSetId = position from msdb..backupset where database_name=N'dbname'
and backup_set_id=(select max (backup_set_id) from msdb..backupset where
database_name=N'dbname' )
if #backupSetId is null begin raiserror(N'Verify failed. Backup information for database
''dbname'' not found.', 16, 1) end
RESTORE VERIFYONLY FROM DISK =#backupfilename WITH FILE = #backupSetId, NOUNLOAD, NOREWIND
GO

I highly recommend Ola's backup stored procedures. They are well supported and extremely solid. If you don't feel comfortable using them you can at least look to them while you write your own routine.

Related

Transaction Log Backup fails with "Exclusive access could not be obtained because the database is in use"

I am attempting a Log Shipping failover test and the step which is intended to put the database into restoring mode is failing with the error "Exclusive access could not be obtained because the database is in use".
The action was carried out through SSMS selecting "Transaction Log" and also selecting "backup the tail of the log" under Media Options which should leave the database in "restoring mode".
After the failure I attempted to put the database into single user mode first and also take it offline but both commands didn't work (or fail).
I have repeated the action against a test database and that worked with no problem. The T-SQL is below:
BACKUP LOG [TESTDB] TO DISK = N'U:\MSSQL\Backup\TESTDB.bak' WITH NO_TRUNCATE , NOFORMAT, NOINIT, NAME = N'TESTDB-Full Database Backup', SKIP, NOREWIND, NOUNLOAD, NORECOVERY , STATS = 10, CHECKSUM
GO
declare #backupSetId as int
select #backupSetId = position from msdb..backupset where database_name=N'TESTDB' and backup_set_id=(select max(backup_set_id) from msdb..backupset where database_name=N'TESTDB' )
if #backupSetId is null begin raiserror(N'Verify failed. Backup information for database ''TESTDB'' not found.', 16, 1) end
RESTORE VERIFYONLY FROM DISK = N'U:\MSSQL\Backup\TESTDB.bak' WITH FILE = #backupSetId, NOUNLOAD, NOREWIND
GO
I also checked for any blocking or running transactions but nothing showed up.
Any ideas anyone?
A log backup that leaves the target database in RESTORING is called a "Tail Log Backup". And taking the database offline requires terminating all other connections to the database. Like this:
use testdb
go
alter database testdb set single_user with rollback immediate
go
use master
BACKUP LOG [TESTDB] TO DISK = N'c:\temp\TESTDB.bak' WITH NO_TRUNCATE , NOFORMAT, NOINIT, NAME = N'TESTDB-Full Database Backup', SKIP, NOREWIND, NOUNLOAD, NORECOVERY , STATS = 10, CHECKSUM
GO

Backup DB to separate server disk via SQL Job

Due to memory allowances, I need to backup my database to a separate remote server disk which has more space.
I want to do this using a scheduled job but it is not allowing me.
Is this even possible?
I've tried the below code, but get the error:
cannot open backup device
I'm wondering if I need to add access credentials to the server but am not sure how.
DECLARE #Location nvarchar(200)
DECLARE #Day int
SET #Day = DATEPART(dw, getdate())
Set #Location = '\\server2\E:\SqlBackups\'
Set #Location = #Location + 'Day'+ cast(#Day as nvarchar(1)) + '\'
Set #Location = #Location + 'COST.bak'
BACKUP DATABASE COST TO DISK = #Location WITH FORMAT, INIT, NAME =
N'COST-Full Database Backup', SKIP, NOREWIND, NOUNLOAD, COMPRESSION,
STATS = 10
declare #backupSetId as int
select #backupSetId = position from msdb..backupset where
database_name=N'COST' and backup_set_id=(select max(backup_set_id) from
msdb..backupset where database_name=N'COST' )
if #backupSetId is null begin raiserror(N'Verify failed. Backup
information for database ''COST'' not found.', 16, 1) end
RESTORE VERIFYONLY FROM DISK = #Location WITH FILE = #backupSetId,
NOUNLOAD, NOREWIND
GO
Check your UNC path it has to have "$" instead of ":"
Set #Location = '\\server2\E$\SqlBackups\'
Slava was correct, but i also had issues with folder / share permissions which cannot be resolved.
the SeBackUpPriviledge was not enabled and i do not believe i can add this to a domain account. :(

partitioned Database Restore issue

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'';
';

Difference by executing SQL in SQLOLEDB and MSDASQL

I have an problem with the following SQL String:
DECLARE #s varchar(1000), #ver nvarchar(128)
SET #ver = Server Version (e.g. 11 for SQL Server 2012)
SELECT #s = case
WHEN
(CheckVersion (e.g. Enterprise)) AND #ver > 9
THEN
'BACKUP DATABASE [DB] TO DISK = ''C:\Backup\DBBackup.bak'' WITH COMPRESSION, NOFORMAT, NOINIT, SKIP, REWIND, NOUNLOAD, STATS = 10'
ELSE
'BACKUP DATABASE [DB] TO DISK = ''C:\Backup\DBBackup.bak'' WITH NOFORMAT, NOINIT, SKIP, REWIND, NOUNLOAD, STATS = 10;'
END
EXEC (#s)
(This is the short Version, i know that this don't work)
When im using SQLOLEDB Provider everything works fine and the Backupfiles getting created.
The same Command in MSDASQL don't crash, but even create no Backupfile.
Could someone explain, why the same command works with SQLOLEDB and not with MSDASQL?
What is the specific different between these two Providers?
Got fixed the Problem.
OLEDB via ADO has always had the issue where DONE_IN_PROC messages (rows affected) confuse code that is not expecting them. A workaround without app code changes is to specify SET NOCOUNT ON as the first statement in the Batch.

What's the best way to create a working copy of a SQL Server database?

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.

Resources