Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2000 Forums
 SQL Server Administration (2000)
 Scripting Maintenance Plan creation

Author  Topic 

Kuda
Starting Member

17 Posts

Posted - 2004-06-09 : 13:39:18
OK so this has turned into an excersize in frustration...
SQL2000 SP3
Win2K Server SP4
All current patches/hotfixes/etc. etc.

Because of the fact that a failure in a single step in a job shows the whole job (and hence a whole maintenance plan) as having failed, I want to create a separate maintenance plan for each database on a given server. To that end, I created a single maintenance plan for a single database, then turned around and used EM to script the various jobs. Then I went and consolidated that all into a single script and added code to make it a little more dynamic (see below for full script)... at any rate, the script runs fine, and creates the appropriate maintenance plans and the jobs all apparently correctly. HOWEVER, when trying to view the newly created plan from EM, I get the following error:

The job '[pick one of the job names for this plan]' could not be parsed. Do you want to ignore it and continue?

Selecting Yes will result in a prompt for each job in the plan, eventually resulting in the normal tabbed view of the maintenance plan with no data in any of the controls. Selecting No will just abort the display of the plan completely. Either way, EM becomes unstable and throws another error (doesn't matter what you're trying to do):

Error 5: [SQL-DMO]Code execution exception: EXCEPTION_ACCESS_VIOLATION

after which you may or may not be able to do anything... it will eventually crash and burn.
So, I guess the question is - is this a bug, or am I doing something heinously wrong in my script (aside from using cursors that is :)?
---------------------------------------------------------

DECLARE @DBNAME SYSNAME,
@DBRECOVERY VARCHAR(128),
@PLANNAME SYSNAME,
@PLANID UNIQUEIDENTIFIER,
@JOBNAME SYSNAME,
@JOBID UNIQUEIDENTIFIER,
@RETURNCODE INT,
@CMD VARCHAR(512),
@ERRMSG VARCHAR(512),
@LOOP CURSOR

IF (SELECT COUNT(*) FROM MSDB.DBO.SYSCATEGORIES WHERE NAME = N'Database Maintenance') < 1
EXECUTE MSDB.DBO.SP_ADD_CATEGORY @NAME = N'Database Maintenance'

/*
SET @LOOP = CURSOR FOR (
SELECT NAME
FROM SYSDATABASES
WHERE NAME <> 'tempdb'
)
*/

SET @LOOP = CURSOR FOR (
SELECT NAME
FROM SYSDATABASES
WHERE NAME = 'MPTestDB'
)

OPEN @LOOP
FETCH NEXT
FROM @LOOP
INTO @DBNAME

WHILE @@FETCH_STATUS = 0
BEGIN
BEGIN TRANSACTION
SELECT @PLANNAME = @DBNAME, @PLANID = NULL, @JOBID = NULL,
@DBRECOVERY = CAST(DATABASEPROPERTYEX(@DBNAME, 'Recovery') AS VARCHAR(128)),
@RETURNCODE = 0

