How to build a script to backup all databases in SQL Server? - sql

We need to backup 40 databases inside a SQL Server instance. We backup each database with the following script:
BACKUP DATABASE [dbname1] TO DISK = N'J:\SQLBACKUPS\dbname1.bak' WITH NOFORMAT, INIT, NAME = N'dbname1-Full Database Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10
GO
declare #backupSetId as int
select #backupSetId = position from msdb..backupset where database_name=N'dbname1' and backup_set_id=(select max(backup_set_id) from msdb..backupset where database_name=N'dbname1' )
if #backupSetId is null begin raiserror(N'Verify failed. Backup information for database ''dbname1'' not found.', 16, 1) end
RESTORE VERIFYONLY FROM DISK = N'J:\SQLBACKUPS\dbname1.bak' WITH FILE = #backupSetId, NOUNLOAD, NOREWIND
GO
We will like to add to the script the functionality of taking each database and replacing it in the above script. Basically a script that will create and verify each database backup from an engine.
I am looking for something like this:
For each database in database-list
sp_backup(database) // this is the call to the script above.
End For
any ideas?

Use SqlBackupAndFTP. Select "Backup all non-system databases"

Maybe you can check the sp_MSForEachDB stored procedure.
EXEC sp_MSForEachDB 'EXEC sp_backup ?'
Where the ? mark stands for the current database on each iteration.

