Backup database with different name time-related - sql

My code ,for agent's job on SQL server 2008 , generate the backup file, but it keep OVERWRITE the first bak file everytime the agent's job triggered !!?
how can i make backup with different name time-related
e.g:
testDB201313328.bak
and after 1 minute create file with name :
testDB201313329.bak
instead overwriting the first one
USE msdb ;
GO
DECLARE #fileName VARCHAR(90);
DECLARE #db_name VARCHAR(20);
DECLARE #fileDate VARCHAR(20);
DECLARE #commandtxt VARCHAR(100);
SET #fileName = 'C:\Test_Backups\';
SET #db_name = 'testDB';
SET #fileDate = CONVERT(VARCHAR(8), GETDATE(),112) + convert (varchar(4),DATEPART(HOUR, GETDATE())) + convert ( varchar(4) ,DATEPART(MINUTE, GETDATE())) + convert ( varchar(4) ,DATEPART(SECOND, GETDATE()));
SET #fileName = #fileName + #db_name + RTRIM(#fileDate) + '.bak';
SET #commandtxt = 'BACKUP LOG testDB TO DISK =''' + #fileName + ''' WITH INIT'
-- add a job
EXEC dbo.sp_add_job
#job_name = N'LogBackup',
#description =N'Log Backup on weekdays every 15 minutes from 8am till 6pm' ;
-- add job steps to job
EXEC sp_add_jobstep
#job_name = N'LogBackup',
#step_name = N'Weekdays_Log_Backup',
#subsystem = N'TSQL',
#command = #commandtxt ,
#on_success_action = 1,
#retry_attempts = 5,
#retry_interval = 1 ;
GO
...

First, backups can contain more than one backup set, so are you sure you are overwriting it and not just appending another set within the same file? Otherwise you need to add the time of day to your filename. Hope this helps. Also if its just one or two db, then there is an excellent (free for limited use) app, google SQLBackupAndFTP HTH

Related

How do I backup a database with a stored procedure in SQL?

I'm trying to create a stored procedure that backs up a database, however whenever I execute it, the folder I'm trying to backup to remains empty.
Here is my stored procedure:
USE [HarvestMan_SoutheskFarm_03_05_22]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: Will Sewell
-- Create date: 03-05-2022
-- Description: Procedure to back up a database
-- =============================================
ALTER PROCEDURE [dbo].[BackupDatabases]
#name VARCHAR(MAX) = 'HarvestMan_SoutheskFarm_03_05_22' -- DB NAME TO CREATE BACKUP
AS
BEGIN
DECLARE #path VARCHAR(256) -- path of backup files
DECLARE #fileName VARCHAR(256) -- filename for backup
DECLARE #fileDate VARCHAR(20) -- used for file name
SET #path = 'C:\Users\will.sewell\Documents\Database_Test'
-- specify filename format
SELECT #fileDate = CONVERT(VARCHAR(20),GETDATE(),112)
BEGIN
SET #fileName = #path + #name + '_' + #fileDate + '.BAK'
BACKUP DATABASE #name TO DISK = #fileName
END
END
I have tried changing the drive that it is writing to.
I've copy and pasted the database name I want to backup to ensure no spelling mistakes.
I'm assuming it might be a permissions issue or a visible files in the folder.
When I execute the stored procedure, I get this:
Processed 24472 pages for database 'HarvestMan_SoutheskFarm_03_05_22', file 'HarvestMan_dat' on file 2.
Processed 1 pages for database 'HarvestMan_SoutheskFarm_03_05_22', file 'HarvestMan_log' on file 2. BACKUP DATABASE successfully processed 24473 pages in 5.039 seconds (37.941 MB/sec).
Completion time: 2022-05-04T10:27:30.2344290+01:00
Dear you have to create the stored procedure first
also your path missing the last slash
BIG Note you must define an actual path
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE PROCEDURE [dbo].[BackupDatabases]
#name VARCHAR(MAX) = 'ActualDataBaseName' -- DB NAME TO CREATE BACKUP
AS
BEGIN
DECLARE #path VARCHAR(256) -- path of backup files
DECLARE #fileName VARCHAR(256) -- filename for backup
DECLARE #fileDate VARCHAR(20) -- used for file name
SET #path = 'C:\ActualPath\'
-- specify filename format
SELECT #fileDate = CONVERT(VARCHAR(20),GETDATE(),112)
BEGIN
SET #fileName = #path + #name + '_' + #fileDate + '.BAK'
BACKUP DATABASE #name TO DISK = #fileName
END
END