--CREATE EMPTY MAINTENANCE PLAN
EXECUTE @RETURNCODE = MSDB.DBO.SP_ADD_MAINTENANCE_PLAN @PLAN_NAME = @PLANNAME, @PLAN_ID = @PLANID OUTPUT
IF (@@ERROR <> 0 OR @ReturnCode <> 0)
BEGIN
SELECT @ERRMSG = 'Unable to create maintenance plan ''' + @PLANNAME + ''''
RAISERROR(@ERRMSG, 16, 1)
GOTO QuitWithRollback
END

--ASSOCIATE DATABASE TO MAINTENANCE PLAN
EXECUTE @RETURNCODE = MSDB.DBO.SP_ADD_MAINTENANCE_PLAN_DB @PLAN_ID = @PLANID, @DB_NAME = @DBNAME
IF (@@ERROR <> 0 OR @ReturnCode <> 0)
BEGIN
SELECT @ERRMSG = 'Unable to associate database to maintenance plan ''' + @PLANNAME + ''''
RAISERROR(@ERRMSG, 16, 1)
GOTO QuitWithRollback
END

--CREATE JOBS FOR THE PLAN

--DB BACKUP JOB
SELECT @JOBNAME = 'DB Backup Job for DB Maintenance Plan ''' + @PLANNAME + ''''

SELECT @JOBID = JOB_ID
FROM MSDB.DBO.SYSJOBS
WHERE NAME = @JOBNAME

IF @JOBID IS NOT NULL
BEGIN
--CHECK IF THE JOB IS A MULTI-SERVER JOB
IF EXISTS (SELECT * FROM MSDB.DBO.SYSJOBSERVERS WHERE JOB_ID = @JOBID AND SERVER_ID <> 0)
BEGIN
--THERE IS, SO ABORT THE SCRIPT
SELECT @ERRMSG = 'Unable to import job ''' + @JOBNAME + ''' since there is already a multi-server job with this name.'
RAISERROR (@ERRMSG, 16, 1)
GOTO QuitWithRollback
END
ELSE
--DELETE THE [LOCAL] JOB
BEGIN
EXECUTE MSDB.DBO.SP_DELETE_JOB @JOB_NAME = @JOBNAME
SELECT @JOBID = NULL
END
END

BEGIN
--ADD THE JOB
EXECUTE @RETURNCODE = MSDB.DBO.SP_ADD_JOB @JOB_ID = @JOBID OUTPUT,
@JOB_NAME = @JOBNAME,
@OWNER_LOGIN_NAME = N'SA',
@DESCRIPTION = @JOBNAME,
@CATEGORY_NAME = 'Database Maintenance',
@ENABLED = 1,
@NOTIFY_LEVEL_EMAIL = 0,
@NOTIFY_LEVEL_PAGE = 0,
@NOTIFY_LEVEL_NETSEND = 2,
@NOTIFY_NETSEND_OPERATOR_NAME = N'John',
@NOTIFY_LEVEL_EVENTLOG = 2,
@DELETE_LEVEL = 0
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback

--ADD THE JOB STEPS
SELECT @CMD = 'EXECUTE MASTER.DBO.XP_SQLMAINT N''-PlanID ' + CAST(@PLANID AS VARCHAR(100)) + ' -WriteHistory -VrfyBackup -BkUpOnlyIfClean -CkDBRepair -BkUpMedia DISK -BkUpDB "\\JPD-FILE\Backup\SQL\JPD-CRM" -DelBkUps 2WEEKS -CrBkSubDir -BkExt "BAK"'''
EXECUTE @RETURNCODE = MSDB.DBO.SP_ADD_JOBSTEP @JOB_ID = @JOBID,
@STEP_ID = 1,
@STEP_NAME = N'Step 1',
@COMMAND = @CMD,
@DATABASE_NAME = N'MASTER',
@SERVER = N'',
@DATABASE_USER_NAME = N'',
@SUBSYSTEM = N'TSQL',
@CMDEXEC_SUCCESS_CODE = 0,
@FLAGS = 4,
@RETRY_ATTEMPTS = 0,
@RETRY_INTERVAL = 0,
@OUTPUT_FILE_NAME = N'',
@ON_SUCCESS_STEP_ID = 0,
@ON_SUCCESS_ACTION = 1,
@ON_FAIL_STEP_ID = 0,
@ON_FAIL_ACTION = 2
IF (@@ERROR <> 0 OR @RETURNCODE <> 0) GOTO QuitWithRollback
EXECUTE @RETURNCODE = MSDB.DBO.SP_UPDATE_JOB @JOB_ID = @JOBID, @START_STEP_ID = 1
IF (@@ERROR <> 0 OR @RETURNCODE <> 0) GOTO QuitWithRollback

