Delete backup files older than 7 days - sql

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.

Related

bulk insert files with filenames that change everyday

I need to bulk insert a text file, which is always stored in the same folder. The file name is 'employee_date', where the date part is not always the actual date. It is a dynamic date that the user changes every day (with the format YYYYMMDDHHMM).
What I need is a query that bulk inserts the data in that text file (that is already formatted). My problem is bulk insert does not work with variables or with *.txt or employes*.txt.
I need a query that bulk insert only the file which name is like EMPLOYEE_YYYYMMDDHHMM.txt that can be executed every day and always insert the file from that folder, doesn't matter what the date is in the file name.
Here is something you can modify to fit your requirements. I had a similar task where we got files SFTP to us from a Linux system and I needed to upload this data into a SQL Server. Here's the basic layout... understanding your file locations, permissions on the folder, SQL permissions, etc all need to be taken into consideration. Including if you can run command shell code in your environment.
CREATE procedure [dbo].[file_upload]
as
DECLARE #dt VARCHAR(10) --date variable but stored as VARCHAR for formatting of file name
DECLARE #fileLocation VARCHAR(128) = 'E:\SomeFolder\' --production location which is
DECLARE #sql NVARCHAR(4000) --dynamic sql variable
DECLARE #fileName VARCHAR(128) --full file name variable
--This stores the file names into a temp table to be used in a cursor.
--The bottom part is handleing some date formatting i needed. You can change to what your files look like
IF OBJECT_ID('tempdb..#FileNames') IS NOT NULL DROP TABLE #FileNames
CREATE TABLE #FileNames (
id int IDENTITY(1,1)
,subdirectory nvarchar(512)
,depth int
,isfile bit
,fileDate date null
,fileTime time null)
INSERT #FileNames (subdirectory,depth,isfile)
EXEC xp_dirtree #fileLocation, 1, 1
UPDATE #FileNames SET
fileDate = CAST(SUBSTRING(subdirectory,LEN(subdirectory) - 19,10) AS DATE)
,fileTime = CAST(REPLACE(SUBSTRING(subdirectory,LEN(subdirectory) - 8,5),'-',':') AS TIME)
--here's the cursor to loop through all the files
DECLARE c CURSOR FOR
select subdirectory from #FileNames
OPEN c
FETCH NEXT FROM c INTO #fileName
--For each file, bulk insert or what ever you want...
WHILE ##FETCH_STATUS = 0
BEGIN
--set the dynamic with the appropriate delimiters, if you want to keep headers, etc.
SET #sql = 'BULK INSERT Server.dbo.someTable FROM '''+ #fileLocation + #fileName +''' WITH (FIELDTERMINATOR = ''|'',FIRSTROW=2,KEEPNULLS,ROWTERMINATOR = ''0x0a'')'
EXEC(#sql)
--do some other stuff like logging, updating, etc...
END
CLOSE c
DEALLOCATE c
This should do it for you. Just adjust as needed.
DECLARE #intFlag INT
SET #intFlag = 1
WHILE (#intFlag <=48)
BEGIN
PRINT #intFlag
declare #fullpath1 varchar(1000)
select #fullpath1 = '''your_path_here\employee_' + convert(varchar, getdate()- #intFlag , 112) + '.txt'''
declare #cmd1 nvarchar(1000)
select #cmd1 = 'bulk insert [dbo].[your_table_name] from ' + #fullpath1 + ' with (FIELDTERMINATOR = ''\t'', FIRSTROW = 2, ROWTERMINATOR=''0x0a'')'
exec (#cmd1)
SET #intFlag = #intFlag + 1
END
GO

Scripted Restore Using xp_DirTree For Transient Logical BAK File Name SQL Server

Hi I am trying to restore a DB from one server to another where the logical name of the .bak file changes daily with a new timestamp, I have so far found success in determining this name using the following SQL script provided by Jeff Moden here: http://www.sqlservercentral.com/Forums/Topic1200360-391-1.aspx
--===== Create a holding table for the file names
CREATE TABLE #File
(
FileName SYSNAME,
Depth TINYINT,
IsFile TINYINT
)
;
--===== Capture the names in the desired directory
-- (Change "C:\Temp" to the directory of your choice)
INSERT INTO #File
(FileName, Depth, IsFile)
EXEC xp_DirTree '\\filepath\',1,1
;
--===== Find the latest file using the "constant" characters
-- in the file name and the ISO style date.
SELECT TOP 1
FileName
FROM #File
WHERE IsFile = 1
AND FileName LIKE '%.bak' ESCAPE '_'
ORDER BY FileName DESC
;
DROP TABLE #File
My question is now how do I use this as the basis of a scripted restore operation? any help would be very much appreciated!
I have found success by extending the above to cache the directory path and ordered bak files chronologically to determine which to use, then combined the restore operation, with move for logs.
--==CHECK IF DB EXISTS IF IT DOES DROP IT
USE [master]
IF EXISTS(SELECT * FROM sys.databases where name='insert db name')
DROP DATABASE [insert db name]
--==START THE RESTORE PROCESS
DECLARE #FileName varchar(255), #PathToBackup varchar(255), #RestoreFilePath varchar(1000)
DECLARE #Files TABLE (subdirectory varchar(255), depth int, [file] int)
SET NOCOUNT ON
--==SET THE FILEPATH
SET #PathToBackup = '\\insert path to back up'
--insert into memory table using dirtree at a single file level
INSERT INTO #Files
EXEC master.dbo.xp_DirTree #PathToBackup,1,1
SELECT TOP 1
#FileName = [subdirectory]
FROM
#Files
WHERE
-- get where it is a file
[file] = 1
AND
--==FIND THE LOGICAL NAME OF THE BAK FILE FROM THE CHRONILOGICALLY ORDERED LIST
subdirectory LIKE '%.bak'
ORDER BY
-- order descending so newest file will be first by naming convention
subdirectory DESC
IF LEFT(REVERSE(#PathToBackup), 1) != '\'
BEGIN
SET #PathToBackup = #PathToBackup + '\'
END
SET #RestoreFilePath = #PathToBackup + #FileName
--Grab the file path to restore from
SELECT #RestoreFilePath
--BEGIN THE RESTORE TO THE DESIGNATED SERVER
RESTORE DATABASE [insert name of database to restore]
FROM DISK = #RestoreFilePath
WITH
FILE = 1,
--Create transactional log files on target
MOVE 'mdf_file_name' TO 'file_path\file.mdf',
MOVE 'log_file_name' TO 'file_path\file.ldf', REPLACE;
Here is a script that I have partly written and partly collected.
Features include:
Imports exactly one backup file that has any file name with .bak
ending. If there are more files, then imports only one without any
errors.
If no files exist, gives an error.
Kicks users out from the database.
Deletes the backup file
DECLARE #DBName nvarchar(255), #FileName nvarchar(255), #PathToBackup nvarchar(255), #RestoreFilePath nvarchar(1000)
DECLARE #Files TABLE (subdirectory nvarchar(255), depth int, [file] int)
SET XACT_ABORT, NOCOUNT ON
SET #PathToBackup = N'I:\Folder'
-- insert into our memory table using dirtree and a single file level
INSERT INTO #Files
EXEC master.dbo.xp_DirTree #PathToBackup,1,1
SELECT
#FileName = [subdirectory]
FROM
#Files
WHERE
-- get where it is a file
[file] = 1
AND
subdirectory LIKE N'%.bak'
ORDER BY
-- order descending so newest file will be first by naming convention
subdirectory DESC
IF LEFT(REVERSE(#PathToBackup), 1) != N'\'
BEGIN
SET #PathToBackup = #PathToBackup + N'\'
END
SET #RestoreFilePath = #PathToBackup + #FileName
SET #DBName = LEFT(#FileName, LEN(#FileName)-4)
-- SELECT 'Replace AdventureWorks2016CTP3 in this script with #DBName'
SELECT #RestoreFilePath
BEGIN TRY
-- You can try to check if this command works "already":
-- ALTER DATABASE [#DBName] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
ALTER DATABASE [AdventureWorks2016CTP3] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
-- You can try to check if this command works "already":
-- RESTORE DATABASE [#DBName]
RESTORE DATABASE [AdventureWorks2016CTP3]
FROM DISK = #RestoreFilePath
WITH FILE = 1, NOUNLOAD, REPLACE, STATS = 10
END TRY
BEGIN CATCH
-- You can try to check if this command works "already":
-- ALTER DATABASE [#DBName] SET MULTI_USER;
ALTER DATABASE [AdventureWorks2016CTP3] SET MULTI_USER;
; THROW
END CATCH
-- You can try to check if this command works "already":
-- ALTER DATABASE [#DBName] SET MULTI_USER;
ALTER DATABASE [AdventureWorks2016CTP3] SET MULTI_USER;
-- This script is especially for the case where you replication from one location to another using backup and restore.
-- Typically you don't need transaction log backups as all changes will be wiped out on next transfer.
-- You can try to check if this command works "already":
-- ALTER DATABASE [#DBName] SET RECOVERY SIMPLE;
ALTER DATABASE [AdventureWorks2016CTP3] SET RECOVERY SIMPLE;
-- Delete file(s)
-- NOTE: This works only if you give deletion permissions as defined in https://learn.microsoft.com/en-us/sql/database-engine/configure-windows/xp-cmdshell-server-configuration-option?view=sql-server-2017
-- EXAMPLE: exec xp_cmdshell 'del "I:\Directory\AdventureWorks2016CTP3___.bak"'
-- exec xp_cmdshell 'del "' + '#PathToBackup + ''\'' + #FileName + ''"''
DECLARE #cmd NVARCHAR(MAX) = 'xp_cmdshell ''del "' + #PathToBackup + #FileName + '"''';
-- SELECT #cmd
EXEC (#cmd)

Backup database with different name time-related

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

Invalid column name: SQL Server 2008 R2

I have a stored procedure I use to extract binary data from SQL tables to create physical files. I have used it a couple of times on tables with the same structure restored from SQL backups, and it works OK.
Today I wanted to extract some binary data from a new table inside a restored backup. I opened the stored procedure I have been using and set about altering the code. Once I was happy with the changes I tried to execute the 'ALTER' statement. Unfortunetly, both of the column names I have used are 'invalid' despite existing on the the 'Document' table.
I have read a number of other threads regarding 'invalid column name' errors, but the majority of these seem to be typing errors. I've checked my column names numurous times (intelli sense even lets me put in 'Document.Document_ID' and 'Document.Document_Filename' but they still fail).
Any ideas where I am going wrong?
Source:
USE [Example Live]
GO
/****** Object: StoredProcedure [dbo].[FileExport] Script Date: 10/18/2012 11:42:14 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: Chris Murray
-- Create date: 18/10/2012
-- Description: Exports binary file data
-- =============================================
ALTER PROCEDURE [dbo].[FileExport]
-- Add the parameters for the stored procedure here
#OutputFilePath VARCHAR(500) = 'C:\Conv\Example\In\Afiles\'
AS
BEGIN
DECLARE #totrow int
DECLARE #currow int
DECLARE #result int
DECLARE #nsql nvarchar(4000)
DECLARE #sqlStatements table (ID int IDENTITY(1, 1), SqlStatement varchar(max))
INSERT
INTO #sqlStatements
SELECT 'BCP "SELECT Document_Data FROM [Example Live].[dbo].[Document] WHERE Document_ID = '''
+ CAST(Document_ID AS VARCHAR(500)) + '''" queryout ' + #OutputFilePath
+ CAST(Document_Filename AS VARCHAR(500)) + ' -S localhost\SQLEXPRESS2008 -T -f C:\Conv\Example\In\AFiles\Images.fmt'
FROM dbo.Photograph
SET #totrow = ##ROWCOUNT
SET #currow = 1
WHILE #totrow > 0 and #currow <= #totrow
BEGIN
SELECT #nsql = SqlStatement
FROM #sqlStatements
WHERE ID = #currow
EXEC #result = xp_cmdshell #nsql
SET #currow = #currow + 1
END
END
Thanks for the ideas everyone.
The problem was of my own making, and a rookie mistake. I neglected to point the SELECT statement at the correct table..

How can I verify that a file exists in Windows with SQL?

I have a SQL Server running on my Windows Server and, at a specific column of a table, I have the path for a Zip file (which in turn has the source of the data stored in the database). Some of these are not valid (do not match the data in database). I need to make SQL Server verify that these Zip files exist and that they match the column that stores the path and name of the zip file. This way I will delete the wrong file-path column correspondences.
you can use the undocumented proc xp_fileexist will return 1 if it exists and 0 otherwise
SET NOCOUNT ON
DECLARE #iFileExists INT
EXEC master..xp_fileexist 'c:\bla.txt',
#iFileExists OUTPUT
select #iFileExists
You can use xp_fileexist however please note it is undocumented and unsupported.
You can use SQLCLR, however you didn't bother specifying what version of SQL Server you're using, so it may not be relevant - and in any case it is disabled by default, and security policies prevent its use in some places.
You can use a #temp table and xp_cmdshell, however xp_cmdshell is typically disabled for the same reasons as SQLCLR.
/* if you need to enable xp_cmdshell:
exec master..sp_configure 'show adv', 1;
reconfigure with override;
exec master..sp_configure 'xp_cmdshell', 1;
reconfigure with override;
exec master..sp_configure 'show adv', 0;
reconfigure with override;
*/
SET NOCOUNT ON;
DECLARE
#file VARCHAR(1000),
#path VARCHAR(255),
#cmd VARCHAR(2048);
SELECT
#file = 'foo.zip',
#path = 'C:\wherever\';
SELECT #cmd = 'dir /b "' + #path + #file + '"';
CREATE TABLE #x(a VARCHAR(1255));
INSERT #x EXEC master..xp_cmdshell #cmd;
IF EXISTS (SELECT 1 FROM #x WHERE a = #file)
PRINT 'file exists';
ELSE
PRINT 'file does not exist';
DROP TABLE #x;
EDIT based on new requirements. It shows a list of files either in the table or in the database, and indicates whether the file is in only one location or both. It assumes that path + file is <= 900 characters long (merely to be able to use an index on at least one side).
USE tempdb;
GO
CREATE TABLE dbo.files(f VARCHAR(1000));
INSERT dbo.files(f) SELECT 'zip_that_does_not_exist.zip'
UNION ALL SELECT 'c:\path\file_that_does_not_exist.zip'
UNION ALL SELECT 'c:\path\file_that_exists.zip'
UNION ALL SELECT 'zip_that_exists.zip';
DECLARE
#path VARCHAR(255),
#cmd VARCHAR(2048);
SELECT
#path = path_column,
#cmd = 'dir /b "' + path_column + '"'
FROM
dbo.table_that_holds_path;
CREATE TABLE #x(f VARCHAR(900) UNIQUE);
INSERT #x EXEC master..xp_cmdshell #cmd;
DELETE #x WHERE f IS NULL;
UPDATE #x SET f = LOWER(f);
WITH f AS
(
SELECT f = REPLACE(LOWER(f), LOWER(#path), '')
FROM dbo.files
)
SELECT
[file] = COALESCE(x.f, f.f),
[status] = CASE
WHEN x.f IS NULL THEN 'in database, not in folder'
WHEN f.f IS NULL THEN 'in folder, not in database'
ELSE 'in both' END
FROM
f FULL OUTER JOIN #x AS x
ON x.f = f.f;
DROP TABLE #x, dbo.files;