Backup script I've been using with no issues for a while tossing an error on new database

I've been using the code below to drop and create a new backup named (current year database)_daily at midnight to allow my team to test new scripts or updates to our student information system.
It worked all last year, and this year for reasons I can't figure out, the script is tossing an error.
Here is the script:
USE master;
GO
-- the original database (use 'SET #DB = NULL' to disable backup)
DECLARE #SourceDatabaseName varchar(200)
DECLARE #SourceDatabaseLogicalName varchar(200)
DECLARE #SourceDatabaseLogicalNameForLog varchar(200)
DECLARE #query varchar(2000)
DECLARE #DataFile varchar(2000)
DECLARE #LogFile varchar(2000)
DECLARE #BackupFile varchar(2000)
DECLARE #TargetDatabaseName varchar(200)
DECLARE #TargetDatbaseFolder varchar(2000)
-- ****************************************************************
SET #SourceDatabaseName = '[DST18000RD]' -- Name of the source database
SET #SourceDatabaseLogicalName = 'DST18000RD' -- Logical name of the DB ( check DB properties / Files tab )
SET #SourceDatabaseLogicalNameForLog = 'DST18000RD_log' -- Logical name of the DB ( check DB properties / Files tab )
SET #BackupFile = 'F:\Dev_Databases\Temp\backup.dat' -- FileName of the backup file
SET #TargetDatabaseName = 'DST18000RD_Daily' -- Name of the target database
SET #TargetDatbaseFolder = 'F:\Dev_Databases\Temp\'
-- ****************************************************************
SET #DataFile = #TargetDatbaseFolder + #TargetDatabaseName + '.mdf';
SET #LogFile = #TargetDatbaseFolder + #TargetDatabaseName + '.ldf';
-- Disconnect any users using #TargetDatabaseName
USE [master];
DECLARE #kill varchar(8000) = '';
SELECT #kill = #kill + 'kill ' + CONVERT(varchar(5), session_id) + ';'
FROM sys.dm_exec_sessions
WHERE database_id = db_id('DST18000RD_Daily')
EXEC(#kill);
-- Backup the #SourceDatabase to #BackupFile location
IF #SourceDatabaseName IS NOT NULL
BEGIN
SET #query = 'BACKUP DATABASE ' + #SourceDatabaseName + ' TO DISK = ' + QUOTENAME(#BackupFile,'''')
PRINT 'Executing query : ' + #query;
EXEC (#query)
END
PRINT 'OK!';
-- Drop #TargetDatabaseName if exists
IF EXISTS(SELECT * FROM sysdatabases WHERE name = #TargetDatabaseName)
BEGIN
SET #query = 'DROP DATABASE ' + #TargetDatabaseName
PRINT 'Executing query : ' + #query;
EXEC (#query)
END
PRINT 'OK!'
-- Restore database from #BackupFile into #DataFile and #LogFile
SET #query = 'RESTORE DATABASE ' + #TargetDatabaseName + ' FROM DISK = ' + QUOTENAME(#BackupFile,'''')
SET #query = #query + ' WITH MOVE ' + QUOTENAME(#SourceDatabaseLogicalName,'''') + ' TO ' + QUOTENAME(#DataFile ,'''')
SET #query = #query + ' , MOVE ' + QUOTENAME(#SourceDatabaseLogicalNameForLog,'''') + ' TO ' + QUOTENAME(#LogFile,'''')
PRINT 'Executing query : ' + #query
EXEC (#query)
PRINT 'OK!'
The script is not mine, I put together two scripts to get me what I needed. Our old database DST17000RD, this script still works flawlessly. On the new database DST18000RD, I get this error:
Executing query : BACKUP DATABASE [DST18000RD] TO DISK = 'F:\Dev_Databases\Temp\backup.dat'
Processed 1209552 pages for database 'DST18000RD', file 'DST18000RD' on file 23.
Processed 2 pages for database 'DST18000RD', file 'DST18000RD_log' on file 23.
BACKUP DATABASE successfully processed 1209554 pages in 139.942 seconds (67.525 MB/sec).
OK!
OK!
Executing query : RESTORE DATABASE DST18000RD_Daily FROM DISK = 'F:\Dev_Databases\Temp\backup.dat' WITH MOVE 'DST18000RD' TO 'F:\Dev_Databases\Temp\DST18000RD_Daily.mdf' , MOVE 'DST18000RD_log' TO 'F:\Dev_Databases\Temp\DST18000RD_Daily.ldf'
Msg 3234, Level 16, State 2, Line 3
Logical file 'DST18000RD' is not part of database 'DST18000RD_Daily'. Use RESTORE FILELISTONLY to list the logical file names.
Msg 3013, Level 16, State 1, Line 3
RESTORE DATABASE is terminating abnormally.
OK!
Some things to note that may just be me barking up the wrong tree. DST17000RD database is compatibility level SQL Server 2012 (110) and the DST18000RD database is SQL Server 2017 (140). The server was upgraded and migrated a couple months ago before the new database was created.
Any help is appreciated. From what I can tell, I feel like the script is not renaming the MDF and LDF files before it tries to copy them for the *_daily database? Honestly I'm not sure. I'm a pretend DBA, self taught on an as needed basis. Thank you in advance for your help!
The error is telling you got the logical name of the db file wrong:
SET #SourceDatabaseLogicalName = 'DST18000RD' -- Logical name of the DB ( check DB properties / Files tab )
and to run:
RESTORE FILELIST ONLY FROM DISK = 'F:\Dev_Databases\Temp\backup.dat'
To see the correct logical file names.
The issue is you are trying to change the file logical name during the database restore, which is not possible even if you use the MOVE clause.
The MOVE clause allows you to change the location and the names of the physical files but does not do anything for the logical names.
Fix
You will have to use the existing logical names for your database, but once you have restored the database then use ALTER DATABASE command to change the logical names of your files using the following command:
USE [master];
GO
ALTER DATABASE [DST18000RD]
MODIFY FILE ( NAME = DST17000RD , NEWNAME = DST18000RD );
GO

SQL GO disrupts chain of local variables

I use script for DB backup as below:
---- INITIALIZATION
-- UNIFIED DATE
DECLARE #DAT DATETIME
SELECT #DAT = GETDATE()
-- DEFAULT BACKUPS LOCATION
DECLARE #PATH VARCHAR(20)
SELECT #PATH = 'Q:\DBbackup\Default\'
---- DATABASE BACKUPS
-- DB1
DECLARE #DBNAME VARCHAR(64)
SELECT #DBNAME = 'DB1'
DECLARE #BACKUPNAME VARCHAR(64)
DECLARE #DESCRIPTION VARCHAR (255)
SELECT #BACKUPNAME = (#PATH + #DBNAME +'_'+ CONVERT(VARCHAR(19),#DAT,121) + '.bak')
SELECT #DESCRIPTION = #DBNAME + ' Full ad hoc backup ' + CONVERT(VARCHAR(20),#DAT)
SELECT #BACKUPNAME
BACKUP DATABASE #DBNAME TO DISK = #BACKUPNAME WITH FORMAT, INIT, NAME = #DESCRIPTION, SKIP, NOREWIND, NOUNLOAD, STATS = 10, COMPRESSION
GO
-- DB2
DECLARE #DBNAME VARCHAR(64)
SELECT #DBNAME = 'DB2'
DECLARE #BACKUPNAME VARCHAR(64)
DECLARE #DESCRIPTION VARCHAR (255)
SELECT #BACKUPNAME = (#PATH + #DBNAME + '_' + CONVERT(VARCHAR(19),#DAT,121) + '.bak')
SELECT #DESCRIPTION = #DBNAME + ' Full ad hoc backup ' + CONVERT(VARCHAR(20),#DAT)
BACKUP DATABASE #DBNAME TO DISK = #BACKUPNAME WITH FORMAT, INIT, NAME = #DESCRIPTION, SKIP, NOREWIND, NOUNLOAD, STATS = 10, COMPRESSION
GO
However, for backup DB2 the variables #PATH and #DAT are not found as they apply only to first backup. It seems the GO command cancels the effect of local variables for DB2 backup. Is there any workaround for this situation? I want to use the variables in INIT only once, not duplicate them for each database backup.
SQL Server does not know what GO means. That's an SSMS feature. It causes multiple batches to be sent. Either remove GO (and restructure the variables so that they are declared only once) or store that data in a persistent location such as a temp table.
Unfortunately, no great options. T-SQL is a stone-age language.

full backups occasionally skipping certain databases

We have a job set up to run a script every night to do a full backup on all of our databases. Recently, we noticed that sometimes the last two databases are skipped, but not all of the time. We have a tracking table that we are inserting the state of each database in when we do the backups. On the nights that the last two databases are skipped, the state for those databases doesn't get recorded in the tracking table either. We can't figure out why those databases are being skipped. This is the backup script we are using:
DECLARE #dbname VARCHAR(100),
#dbid INT,
#rcmodel VARCHAR(50),
#state VARCHAR(60),
#date VARCHAR(50),
#time VARCHAR(50),
#sql VARCHAR(3000),
#dir VARCHAR(1000),
#path VARCHAR(100),
#type VARCHAR(10)
SET #path = 'E:\Backups\'
SET #type = 'Full'
SET #date = REPLACE(CONVERT(date,GETDATE(),101),'-','_')
SET #time = REPLACE(CONVERT(TIME(0), GETDATE()),':','_')
SET #path = #path + CONVERT(VARCHAR(30),##SERVERNAME) + '\' + #type + '\'
DECLARE BackupCur CURSOR FOR
SELECT NAME, database_id, recovery_model_desc, state_desc
FROM sys.databases
WHERE NAME <> 'tempdb'
OPEN BackupCur
FETCH NEXT FROM BackupCur INTO #dbname, #dbid, #rcmodel, #state
WHILE ##FETCH_STATUS = 0
BEGIN
INSERT INTO backuptrackingtable (db, statedesc, datecreated)
values (#dbname, #state, GETDATE())
IF #type = 'Full' AND #state = 'ONLINE'
BEGIN
SET #dir = 'EXECUTE master.dbo.xp_create_subdir N'''+#path+#dbname+''''
SET #sql = 'BACKUP DATABASE '+#dbname+' TO DISK = N'''+#path+#dbname+'\'+#dbname+'_'+#date+'.bak'' WITH NOFORMAT, INIT, SKIP, REWIND, NOUNLOAD, COMPRESSION'
PRINT 'Backing up ' + #dbname
EXEC (#dir)
EXEC (#sql)
END
IF #type = 'Log' AND #dbid > 4 AND #rcmodel = 'FULL' AND #state = 'ONLINE'
BEGIN
SET #dir = 'EXECUTE master.dbo.xp_create_subdir N'''+#path+#dbname+''''
SET #sql = 'BACKUP LOG '+#dbname+' TO DISK = N'''+#path+#dbname+'\'+#dbname+'_'+#date+'__'+#time+'.bak'' WITH NOFORMAT, INIT, SKIP, REWIND, NOUNLOAD, COMPRESSION'
PRINT 'Backing up ' + #dbname
EXEC (#dir)
EXEC (#sql)
END
FETCH NEXT FROM BackupCur INTO #dbname, #dbid, #rcmodel, #state
END
CLOSE BackupCur
DEALLOCATE BackupCur
Can think of three possible explanations.
They aren't being returned from the query against sys.databases because they don't exist or the user running the query doesn't have permissions on them.
An unhandled error means that the script aborts before processing them.
##FETCH_STATUS returns -2 at some point because a database has been dropped since the keyset cursor opened.
You would need to put more logging in to investigate further. But you might want to consider using a maintenance plan (dependant on edition) or Ola Hallengren's DB maintenance scripts rather than re-inventing the wheel anyway.

Delete backup files older than 7 days

Using osql command, SSQL backup of a database is created.
It is saved to Disk.
Then renamed to match the date of the day backup was taken.
All these files are saved in a single folder all the time.
for example:
Batch1.bat does the following
1) Created backup.bak
2) renamed to backup 12-13-2009.bak (this is done by the combination of % ~ - etc to get the date parameter)
This is now automated to take backup everyday by Task scheduler in Windows.
Can the batch file also be modified to delete backup files older than 7 days? if so, how ?
If it is not possible via batch file, other than manually deleting the files are there any other alternatives to automate the deleting job ?
Thanks in advance, Balaji S
If you have RoboCopy (part of the Windows Server 2003 Resource Kit Tools) installed.
The following lines can be added to your Batch1.bat file to move and delete files older than seven days:
ROBOCOPY C:\Temp\New C:\Temp\Old *.* /move /minage:7
DEL C:\Temp\Old\*.*
The first row moves all files that are older than seven days in the 'New' folder to the 'Old' folder.
The second row deletes all files in the 'Old' folder
I'm using the same technique to make a backup from database. I've created a stored procedure as follows.
Create Procedure [dbo].[CreateBackup]
As
Begin
Declare #path nvarchar(256),
#filename nvarchar(256),
#currentDateTime datetime
Set #currentDateTime = GetDate()
Set #path = 'C:\DBBackup\'
Set #filename = #path + Cast(DatePart(month, #currentDateTime) As nvarchar) + Cast(DatePart(day, #currentDateTime) As nvarchar) + '.bak'
Backup Database Foo To Disk = #filename
Set #currentDateTime = DateAdd(day, -3, #currentDateTime)
Set #filename = 'del ' + #path + Cast(DatePart(month, #currentDateTime) As nvarchar) + Cast(DatePart(day, #currentDateTime) As nvarchar) + '.bak'
Exec xp_cmdshell #filename
End
To use the xp_cmdshell, you should enable it before.
http://weblogs.sqlteam.com/tarad/archive/2006/09/14/12103.aspx
enter code hereThis procedure backup given database(s) for specified #retentionPeriod to a given network location (or local)
USE [master]
GO
/****** Object: StoredProcedure [dbo].[scrDoRemoteBackup] Script Date: 12/13/2009 09:20:20 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER proc [dbo].[scrDoRemoteBackup] as
set NoCount on
declare #dbName Varchar(100)
,#fName varchar(100)
,#RetentionPeriod Int -- in days
,#i int
,#n int
,#NetPath varchar(400)
,#BackupSetName Varchar(300)
,#params nvarchar(300)
,#q nvarchar(3400)
,#cmd nvarchar(4000)
,#error int
Declare #DataBases2Backup table(id int identity(1,1),dbName Varchar(100))
-- total back time 4:24 2nd Nov 06
set #NetPath='\\rapidsnet01s\RapidsDbBackup'
set #netPath='\\mail1\RapidsDbBackup'
set #netPath = '\\rapidsweb02p\Backup'
set #netPath='\\BUP2D-2K\_RapidsDB$\SAABZXO1D' -- 26th Feb 2008 - ap/li rapidsweb02p\backup space runout
set #netPath='\\saacsfs\RapidsBackup\SAABZXo1d' -- 22nd Oct 2009
---- insert all databaes to be backed up
--Insert #DataBases2Backup select 'Rapids'
--Insert #DataBases2Backup select 'GDC'
--Insert #DataBases2Backup select 'Master'
--
--
----Insert #DataBases2Backup select 'GDCComDev'
--
--Insert #DataBases2Backup select 'saaNCP'
----Insert #DataBases2Backup select 'US_Reps'
--Insert #DataBases2Backup select 'saaPackageWorx'
--Insert #DataBases2Backup select 'saaExtract'
Insert #DataBases2Backup select 'Master'
Insert #DataBases2Backup select 'QuickPickDBprod'
Insert #DataBases2Backup select 'QuickPickDBStaging'
--Set #RetentionPeriod = 13
Set #RetentionPeriod = 6 -- For Terry McCraith Jan06'09
select #n= count(*) from #DataBases2Backup
set #i = 1;
-- Set the Network path for the Backup location ;
-- ( re-establish the connection if the connection was broken)
set #q = 'net use '+#Netpath --+' * /USER:apeiris#armlink.com'
print #q
exec master.dbo.xp_cmdShell #q
While #i <= #n
Begin
select #dbName=dbName from #DataBases2Backup where id = #i
-- Get the backupset name prior to Retention Period
set #BackupSetName=#dbName+ dbo.fnGetDateNameBefore(GetDate(),#RetentionPeriod)
-- Delete the old backup device
set #q='Del '+#NetPath+'\'+#BackupSetName+'.bkp'
exec master.dbo.xp_cmdShell #q
-- Now get the current backupset name and backit up
set #BackupSetName=#dbName+ dbo.fnGetDateNameBefore(GetDate(),0)
set #fname = #netPath +'\'+#BackupSetName+'.bkp'
print 'Fname ='+#fname
Print 'Drop and Add Dumpdevice ' + #dbname + ' Fname='+#fname
exec #error=sp_dropDevice #dbname
print 'Error drop device-----------'+Convert(varchar,#error)+':'+Convert(varchar,##error)
exec #error=sp_addumpDevice 'disk',#dbName,#fname
exec sp_helpdevice #dbName
print 'Error -----------'+Convert(varchar,#error)
set #i=#i+1
if #error <> 0
Begin
print 'send alert'
exec saabzt01p.alerts.dbo.prDispatchAlertV2 'RemoteDBBackupError' ,##servername,'test','RemoteDBBackupError','test'
End
else
Begin
Backup Log #dbname with truncate_only
Backup Database #dbname to #dbname with format
if ##Error <> 0
Begin
print 'Send alert'
exec saabzt01p.alerts.dbo.prDispatchAlertV2 'RemoteDBBackupError',##servername,'test','RemoteDBBackupError','test'
Goto Errors
end
end
End
Errors:
And here are supporting functions
-- This function returns oldest data set name compared to retentionPeriod
Create function [dbo].[fnGetDateNameBefore](#d Datetime,#nDays int) returns varchar(40) as
Begin
declare #OD datetime
,#dName Varchar(40);
set #OD=DateAdd(dd,#nDays * -1,#d)
select #dName= DateName(yy,#od)+Left(DateName(Month,#od),3)+DateName(dd,#od)
Return #dName
end
-- This function returns oldest data set name compared to retentionPeriod
Create function [dbo].[fnGetDateNameBefore](#d Datetime,#nDays int) returns varchar(40) as
Begin
declare #OD datetime
,#dName Varchar(40);
set #OD=DateAdd(dd,#nDays * -1,#d)
select #dName= DateName(yy,#od)+Left(DateName(Month,#od),3)+DateName(dd,#od)
Return #dName
end
Nope don't do it that way. Do it this way.
Use SQL backup manager from the command line and script out a schedlue using Backup manager express. This is included and located in your SQL bin folder. Run this once, then modify the registry if it gives you an error. Then run again, ot should work. Perform this methodolgy to obtian your backups on a scheduled basis.