--ADD THE JOB SCHEDULES
EXECUTE @RETURNCODE = MSDB.DBO.SP_ADD_JOBSCHEDULE @JOB_ID = @JOBID,
@NAME = N'Schedule 1',
@ENABLED = 1,
@FREQ_TYPE = 8,
@ACTIVE_START_DATE = 20040101,
@ACTIVE_START_TIME = 20000,
@FREQ_INTERVAL = 1,
@FREQ_SUBDAY_TYPE = 1,
@FREQ_SUBDAY_INTERVAL = 0,
@FREQ_RELATIVE_INTERVAL = 0,
@FREQ_RECURRENCE_FACTOR = 1,
@ACTIVE_END_DATE = 99991231,
@ACTIVE_END_TIME = 235959
IF (@@ERROR <> 0 OR @RETURNCODE <> 0) GOTO QuitWithRollback

--ADD THE TARGET SERVERS
EXECUTE @RETURNCODE = MSDB.DBO.SP_ADD_JOBSERVER @JOB_ID = @JOBID,
@SERVER_NAME = N'(local)'
IF (@@ERROR <> 0 OR @RETURNCODE <> 0) GOTO QuitWithRollback
END
EXECUTE MSDB.DBO.SP_ADD_MAINTENANCE_PLAN_JOB @PLAN_ID = @PLANID, @JOB_ID = @JOBID

--INTEGRITY CHECKS JOB
SELECT @RETURNCODE = 0, @JOBID = NULL, @JOBNAME = 'Integrity Checks Job for DB Maintenance Plan ''' + @PLANNAME + ''''

SELECT @JOBID = JOB_ID
FROM MSDB.DBO.SYSJOBS
WHERE NAME = @JOBNAME

IF @JOBID IS NOT NULL
BEGIN
--CHECK IF THE JOB IS A MULTI-SERVER JOB
IF EXISTS (SELECT * FROM MSDB.DBO.SYSJOBSERVERS WHERE JOB_ID = @JOBID AND SERVER_ID <> 0)
BEGIN
--THERE IS, SO ABORT THE SCRIPT
SELECT @ERRMSG = 'Unable to import job ''' + @JOBNAME + ''' since there is already a multi-server job with this name.'
RAISERROR (@ERRMSG, 16, 1)
GOTO QuitWithRollback
END
ELSE
--DELETE THE [LOCAL] JOB
BEGIN
EXECUTE MSDB.DBO.SP_DELETE_JOB @JOB_NAME = @JOBNAME
SELECT @JOBID = NULL
END
END

BEGIN
--ADD THE JOB
EXECUTE @RETURNCODE = MSDB.DBO.SP_ADD_JOB @JOB_ID = @JOBID OUTPUT,
@JOB_NAME = @JOBNAME,
@OWNER_LOGIN_NAME = N'SA',
@DESCRIPTION = @JOBNAME,
@CATEGORY_NAME = N'Database Maintenance',
@ENABLED = 1,
@NOTIFY_LEVEL_EMAIL = 0,
@NOTIFY_LEVEL_PAGE = 0,
@NOTIFY_LEVEL_NETSEND = 2,
@NOTIFY_NETSEND_OPERATOR_NAME = N'John',
@NOTIFY_LEVEL_EVENTLOG = 2,
@DELETE_LEVEL= 0
IF (@@ERROR <> 0 OR @RETURNCODE <> 0) GOTO QuitWithRollback

--ADD THE JOB STEPS
SELECT @CMD = 'EXECUTE MASTER.DBO.XP_SQLMAINT N''-PlanID ' + CAST(@PLANID AS VARCHAR(100)) + ' -WriteHistory -CkDBRepair '''
EXECUTE @RETURNCODE = MSDB.DBO.SP_ADD_JOBSTEP @JOB_ID = @JOBID,
@STEP_ID = 1,
@STEP_NAME = N'Step 1',
@COMMAND = @CMD,
@DATABASE_NAME = N'MASTER',
@SERVER = N'',
@DATABASE_USER_NAME = N'',
@SUBSYSTEM = N'TSQL',
@CMDEXEC_SUCCESS_CODE = 0,
@FLAGS = 4,
@RETRY_ATTEMPTS = 0,
@RETRY_INTERVAL = 0,
@OUTPUT_FILE_NAME = N'',
@ON_SUCCESS_STEP_ID = 0,
@ON_SUCCESS_ACTION = 1,
@ON_FAIL_STEP_ID = 0,
@ON_FAIL_ACTION = 2
IF (@@ERROR <> 0 OR @RETURNCODE <> 0) GOTO QuitWithRollback
EXECUTE @RETURNCODE = MSDB.DBO.SP_UPDATE_JOB @JOB_ID = @JOBID,
@START_STEP_ID = 1
IF (@@ERROR <> 0 OR @RETURNCODE <> 0) GOTO QuitWithRollback