You said "verify" too... This would require a 2nd statement per database (RESTORE VERIFYONLY, as well the other answers offered.
I'd investigate using maintenance plans to include index maintenance too...

Something like:
DECLARE #SQL varchar(max)
SET #SQL = ''
SELECT #SQL = #SQL + 'BACKUP ' + Name + ' To Disk=''c:\' + Name + '.bak'';'
FROM sys.sysdatabases
EXEC(#SQL)

SQL Backup Master has the ability to back up all databases on a given server instance and then send the backups to Dropbox, FTP, Amazon S3, Google Drive, or local/network folder.

Related

Query for backups

I'm new to sql, and I'm trying to do a query for my backups, but I'm getting an error with some of the lines, I have 20 or more databases, but my query doesn't work on all the DB, its the same query for each DB, it display a message:
query:
USE [DB Name];
GO
BACKUP DATABASE DB Name
TO DISK = 'E:\xxxx\xx\DB Name.Bak'
;WITH FORMAT
MEDIANAME = 'DB Name_SQLServerBackups',
NAME = 'Full Backup DB Name'
Is giving the error message:
Msg 102, Level 15, State 1, Line 69
Incorrect syntax near 'DB Name'.
What am I doing wrong? Really appreciate your help.
Try using brackets around the second [DB Name] too and make a few syntax fixes to your command:
USE [DB Name];
GO
BACKUP DATABASE [DB Name]
TO DISK = 'E:\xxxx\xx\DB Name.Bak'
WITH FORMAT
, MEDIANAME = 'DB Name_SQLServerBackups'
, NAME = 'Full Backup DB Name';
(this worked for me)
Your best place to start would be with the scripts put together by Ola Hallengren which are very comprehensive and cover everything you will need.
Try this:
USE master
BACKUP DATABASE [AdventureWorks2012]
TO DISK = N'D:\Backup\AdventureWorks2012.bak'
WITH COPY_ONLY, NOFORMAT,
NOINIT,
NAME = N'AdventureWorks2012-Full Database Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10
GO
--SPlit backup Process
USE master
BACKUP DATABASE [AdventureWorks2012]
TO DISK = N'D:\Backup\AdventureWorks2012_1.bak'
,DISK = N'D:\Backup\AdventureWorks2012_2.bak'
,DISK = N'D:\Backup\AdventureWorks2012_3.bak'
,DISK = N'D:\Backup\AdventureWorks2012_4.bak'
WITH COPY_ONLY, NOFORMAT,
NOINIT,
NAME = N'AdventureWorks2012-Full Database Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10
GO
Here is a simple script that will backup all databases on your server. I would look carefully at this and learn exactly what it is doing. It's a good starting point but I would try to work to create your own scripts, what works best for you. The cursor allows you to iterate through all the databases and STATIC ensures you capture all databases when querying sys.databases.
/* Full database backup for all user databases. */
DECLARE #dbname varchar (300)
DECLARE #filepath varchar (1000)
DECLARE #filedate varchar (20)
DECLARE #filename varchar (256)
DECLARE #subdir varchar (1000)
SET #filepath = 'C:\TestBackup\' --This is your backup directory
SET #filedate = REPLACE(GETDATE(), ':', '_') --CONVERT(VARCHAR(10),GETDATE(),112) --gets the date and timestamp, replaces : with an underscore
DECLARE backup_cursor CURSOR STATIC FORWARD_ONLY FOR
SELECT [name]
FROM master.sys.databases sd
-- WHERE ... exclude databases
OPEN backup_cursor
FETCH NEXT FROM backup_cursor INTO #dbname
WHILE ##FETCH_STATUS = 0
BEGIN
SET #subdir = 'C:\Backup\' + #dbname
EXEC master.dbo.xp_create_subdir #subdir
SET #fileName = #filepath + #dbname + '\' + #dbname + '_' + #fileDate + '.bak'
BACKUP DATABASE #dbname TO DISK = #fileName
WITH CHECKSUM, STOP_ON_ERROR
RESTORE VERIFYONLY FROM DISK = #fileName
WITH STOP_ON_ERROR
FETCH NEXT FROM backup_cursor INTO #dbname
END
CLOSE backup_cursor
DEALLOCATE backup_cursor

how do i create an automated sql restore script for multiple backups?

Hello to all SQL gurus out there.
I basically have 6 daily sql backups (.bak) that need a restore everyday. I want to automate this process by having the sql agent run the script daily. I have the following restore script written, and I know it's not completely correct, that is why I'm here to ask for any pointers is much appreciated! I'm also still new to writing SQL stored procedures, but my job entails a lot of it. So, I'm learning all this as I go. I welcome any help. :) Thanks a bunch everyone!
use master;
go
set nocount on
-- 1 - variable declaration
declare #dbname nvarchar(max) --database to restore
declare #backuppath nvarchar(max) --backup location
declare #filelisttable --list the table to populate
declare #sql nvarchar(max) --dynamic sql
declare #mdf nvarchar(max) --logical primary data file
declare #ndf nvarchar(max) --logical 2nd data file
declare #ldf nvarchar(max) --logical log data file
declare #dp nvarchar(200) --data file path
declare #lp nvarchar(200) --log file path
declare #backupfile nvarchar(500)
-- 2 - initialize variables
set #dbname = 'test'
set #backuppath = '\\mybackuppath\c$\test'
-- 3 - get list of files
insert into #filelisttable exec('restore filelistonly from disk = ''' +#backuppath+'''') --temptable to retrieve all back up files
-- 4 - retrieve top 6 recent data extracts
select #backuppath = max(backupfile)
from #filelist
where backupfile like '%.bak' --how to pick up most recent 6 back up files w/timestamp on trails?
set #sql = ('use [master])
restore database #dbname ['+#dbname+']
from disk = N'''+#backuppath+'''
with replace,
move N'''+#mdf+''' to N'''+#mdf+'''
move N'''+#ndf+''' to N'''+#ndf+'''
move N'''+#ldf+''' to N'''+#ldf+''''
-- 5- the 6 backup files that need to be restored daily
/** I have to run this manually everyday, and I want to automate this.
RESTORE DATABASE test FROM
DISK = 'C:\test\test_Customer_20160518_1.bak',
DISK = 'C:\test\test_Customer_20160518_2.bak',
DISK = 'C:\test\test_Customer_20160518_3.bak',
DISK = 'C:\test\test_Customer_20160518_4.bak',
DISK = 'C:\test\test_Customer_20160518_5.bak',
DISK = 'C:\test\test_Customer_20160518_6.bak'
WITH REPLACE,
MOVE 'test_Data1' TO 'E:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\test_CUSTOMER.mdf',
MOVE 'test_Data2' TO 'E:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\test_CUSTOMER_1.ndf',
MOVE 'test_Log' TO 'E:\Program Files\Microsoft SQL Server\MSSQL10.MSSQLSERVER\MSSQL\DATA\test_CUSTOMER_2.ldf'
GO
**/
use master
alter database test set multi_user with rollback immediate;
go
return

can a shrink be performed on the current database without specifying the database name

We are connecting to a database in C# and then running a few sql scripts on it.
I need to be able to shrink the current database without specifying the name.
We do not have the database name in the program we are just given the connection and running the scripts.
This is what I started with:
ALTER DATABASE SSSIndexes SET RECOVERY SIMPLE WITH NO_WAIT
GO
DBCC SHRINKFILE(N'SSSIndexes_Log', 1) <-- my issue is here
GO
But I won't know the database name or the log file name.
Can it be done?
You can get the current database and shrink it by calling:
DECLARE #dbName VARCHAR(50)
SELECT #dbName = DB_NAME()
DBCC SHRINKDATABASE(#dbName)
To do just the log file:
DECLARE #logName VARCHAR(50)
SELECT #logName = name FROM sys.master_files WHERE database_id = db_id() AND type = 1
DBCC SHRINKFILE(#logName, 1)

Attach multiple databases using T-SQL

We are migrating one of our servers from SQL Server 2005 to SQL Server 2008.
This server has about 50 small databases on it.
The migration path we are taking goes as follows:
Create new server with SQL 2008
Shutdown SQL Services on old server and copy databases to new one
Shutdown old server and rename new server to the same name as the old one.
Attach the 50 databases
Is there a fast way using t-sql to attach the 50 databases to the new server?
All the data files are going to be located at E:\DATA and transaction logs are going to be located at E:\TLOG
Using the SQLCMD mode, you can easily script this:
:setvar dbname YourDatabaseName
:setvar dbfile N'E:\DATA\YourDatabase.mdf'
:setvar logfile N'E:\TLOG\YourDatabase_log.ldf'
USE [master]
GO
CREATE DATABASE $(dbname) ON
( FILENAME = $(dbfile) ),
( FILENAME = $(logfile) )
FOR ATTACH
GO
This works either from sqlcmd.exe from the command line (you can even supply the values for the variables dbname, dbfile, logfile from the command line, too), or it works in SQL Server Management Studio if you enabled Tools > Options > Query Execution > by default, open new queries in SQLCMD mode .
Read more about the SQLCMD utility and all its parameters on MSDN.
PS: of course, this approach with a SQLCMD enabled script also works for BACKUP/RESTORE cycles :-) (as recommended by Aaron)
PPS: if you have a good naming convention, and the data file is always $(dbname).mdf and the log file is always $(dbname)_log.ldf, you could also use this shortened SQLCMD script:
:setvar dbname YourDatabaseName
USE [master]
GO
CREATE DATABASE $(dbname) ON
( FILENAME = N'E:\DATA\$(dbfile).mdf' ),
( FILENAME = N'E:\TLOG\$(logfile)_log.ldf' )
FOR ATTACH
GO
and then just call this from the command line:
C:\> sqlcmd.exe -S yourserver -E -i attach.sql -v dbname=YourDb1
and so forth, once for each database you need to re-attach.
PPPS: if you want to restore backups, it's just slightly more complicated :
:setvar dbname YourDatabaseName
USE [master]
GO
RESTORE DATABASE $(dbname)
FROM DISK = N'E:\Backup\$(dbname).bak'
WITH FILE = 1,
MOVE N'$(dbname)' TO N'E:\DATA\$(dbname).mdf',
MOVE N'$(dbname)_Log' TO N'E:\TLOG\$(dbname)_Log.ldf',
NOUNLOAD, REPLACE
GO
This works, as long as you name your .bak files the same as your database name, and you put them in a fixed location (I presumed E:\Backup here - adapt as needed).
To re-iterate my comment, I suggest a backup/restore approach as opposed to a detach/attach approach (my reasons are outlined here and here).
And while I like #marc_s's SQLCMD approach, I prefer to pull this stuff from the metadata directly. This way I can inspect all of the output, copy and paste the parts I want to execute in batches instead of all at once, etc. Something like:
SET NOCOUNT ON;
DECLARE #folder nvarchar(512) = N'\\fileshare\folder\'; -- 'backup location
SELECT N'BACKUP DATABASE ' + QUOTENAME(name)
+ N' TO DISK = N''' + #folder + name + N'.BAK'' WITH INIT;
ALTER DATABASE ' + QUOTENAME(name) + N' SET OFFLINE;'
FROM sys.databases
WHERE database_id > 4 -- AND other filter criteria
SELECT N'RESTORE DATABASE ' + QUOTENAME(d.name)
+ N' FROM DISK = N''' + #folder + d.name + N'.BAK'' WITH '
+ STUFF(
(SELECT N',
MOVE N''' + f.name + N''' TO ''E:\DATA\' + f.name + '.mdf'''
FROM master.sys.master_files AS f
WHERE f.database_id = d.database_id
AND type_desc = N'ROWS'
FOR XML PATH(''),
TYPE).value(N'./text()[1]', N'nvarchar(max)'), 1, 1, N'')
+ N', ' + STUFF(
(SELECT N',
MOVE N''' + f.name + N''' TO N''E:\TLOG\' + f.name + N'.mdf'''
FROM master.sys.master_files AS f
WHERE f.database_id = d.database_id
AND type_desc = 'LOG'
FOR XML PATH(''),
TYPE).value(N'./text()[1]', N'nvarchar(max)'), 1, 1, N'') + N';
ALTER DATABASE ' + QUOTENAME(d.name)
+ N' SET COMPATIBILITY_LEVEL = 100;'
FROM sys.databases AS d
WHERE database_id > 4; -- AND other filter criteria
(This assumes that you only have data/log files, no filestream etc. and that you can backup to / restore from a common location accessible to both instances.)
To clarify, you would generate both sets of commands on the 2005 server, copy & run the backup commands there (and perhaps set them to offline immediately afterward), then copy & run the restore commands on the 2008 server.
You'll also want to update statistics on your key tables, otherwise you may be in for some serious head-scratching when your performance goes down the tubes as the plan cache on the new server gets primed...

How can I schedule a daily backup with SQL Server Express? [duplicate]

This question already has answers here:
SQL Server Automated Backups [closed]
(3 answers)
Closed 5 years ago.
I'm running a small web application with SQL server express (2005) as backend. I can create a backup with a SQL script, however, I'd like to schedule this on a daily basis. As extra option (should-have) I'd like to keep only the last X backups (for space-saving reasons obviously) Any pointers?
[edit] SQL server agent is unavailable in SQL server express...
You cannot use the SQL Server agent in SQL Server Express.
The way I have done it before is to create a SQL Script, and then run it as a scheduled task each day, you could have multiple scheduled tasks to fit in with your backup schedule/retention. The command I use in the scheduled task is:
"C:\Program Files\Microsoft SQL Server\90\Tools\Binn\SQLCMD.EXE" -i"c:\path\to\sqlbackupScript.sql"
Eduardo Molteni had a great answer:
SQL Server Automated Backups
Using Windows Scheduled Tasks:
In the batch file
"C:\Program Files\Microsoft SQL Server\100\Tools\Binn\SQLCMD.EXE" -S
(local)\SQLExpress -i D:\dbbackups\SQLExpressBackups.sql
In SQLExpressBackups.sql
BACKUP DATABASE MyDataBase1 TO DISK = N'D:\DBbackups\MyDataBase1.bak'
WITH NOFORMAT, INIT, NAME = N'MyDataBase1 Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10
BACKUP DATABASE MyDataBase2 TO DISK = N'D:\DBbackups\MyDataBase2.bak'
WITH NOFORMAT, INIT, NAME = N'MyDataBase2 Backup', SKIP, NOREWIND, NOUNLOAD, STATS = 10
GO
Just use this script to dynamically backup all databases on the server. Then create batch file according to the article. It is usefull to create two batch files, one for full backup a and one for diff backup. Then Create two tasks in Task Scheduler, one for full and one for diff.
-- // Copyright © Microsoft Corporation. All Rights Reserved.
-- // This code released under the terms of the
-- // Microsoft Public License (MS-PL, http://opensource.org/licenses/ms-pl.html.)
USE [master]
GO
/****** Object: StoredProcedure [dbo].[sp_BackupDatabases] ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: Microsoft
-- Create date: 2010-02-06
-- Description: Backup Databases for SQLExpress
-- Parameter1: databaseName
-- Parameter2: backupType F=full, D=differential, L=log
-- Parameter3: backup file location
-- =============================================
CREATE PROCEDURE [dbo].[sp_BackupDatabases]
#databaseName sysname = null,
#backupType CHAR(1),
#backupLocation nvarchar(200)
AS
SET NOCOUNT ON;
DECLARE #DBs TABLE
(
ID int IDENTITY PRIMARY KEY,
DBNAME nvarchar(500)
)
-- Pick out only databases which are online in case ALL databases are chosen to be backed up
-- If specific database is chosen to be backed up only pick that out from #DBs
INSERT INTO #DBs (DBNAME)
SELECT Name FROM master.sys.databases
where state=0
AND name=#DatabaseName
OR #DatabaseName IS NULL
ORDER BY Name
-- Filter out databases which do not need to backed up
IF #backupType='F'
BEGIN
DELETE #DBs where DBNAME IN ('tempdb','Northwind','pubs','AdventureWorks')
END
ELSE IF #backupType='D'
BEGIN
DELETE #DBs where DBNAME IN ('tempdb','Northwind','pubs','master','AdventureWorks')
END
ELSE IF #backupType='L'
BEGIN
DELETE #DBs where DBNAME IN ('tempdb','Northwind','pubs','master','AdventureWorks')
END
ELSE
BEGIN
RETURN
END
-- Declare variables
DECLARE #BackupName varchar(100)
DECLARE #BackupFile varchar(100)
DECLARE #DBNAME varchar(300)
DECLARE #sqlCommand NVARCHAR(1000)
DECLARE #dateTime NVARCHAR(20)
DECLARE #Loop int
-- Loop through the databases one by one
SELECT #Loop = min(ID) FROM #DBs
WHILE #Loop IS NOT NULL
BEGIN
-- Database Names have to be in [dbname] format since some have - or _ in their name
SET #DBNAME = '['+(SELECT DBNAME FROM #DBs WHERE ID = #Loop)+']'
-- Set the current date and time n yyyyhhmmss format
SET #dateTime = REPLACE(CONVERT(VARCHAR, GETDATE(),101),'/','') + '_' + REPLACE(CONVERT(VARCHAR, GETDATE(),108),':','')
-- Create backup filename in path\filename.extension format for full,diff and log backups
IF #backupType = 'F'
SET #BackupFile = #backupLocation+REPLACE(REPLACE(#DBNAME, '[',''),']','')+ '_FULL_'+ #dateTime+ '.BAK'
ELSE IF #backupType = 'D'
SET #BackupFile = #backupLocation+REPLACE(REPLACE(#DBNAME, '[',''),']','')+ '_DIFF_'+ #dateTime+ '.BAK'
ELSE IF #backupType = 'L'
SET #BackupFile = #backupLocation+REPLACE(REPLACE(#DBNAME, '[',''),']','')+ '_LOG_'+ #dateTime+ '.TRN'
-- Provide the backup a name for storing in the media
IF #backupType = 'F'
SET #BackupName = REPLACE(REPLACE(#DBNAME,'[',''),']','') +' full backup for '+ #dateTime
IF #backupType = 'D'
SET #BackupName = REPLACE(REPLACE(#DBNAME,'[',''),']','') +' differential backup for '+ #dateTime
IF #backupType = 'L'
SET #BackupName = REPLACE(REPLACE(#DBNAME,'[',''),']','') +' log backup for '+ #dateTime
-- Generate the dynamic SQL command to be executed
IF #backupType = 'F'
BEGIN
SET #sqlCommand = 'BACKUP DATABASE ' +#DBNAME+ ' TO DISK = '''+#BackupFile+ ''' WITH INIT, NAME= ''' +#BackupName+''', NOSKIP, NOFORMAT'
END
IF #backupType = 'D'
BEGIN
SET #sqlCommand = 'BACKUP DATABASE ' +#DBNAME+ ' TO DISK = '''+#BackupFile+ ''' WITH DIFFERENTIAL, INIT, NAME= ''' +#BackupName+''', NOSKIP, NOFORMAT'
END
IF #backupType = 'L'
BEGIN
SET #sqlCommand = 'BACKUP LOG ' +#DBNAME+ ' TO DISK = '''+#BackupFile+ ''' WITH INIT, NAME= ''' +#BackupName+''', NOSKIP, NOFORMAT'
END
-- Execute the generated SQL command
EXEC(#sqlCommand)
-- Goto the next database
SELECT #Loop = min(ID) FROM #DBs where ID>#Loop
END
And batch file can look like this:
sqlcmd -S localhost\myDB -Q "EXEC sp_BackupDatabases #backupLocation='c:\Dropbox\backup\DB\', #backupType='F'" >> c:\Dropbox\backup\DB\full.log 2>&1
and
sqlcmd -S localhost\myDB -Q "EXEC sp_BackupDatabases #backupLocation='c:\Dropbox\backup\DB\', #backupType='D'" >> c:\Dropbox\backup\DB\diff.log 2>&1
The advantage of this method is that you don't need to change anything if you add new database or delete a database, you don't even need to list the databases in the script. Answer from JohnB is better/simpler for server with one database, this approach is more suitable for multi database servers.
The folks at MSSQLTips have some very helpful articles, the one most relevant for this is "Automating SQL Server 2005 Express Backups and Deletion of Older Backup Files"
The basic approach is to set up two tasks using the Windows Task Scheduler. One task runs a TSQL script that generates separate backup files for all MSSQL databases (except TEMPDB) with the database name and a date/time stamp in the file name into a specified directory. The second task runs a VBScript script that goes through that directory and deletes all files with a .BAK extension that are more than 3 days old.
Both scripts require minor editing for your environment (paths, how long to keep those database dumps) but are very close to drop-in-and-run.
Note that there are possible security implications if you're sloppy with these or with directory permissions, since they are plain text files that will need to run with some level of privilege. Don't be sloppy.
We have used the combination of:
Cobian Backup for scheduling/maintenance
ExpressMaint for backup
Both of these are free. The process is to script ExpressMaint to take a backup as a Cobian "before Backup" event. I usually let this overwrite the previous backup file. Cobian then takes a zip/7zip out of this and archives these to the backup folder. In Cobian you can specify the number of full copies to keep, make multiple backup cycles etc.
ExpressMaint command syntax example:
expressmaint -S HOST\SQLEXPRESS -D ALL_USER -T DB -R logpath -RU WEEKS -RV 1 -B backuppath -BU HOURS -BV 3
You can create a backup device in server object, let us say
BDTEST
and then create a batch file contain following command
sqlcmd -S 192.168.1.25 -E -Q "BACKUP DATABASE dbtest TO BDTEST"
let us say with name
backup.bat
then you can call
backup.bat
in task scheduler according to your convenience