{"id":2561,"date":"2007-10-16T16:45:00","date_gmt":"2007-10-16T16:45:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/do-i-ask-too-much-of-my-beloved-rdbms\/"},"modified":"2016-07-28T10:49:11","modified_gmt":"2016-07-28T10:49:11","slug":"do-i-ask-too-much-of-my-beloved-rdbms","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/blogs\/do-i-ask-too-much-of-my-beloved-rdbms\/","title":{"rendered":"Do I Ask Too Much of My Beloved RDBMS?"},"content":{"rendered":"<p>OK&#160;Simple-Talkers I have a interesting situation driving be nuttier than squirrel poo.<\/p>\n<p>I have the following 2 steps in a scheduled SQL job I use to backup logs.&#160; If for some reason a log file does not exist it will throw the error 22049.&#160; I trap for it and want it to proceed with the remainder of the step before completing the job.&#160; The issue I have is that if any error is raised in a SQL job step you have limited options: Quit Reporting Success, Quit Reporting Failure, or Go To Step X.&#160; I need it to <u>complete<\/u> the step before making that decision.&#160; That is not one of the options.&#160; The action occurs on the first error &#8211; whether or not the error is handled gently.&#160; If any error occurs the step stops.<\/p>\n<p>Do I ask too much of the RDBMS I love so?!?<\/p>\n<p><strong>&#8211;STEP 1&#160; BACK UP LOGS<\/strong><\/p>\n<p>DECLARE @folder_name nvarchar(500)<br \/>DECLARE @name sysname<br \/>DECLARE @file nvarchar (1000)<\/p>\n<p>DECLARE @dirtree&#160;table (subdirectory nvarchar(255), depth int)<\/p>\n<p>SET @folder_name = &#8216;\\SQLBackupBackup&#8217;<br \/>&#160;&#160;&#160;<br \/>INSERT @dirtree<br \/>EXEC master.sys.xp_dirtree @folder_name<\/p>\n<p>DECLARE backup_cur&#160;CURSOR FOR<br \/>&#160;SELECT name <br \/>&#160;FROM master.sys.databases<br \/>&#160;WHERE&#160;name NOT IN (&#8216;master&#8217;, &#8216;model&#8217;, &#8216;msdb&#8217;, &#8216;tempdb&#8217;)<br \/>&#160;&#160;AND&#160;recovery_model_desc &lt;&gt; &#8216;SIMPLE&#8217;<br \/>&#160;&#160;AND&#160;DATEDIFF(day, create_date, GETDATE()) &gt;= 1&#160;&#160;&#8211; Must perform 1 full backup before you can do log backups.<br \/>&#160;&#160;AND&#160;name NOT IN <br \/>&#160;&#160;&#160;(<br \/>&#160;&#160;&#160;SELECT database_nm <br \/>&#160;&#160;&#160;FROM iDBA.backups.ignore_databases<br \/>&#160;&#160;&#160;)<br \/>&#160;ORDER BY name<\/p>\n<p>OPEN backup_cur<\/p>\n<p>FETCH NEXT FROM backup_cur INTO @name<\/p>\n<p>WHILE @@FETCH_STATUS = 0<br \/>&#160;BEGIN<br \/>&#160;&#160;SET @folder_name = &#8216;\\SQLBackupBackup&#8217; + @name<\/p>\n<p>&#160;&#160;IF NOT EXISTS (SELECT 1 FROM @dirtree WHERE subdirectory = @name)<br \/>&#160;&#160;&#160;EXECUTE master.dbo.xp_create_subdir @folder_name<\/p>\n<p>&#160;&#160;&#160;SET @file = @folder_name + &#8221; + @name + &#8216;_tlog_&#8217; + CONVERT(NVARCHAR, GETDATE(), 112) + LEFT(REPLACE(CONVERT(VARCHAR, GETDATE(), 108), &#8216;:&#8217;, &#8221;), 4)+ &#8216;.trn&#8217;<br \/>&#160;&#160;&#160;<br \/>&#160;&#160;&#160;BACKUP LOG @name<br \/>&#160;&#160;&#160;TO DISK = @file<br \/>&#160;&#160;&#160;WITH RETAINDAYS = 1<\/p>\n<p>&#160;&#160;&#160;INSERT iDBA.backups.db_log_backups<br \/>&#160;&#160;&#160;VALUES (@name, @file, GETDATE(), DATEADD(dd, 1, GETDATE()), NULL)<\/p>\n<p>&#160;&#160;&#160;FETCH NEXT FROM backup_cur INTO @name<br \/>&#160;&#160;END<\/p>\n<p>CLOSE backup_cur<br \/>DEALLOCATE backup_cur<\/p>\n<p><strong>&#8211;STEP 2 DELETE EXPIRED BACKUP FILES<\/strong><\/p>\n<p>BEGIN TRAN<br \/>&#160;DECLARE @backup_file&#160;nvarchar(1000)<\/p>\n<p>&#160;DECLARE del_cur CURSOR FOR<br \/>&#160;&#160;SELECT backup_full_file_nm<br \/>&#160;&#160;FROM iDBA.backups.db_log_backups<br \/>&#160;&#160;WHERE database_nm NOT IN (&#8216;master&#8217;, &#8216;model&#8217;, &#8216;msdb&#8217;, &#8216;tempdb&#8217;)<br \/>&#160;&#160;&#160;AND&#160;backup_expiration_dt &lt;= GETDATE()<br \/>&#160;&#160;&#160;AND backup_removed_dt IS NULL<br \/>&#160;&#160;ORDER BY database_nm<\/p>\n<p>&#160;OPEN del_cur<br \/>&#160;&#160;<br \/>&#160;FETCH NEXT FROM del_cur INTO @backup_file<\/p>\n<p>&#160;WHILE @@FETCH_STATUS = 0<br \/>&#160;&#160;BEGIN<br \/>&#160;&#160;&#160;BEGIN TRY<br \/>&#160;&#160;&#160;&#160;EXEC master.sys.xp_delete_file 0, @backup_file<br \/>&#160;&#160;&#160;&#160;PRINT CAST(&#8216;Deleted File:&#160; &#8216; + @backup_file AS nvarchar(120))<br \/>&#160;&#160;&#160;END TRY<\/p>\n<p>&#160;&#160;&#160;BEGIN CATCH<br \/>&#160;&#160;&#160;&#160;IF @@ERROR &lt;&gt; 22049<br \/>&#160;&#160;&#160;&#160;&#160;BEGIN<br \/>&#160;&#160;&#160;&#160;&#160;&#160;DECLARE @err_msg&#160;NVARCHAR (2000)<br \/>&#160;&#160;&#160;&#160;&#160;&#160;DECLARE @err_sev INT<br \/>&#160;&#160;&#160;&#160;&#160;&#160;DECLARE @err_state&#160;INT<\/p>\n<p>&#160;&#160;&#160;&#160;&#160;&#160;SELECT @err_msg = ERROR_MESSAGE()&#160;, @err_sev = ERROR_SEVERITY(), @err_state = ERROR_STATE()<br \/>&#160;&#160;&#160;&#160;&#160;&#160;RAISERROR (@err_msg, @err_sev, @err_state)<br \/>&#160;&#160;&#160;&#160;&#160;END<br \/>&#160;&#160;&#160;&#160;ELSE<br \/>&#160;&#160;&#160;&#160;&#160;BEGIN<br \/>&#160;&#160;&#160;&#160;&#160;&#160;PRINT CAST(&#8216;Missing File:&#160; &#8216; + @backup_file AS nvarchar(120))<br \/>&#160;&#160;&#160;&#160;&#160;END<br \/>&#160;&#160;&#160;END CATCH<\/p>\n<p>&#160;&#160;&#160;UPDATE&#160;iDBA.backups.db_log_backups<br \/>&#160;&#160;&#160;SET backup_removed_dt = GETDATE()<br \/>&#160;&#160;&#160;WHERE&#160;backup_full_file_nm = @backup_file<\/p>\n<p>&#160;&#160;&#160;FETCH NEXT FROM del_cur INTO @backup_file<br \/>&#160;&#160;END<\/p>\n<p>&#160;CLOSE del_cur<br \/>&#160;DEALLOCATE del_cur<\/p>\n<p>IF @@TRANCOUNT &gt; 0 COMMIT TRAN<\/p>\n","protected":false},"excerpt":{"rendered":"<p>OK&#160;Simple-Talkers I have a interesting situation driving be nuttier than squirrel poo. I have the following 2 steps in a scheduled SQL job I use to backup logs.&#160; If for some reason a log file does not exist it will throw the error 22049.&#160; I trap for it and want it to proceed with the&#8230;&hellip;<\/p>\n","protected":false},"author":199104,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2],"tags":[],"coauthors":[],"class_list":["post-2561","post","type-post","status-publish","format-standard","hentry","category-blogs"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/2561","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/199104"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=2561"}],"version-history":[{"count":2,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/2561\/revisions"}],"predecessor-version":[{"id":41571,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/2561\/revisions\/41571"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=2561"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=2561"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=2561"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=2561"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}