--ADD THE JOB SCHEDULES
EXECUTE @RETURNCODE = MSDB.DBO.SP_ADD_JOBSCHEDULE @JOB_ID = @JOBID,
@NAME = N'Schedule 1',
@ENABLED = 1,
@FREQ_TYPE = 8,
@ACTIVE_START_DATE = 20040101,
@ACTIVE_START_TIME = 0,
@FREQ_INTERVAL = 1,
@FREQ_SUBDAY_TYPE = 1,
@FREQ_SUBDAY_INTERVAL = 0,
@FREQ_RELATIVE_INTERVAL = 0,
@FREQ_RECURRENCE_FACTOR = 1,
@ACTIVE_END_DATE = 99991231,
@ACTIVE_END_TIME = 235959
IF (@@ERROR <> 0 OR @RETURNCODE <> 0) GOTO QuitWithRollback

--ADD THE TARGET SERVERS
EXECUTE @RETURNCODE = MSDB.DBO.SP_ADD_JOBSERVER @JOB_ID = @JOBID,
@SERVER_NAME = N'(local)'
IF (@@ERROR <> 0 OR @RETURNCODE <> 0) GOTO QuitWithRollback
END
EXECUTE MSDB.DBO.SP_ADD_MAINTENANCE_PLAN_JOB @PLAN_ID = @PLANID, @JOB_ID = @JOBID

--OPTIMIZATIONS JOB
SELECT @RETURNCODE = 0, @JOBID = NULL, @JOBNAME = 'Optimizations Job for DB Maintenance Plan ''' + @PLANNAME + ''''

SELECT @JOBID = JOB_ID
FROM MSDB.DBO.SYSJOBS
WHERE NAME = @JOBNAME

IF @JOBID IS NOT NULL
BEGIN
--CHECK IF THE JOB IS A MULTI-SERVER JOB
IF EXISTS (SELECT * FROM MSDB.DBO.SYSJOBSERVERS WHERE JOB_ID = @JOBID AND SERVER_ID <> 0)
BEGIN
--THERE IS, SO ABORT THE SCRIPT
SELECT @ERRMSG = 'Unable to import job ''' + @JOBNAME + ''' since there is already a multi-server job with this name.'
RAISERROR (@ERRMSG, 16, 1)
GOTO QuitWithRollback
END
ELSE
--DELETE THE [LOCAL] JOB
BEGIN
EXECUTE MSDB.DBO.SP_DELETE_JOB @JOB_NAME = @JOBNAME
SELECT @JOBID = NULL
END
END

BEGIN
--ADD THE JOB
EXECUTE @RETURNCODE = MSDB.DBO.SP_ADD_JOB @JOB_ID = @JOBID OUTPUT,
@JOB_NAME = @JOBNAME,
@OWNER_LOGIN_NAME = N'SA',
@DESCRIPTION = @JOBNAME,
@CATEGORY_NAME = N'Database Maintenance',
@ENABLED = 1,
@NOTIFY_LEVEL_EMAIL = 0,
@NOTIFY_LEVEL_PAGE = 0,
@NOTIFY_LEVEL_NETSEND = 2,
@NOTIFY_NETSEND_OPERATOR_NAME = N'John',
@NOTIFY_LEVEL_EVENTLOG = 2,
@DELETE_LEVEL= 0
IF (@@ERROR <> 0 OR @RETURNCODE <> 0) GOTO QuitWithRollback

--ADD THE JOB STEPS
SELECT @CMD = 'EXECUTE MASTER.DBO.XP_SQLMAINT N''-PlanID ' + CAST(@PLANID AS VARCHAR(100)) + ' -WriteHistory -RebldIdx 10 -RmUnusedSpace 25 10 '''
EXECUTE @RETURNCODE = MSDB.DBO.SP_ADD_JOBSTEP @JOB_ID = @JOBID,
@STEP_ID = 1,
@STEP_NAME = N'STEP 1',
@COMMAND = @CMD,
@DATABASE_NAME = N'MASTER',
@SERVER = N'',
@DATABASE_USER_NAME = N'',
@SUBSYSTEM = N'TSQL',
@CMDEXEC_SUCCESS_CODE = 0,
@FLAGS = 4,
@RETRY_ATTEMPTS = 0,
@RETRY_INTERVAL = 0,
@OUTPUT_FILE_NAME = N'',
@ON_SUCCESS_STEP_ID = 0,
@ON_SUCCESS_ACTION = 1,
@ON_FAIL_STEP_ID = 0,
@ON_FAIL_ACTION = 2
IF (@@ERROR <> 0 OR @RETURNCODE <> 0) GOTO QuitWithRollback
EXECUTE @RETURNCODE = MSDB.DBO.SP_UPDATE_JOB @JOB_ID = @JOBID,
@START_STEP_ID = 1
IF (@@ERROR <> 0 OR @RETURNCODE <> 0) GOTO QuitWithRollback

--ADD THE JOB SCHEDULES
EXECUTE @RETURNCODE = MSDB.DBO.SP_ADD_JOBSCHEDULE @JOB_ID = @JOBID,
@NAME = N'Schedule 1',
@ENABLED = 1,
@FREQ_TYPE = 8,
@ACTIVE_START_DATE = 20040101,
@ACTIVE_START_TIME = 10000,
@FREQ_INTERVAL = 1,
@FREQ_SUBDAY_TYPE = 1,
@FREQ_SUBDAY_INTERVAL = 0,
@FREQ_RELATIVE_INTERVAL = 0,
@FREQ_RECURRENCE_FACTOR = 1,
@ACTIVE_END_DATE = 99991231,
@ACTIVE_END_TIME = 235959
IF (@@ERROR <> 0 OR @RETURNCODE <> 0) GOTO QuitWithRollback

--ADD THE TARGET SERVERS
EXECUTE @RETURNCODE = MSDB.DBO.SP_ADD_JOBSERVER @JOB_ID = @JOBID,
@SERVER_NAME = N'(local)'
IF (@@ERROR <> 0 OR @RETURNCODE <> 0) GOTO QuitWithRollback
END
EXECUTE MSDB.DBO.SP_ADD_MAINTENANCE_PLAN_JOB @PLAN_ID = @PLANID, @JOB_ID = @JOBID

--TRANSACTION LOG BACKUP JOB
IF @DBRECOVERY <> 'SIMPLE'
BEGIN
SELECT @RETURNCODE = 0, @JOBID = NULL, @JOBNAME = 'Transaction Log Backup Job for DB Maintenance Plan ''' + @PLANNAME + ''''

SELECT @JOBID = JOB_ID
FROM MSDB.DBO.SYSJOBS
WHERE NAME = @JOBNAME

IF @JOBID IS NOT NULL
BEGIN
--CHECK IF THE JOB IS A MULTI-SERVER JOB
IF EXISTS (SELECT * FROM MSDB.DBO.SYSJOBSERVERS WHERE JOB_ID = @JOBID AND SERVER_ID <> 0)
BEGIN
--THERE IS, SO ABORT THE SCRIPT
SELECT @ERRMSG = 'Unable to import job ''' + @JOBNAME + ''' since there is already a multi-server job with this name.'
RAISERROR (@ERRMSG, 16, 1)
GOTO QuitWithRollback
END
ELSE
--DELETE THE [LOCAL] JOB
BEGIN
EXECUTE MSDB.DBO.SP_DELETE_JOB @JOB_NAME = @JOBNAME
SELECT @JOBID = NULL
END
END

BEGIN
--ADD THE JOB
EXECUTE @RETURNCODE = MSDB.DBO.SP_ADD_JOB @JOB_ID = @JOBID OUTPUT,
@JOB_NAME = @JOBNAME,
@OWNER_LOGIN_NAME = N'SA',
@DESCRIPTION = @JOBNAME,
@CATEGORY_NAME = N'Database Maintenance',
@ENABLED = 1,
@NOTIFY_LEVEL_EMAIL = 0,
@NOTIFY_LEVEL_PAGE = 0,
@NOTIFY_LEVEL_NETSEND = 2,
@NOTIFY_NETSEND_OPERATOR_NAME = N'John',
@NOTIFY_LEVEL_EVENTLOG = 2,
@DELETE_LEVEL= 0
IF (@@ERROR <> 0 OR @RETURNCODE <> 0) GOTO QuitWithRollback

--ADD THE JOB STEPS
SELECT @CMD = 'EXECUTE MASTER.DBO.XP_SQLMAINT N''-PlanID ' + CAST(@PLANID AS VARCHAR(100)) + ' -WriteHistory -VrfyBackup -BkUpOnlyIfClean -CkDBRepair -BkUpMedia DISK -BkUpLog "\\JPD-FILE\Backup\SQL\JPD-CRM" -DelBkUps 2WEEKS -CrBkSubDir -BkExt "TRN"'''
EXECUTE @RETURNCODE = MSDB.DBO.SP_ADD_JOBSTEP @JOB_ID = @JOBID,
@STEP_ID = 1,
@STEP_NAME = N'Step 1',
@COMMAND = @CMD,
@DATABASE_NAME = N'MASTER',
@SERVER = N'',
@DATABASE_USER_NAME = N'',
@SUBSYSTEM = N'TSQL',
@CMDEXEC_SUCCESS_CODE = 0,
@FLAGS = 4,
@RETRY_ATTEMPTS = 0,
@RETRY_INTERVAL = 0,
@OUTPUT_FILE_NAME = N'',
@ON_SUCCESS_STEP_ID = 0,
@ON_SUCCESS_ACTION = 1,
@ON_FAIL_STEP_ID = 0,
@ON_FAIL_ACTION = 2
IF (@@ERROR <> 0 OR @RETURNCODE <> 0) GOTO QuitWithRollback
EXECUTE @RETURNCODE = MSDB.DBO.SP_UPDATE_JOB @JOB_ID = @JOBID,
@START_STEP_ID = 1
IF (@@ERROR <> 0 OR @RETURNCODE <> 0) GOTO QuitWithRollback

--ADD THE JOB SCHEDULES
EXECUTE @RETURNCODE = MSDB.DBO.SP_ADD_JOBSCHEDULE @JOB_ID = @JOBID,
@NAME = N'Schedule 1',
@ENABLED = 1,
@FREQ_TYPE = 4,
@ACTIVE_START_DATE = 20040607,
@ACTIVE_START_TIME = 80000,
@FREQ_INTERVAL = 1,
@FREQ_SUBDAY_TYPE = 8,
@FREQ_SUBDAY_INTERVAL = 1,
@FREQ_RELATIVE_INTERVAL = 0,
@FREQ_RECURRENCE_FACTOR = 0,
@ACTIVE_END_DATE = 99991231,
@ACTIVE_END_TIME = 205959
IF (@@ERROR <> 0 OR @RETURNCODE <> 0) GOTO QuitWithRollback

--ADD THE TARGET SERVERS
EXECUTE @RETURNCODE = MSDB.DBO.SP_ADD_JOBSERVER @JOB_ID = @JOBID,
@SERVER_NAME = N'(local)'
IF (@@ERROR <> 0 OR @RETURNCODE <> 0) GOTO QuitWithRollback
END
EXECUTE MSDB.DBO.SP_ADD_MAINTENANCE_PLAN_JOB @PLAN_ID = @PLANID, @JOB_ID = @JOBID
END

COMMIT TRANSACTION

FETCH NEXT
FROM @LOOP
INTO @DBNAME
END
GOTO EndSave

QuitWithRollback:
IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION

EndSave:
CLOSE @LOOP
DEALLOCATE @LOOP


==========================================================
But who can save the sane? Some beings just can't change...

eyechart
Master Smack Fu Yak Hacker

3575 Posts

Posted - 2004-06-09 : 14:06:26
Why don't you code your own maintenance scripts and schedule them using SQL agent instead? The maintenance jobs created by the Maintenance plan wizard basically suck and will drive you crazy if you use them long enough.

I realize that this post doesn't help your current situation, but with all the effort you have put into your script you could have been done already with creating your own "maintenance plan free" jobs.


-ec
Go to Top of Page

tkizer
Almighty SQL Goddess

38200 Posts

Posted - 2004-06-09 : 14:12:16
Here's one that I created for backups. It deletes files that are older than two days. It is overly commented on purpose.



----------------------------------------------------------------------------------------------------
-- OBJECT NAME : isp_Backup
--
-- AUTHOR : Tara Duggan
-- DATE : December 18, 2003
--
-- INPUTS : @Path - location of the backups
-- @dbType - which databases to backup - All, System, or User
-- OUTPUTS : None
-- DEPENDENCIES : None
--
-- DESCRIPTION : This stored procedure performs a full backup on all of the user databases
--
-- EXAMPLES (optional) : EXEC isp_Backup @Path = 'C:\MSSQL\Backup\', @dbType = 'All'
--
-- MODIFICATION HISTORY :
----------------------------------------------------------------------------------------------------
--
----------------------------------------------------------------------------------------------------
CREATE PROC isp_Backup
(@Path VARCHAR(100), @dbType VARCHAR(6))
AS

SET NOCOUNT ON

DECLARE @Now CHAR(14) -- current date in the form of yyyymmddhhmmss
DECLARE @DBName SYSNAME -- stores the database name that is currently being processed
DECLARE @cmd SYSNAME -- stores the dynamically created DOS command
DECLARE @Result INT -- stores the result of the dir DOS command
DECLARE @RowCnt INT -- stores @@ROWCOUNT
DECLARE @filename VARCHAR(200) -- stores the path and file name of the BAK file

CREATE TABLE #WhichDatabase
(
dbName SYSNAME NOT NULL
)

-- Get the list of the databases to be backed up
IF @dbType = 'All'

INSERT INTO #WhichDatabase (dbName)
SELECT [name]
FROM master.dbo.sysdatabases
WHERE [name] <> 'tempdb'
ORDER BY [name]

ELSE
BEGIN

IF @dbType = 'System'

INSERT INTO #WhichDatabase (dbName)
SELECT [name]
FROM master.dbo.sysdatabases
WHERE [name] IN ('master', 'model', 'msdb')
ORDER BY [name]

ELSE
BEGIN

IF @dbType = 'User'

INSERT INTO #WhichDatabase (dbName)
SELECT [name]
FROM master.dbo.sysdatabases
WHERE [name] NOT IN ('master', 'model', 'msdb', 'tempdb')
ORDER BY [name]

ELSE
BEGIN

DROP TABLE #WhichDatabase

RETURN -1

END

END

END

-- Get the database to be backed up
SELECT TOP 1 @DBName = dbName
FROM #WhichDatabase

SET @RowCnt = @@ROWCOUNT

-- Iterate throught the temp table until no more databases need to be backed up
WHILE @RowCnt <> 0
BEGIN

-- Get the current date using style 120, remove all dashes, spaces, and colons
SELECT @Now = REPLACE(REPLACE(REPLACE(CONVERT(VARCHAR(50), GETDATE(), 120), '-', ''), ' ', ''), ':', '')

-- Build the .BAK path and file name
SELECT @filename = @Path + @DBName + '\' + @DBName + '_' + @Now + '.BAK'

-- Build the dir command that will check to see if the directory exists
SELECT @cmd = 'dir ' + @Path + @DBName

-- Run the dir command, put output of xp_cmdshell into @result
EXEC @result = master.dbo.xp_cmdshell @cmd

-- If the directory does not exist, we must create it
IF @result <> 0
BEGIN

-- Build the mkdir command
SELECT @cmd = 'mkdir ' + @Path + @DBName

-- Create the directory
EXEC master.dbo.xp_cmdshell @cmd, NO_OUTPUT

END
-- The directory exists, so let's delete files older than two days
ELSE
BEGIN

-- Stores the name of the file to be deleted
DECLARE @WhichFile VARCHAR(1000)

CREATE TABLE #DeleteOldFiles
(
DirInfo VARCHAR(7000)
)

-- Build the command that will list out all of the files in a directory
SELECT @cmd = 'dir ' + @Path + @DBName + ' /OD'

-- Run the dir command and put the results into a temp table
INSERT INTO #DeleteOldFiles
EXEC master.dbo.xp_cmdshell @cmd

-- Delete all rows from the temp table except the ones that correspond to the files to be deleted
DELETE
FROM #DeleteOldFiles
WHERE ISDATE(SUBSTRING(DirInfo, 1, 10)) = 0 OR DirInfo LIKE '%<DIR>%' OR SUBSTRING(DirInfo, 1, 10) >= GETDATE() - 2

-- Get the file name portion of the row that corresponds to the file to be deleted
SELECT TOP 1 @WhichFile = SUBSTRING(DirInfo, LEN(DirInfo) - PATINDEX('% %', REVERSE(DirInfo)) + 2, LEN(DirInfo))
FROM #DeleteOldFiles


SET @RowCnt = @@ROWCOUNT

-- Interate through the temp table until there are no more files to delete
WHILE @RowCnt <> 0
BEGIN

-- Build the del command
SELECT @cmd = 'del ' + @Path + + @DBName + '\' + @WhichFile + ' /Q /F'

-- Delete the file
EXEC master.dbo.xp_cmdshell @cmd, NO_OUTPUT

-- To move to the next file, the current file name needs to be deleted from the temp table
DELETE
FROM #DeleteOldFiles
WHERE SUBSTRING(DirInfo, LEN(DirInfo) - PATINDEX('% %', REVERSE(DirInfo)) + 2, LEN(DirInfo)) = @WhichFile

-- Get the file name portion of the row that corresponds to the file to be deleted
SELECT TOP 1 @WhichFile = SUBSTRING(DirInfo, LEN(DirInfo) - PATINDEX('% %', REVERSE(DirInfo)) + 2, LEN(DirInfo))
FROM #DeleteOldFiles

SET @RowCnt = @@ROWCOUNT

END

DROP TABLE #DeleteOldFiles

END

-- Backup the database
BACKUP DATABASE @DBName
TO DISK = @filename
WITH INIT

-- To move onto the next database, the current database name needs to be deleted from the temp table
DELETE
FROM #WhichDatabase
WHERE dbName = @DBName

-- Get the database to be backed up
SELECT TOP 1 @DBName = dbName
FROM #WhichDatabase

SET @RowCnt = @@ROWCOUNT

-- Let the system rest for 5 seconds before starting on the next backup
WAITFOR DELAY '00:00:05'

END

DROP TABLE #WhichDatabase

SET NOCOUNT OFF

RETURN 0



Tara
Go to Top of Page
   

- Advertisement -