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.
Author |
Topic |
jocampo
Starting Member
48 Posts |
Posted - 2006-09-07 : 09:48:07
|
Hello Tara/Forum friends.I'm trying to run this Tara's modified scrip with adds a new functionality, backup a single database, but it simply does nothing. No single DB is being backing up.Here's the Tara's (modified version) script----------------------------------------------------------------------------------------------------- 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-- @Retention - numbers of days to retain backups-- OUTPUTS : None-- DEPENDENCIES : None---- DESCRIPTION : This stored procedure performs a full backup on all of the user databases---- EXAMPLES (optional) : EXEC isp_Backup @Path = 'E:\MSSQL\Backup\', @dbType = 'All', @Retention = 5----------------------------------------------------------------------------------------------------CREATE PROC isp_Backup(@Path VARCHAR(100), @dbType VARCHAR(6), @Retention INT = 2)ASSET NOCOUNT ONDECLARE @Now CHAR(14) -- current date in the form of yyyymmddhhmmssDECLARE @DBName SYSNAME -- stores the database name that is currently being processedDECLARE @cmd SYSNAME -- stores the dynamically created DOS commandDECLARE @Result INT -- stores the result of the dir DOS commandDECLARE @RowCnt INT -- stores @@ROWCOUNTDECLARE @filename VARCHAR(200) -- stores the path and file name of the BAK fileCREATE 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' AND [name] NOT IN (SELECT database_name FROM msdb.dbo.log_shipping_databases) 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') AND [name] NOT IN (SELECT database_name FROM msdb.dbo.log_shipping_databases) ORDER BY [name] ELSE BEGIN IF @dbType != '' IF EXISTS (SELECT [name] FROM master.dbo.sysdatabases WHERE [name] = @dbType) INSERT INTO #WhichDatabase (dbName) SELECT @dbType ELSE BEGIN DROP TABLE #WhichDatabase RETURN -1 END ELSE BEGIN DROP TABLE #WhichDatabase RETURN -1 END END END END -- Get the database to be backed upSELECT TOP 1 @DBName = dbNameFROM #WhichDatabaseSET @RowCnt = @@ROWCOUNT-- Iterate throught the temp table until no more databases need to be backed upWHILE @RowCnt <> 0BEGIN -- 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, NO_OUTPUT -- 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 '% %' OR SUBSTRING(DirInfo, 1, 10) >= GETDATE() - @Retention -- 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'ENDDROP TABLE #WhichDatabaseSET NOCOUNT OFFRETURN 0GOWhat's wrong? ... thanks for the help ... |
|
Kristen
Test
22859 Posts |
Posted - 2006-09-07 : 12:43:50
|
I expect the problem is the@dbType VARCHAR(6)declaration - which does not allow for a very long database name!!Kristen |
 |
|
tkizer
Almighty SQL Goddess
38200 Posts |
Posted - 2006-09-07 : 13:07:06
|
@dbType doesn't store the database name. It stores the type of backup you want to perform such as System, User, or All. Well that's at least in this version of the stored procedure (I've got a newer one that I haven't posted yet). Joe, could you bold or change the color in the code where you modified the stored procedure?Tara Kizer |
 |
|
JoeNak
Constraint Violating Yak Guru
292 Posts |
Posted - 2006-09-07 : 13:17:42
|
quote: IF @dbType != ''IF EXISTS (SELECT [name] FROM master.dbo.sysdatabases WHERE [name] = @dbType)INSERT INTO #WhichDatabase (dbName)SELECT @dbType
Looks like the issue... |
 |
|
tkizer
Almighty SQL Goddess
38200 Posts |
Posted - 2006-09-07 : 13:26:08
|
I agree. That part of the code that he posted isn't in my original version.If you really are using @dbType to store the database name instead of how I originally wrote it, then you do need to change the data type. Then you'll need:IF EXISTS (SELECT [name] FROM master.dbo.sysdatabases WHERE [name] = @dbType)INSERT INTO #WhichDatabase (dbName) VALUES (@dbType)Get rid of the IF check for @dbType <> ''.Tara Kizer |
 |
|
Kristen
Test
22859 Posts |
Posted - 2006-09-07 : 13:46:58
|
What a horrid bodge - you are being too kind Tara!!jocampo: Add another optional parameter @SingleDatabaseBackupName or somesuch and use that as the name of the DB to back up.IMHO @dbType is much better constrained to a sensible size for its intended purpose of holding the TYPE - rather than lose constraints and dual-duty storing something which clearly has nothing to do with the TYPE!Kristen |
 |
|
tkizer
Almighty SQL Goddess
38200 Posts |
Posted - 2006-09-07 : 13:52:06
|
In my new version of this code, I reuse @dbType as well to backup a single database. New data type is sysname since that's the data type of database names. If the user intends to backup a single database, the user must specify a dash prior to the database name, such as -Toolbox. This is documented in the comment header block for clarity. I also do various checks to ensure all inputs are validated. Eventually I'll get around to posting the new version in my blog and perhaps here. It supports both SQL Server 2000 and 2005 plus LiteSpeed for both. It also supports differential backups. The reason I haven't posted it yet is due to insufficient testing of it.Tara Kizer |
 |
|
Kristen
Test
22859 Posts |
Posted - 2006-09-07 : 13:53:45
|
Still don't like the reuse of @dbType - or the "secret knowledge" of the hyphen prefix ... Kristen |
 |
|
tkizer
Almighty SQL Goddess
38200 Posts |
Posted - 2006-09-07 : 14:02:43
|
It's not a secret if it's documented. I didn't see a reason to declare another variable, which would use additional memory, when the code flows using @dbType. Alright, so here's part of the code:...CREATE TABLE #WhichDatabase(dbName SYSNAME NOT NULL)-- put the databases to be backed up into temp tableIF @dbType LIKE '-%' IF @bkpType = 'TLog' AND DATABASEPROPERTYEX(SUBSTRING(@dbType, 2, DATALENGTH(@dbType)), 'RECOVERY') = 'SIMPLE' BEGIN SET @rc = 7 GOTO EXIT_ROUTINE END ELSE IF @edition = 3 BEGIN IF @version = '8' AND EXISTS (SELECT * FROM msdb.dbo.log_shipping_databases WHERE database_name = SUBSTRING(@dbType, 2, DATALENGTH(@dbType))) BEGIN SET @rc = 8 GOTO EXIT_ROUTINE END ELSE IF @version = '9' AND EXISTS (SELECT * FROM msdb.dbo.log_shipping_primary_databases WHERE primary_database = SUBSTRING(@dbType, 2, DATALENGTH(@dbType))) BEGIN SET @rc = 8 GOTO EXIT_ROUTINE END END ELSE INSERT INTO #WhichDatabase(dbName) VALUES(REPLACE(@dbType, '-', ''))ELSE IF @dbType = 'All' BEGIN IF @edition = 3 AND @version = '8' INSERT INTO #WhichDatabase (dbName) SELECT [name] FROM master.dbo.sysdatabases WHERE [name] NOT IN ('tempdb', 'ReportServerTempDB') AND [name] NOT IN (SELECT database_name FROM msdb.dbo.log_shipping_databases) AND DATABASEPROPERTYEX([name], 'IsInStandBy') = 0 AND DATABASEPROPERTYEX([name], 'Status') = 'ONLINE' ORDER BY [name] ELSE IF @edition = 3 AND @version = '9' INSERT INTO #WhichDatabase (dbName) SELECT [name] FROM master.sys.databases WHERE [name] NOT IN ('tempdb', 'ReportServerTempDB') AND [name] NOT IN (SELECT primary_database FROM msdb.dbo.log_shipping_primary_databases) AND DATABASEPROPERTYEX([name], 'IsInStandBy') = 0 AND DATABASEPROPERTYEX([name], 'Status') = 'ONLINE' ORDER BY [name] ELSE IF @version = '8' INSERT INTO #WhichDatabase (dbName) SELECT [name] FROM master.dbo.sysdatabases WHERE [name] NOT IN ('tempdb', 'ReportServerTempDB') AND DATABASEPROPERTYEX([name], 'IsInStandBy') = 0 AND DATABASEPROPERTYEX([name], 'Status') = 'ONLINE' ORDER BY [name] ELSE -- version is 9 INSERT INTO #WhichDatabase (dbName) SELECT [name] FROM master.sys.databases WHERE [name] NOT IN ('tempdb', 'ReportServerTempDB') AND DATABASEPROPERTYEX([name], 'IsInStandBy') = 0 AND DATABASEPROPERTYEX([name], 'Status') = 'ONLINE' ORDER BY [name]ENDELSE IF @dbType = 'System'BEGIN IF @version = 8 INSERT INTO #WhichDatabase (dbName) SELECT [name] FROM master.dbo.sysdatabases WHERE [name] IN ('master', 'model', 'msdb') ORDER BY [name] ELSE INSERT INTO #WhichDatabase (dbName) SELECT [name] FROM master.sys.databases WHERE [name] IN ('master', 'model', 'msdb') ORDER BY [name]ENDELSE IF @dbType = 'User'BEGIN IF @edition = 3 AND @version = '8' INSERT INTO #WhichDatabase (dbName) SELECT [name] FROM master.dbo.sysdatabases WHERE [name] NOT IN ('master', 'model', 'msdb', 'tempdb', 'ReportServerTempDB') AND [name] NOT IN (SELECT database_name FROM msdb.dbo.log_shipping_databases) AND DATABASEPROPERTYEX([name], 'IsInStandBy') = 0 AND DATABASEPROPERTYEX([name], 'Status') = 'ONLINE' ORDER BY [name] ELSE IF @edition = 3 AND @version = '9' INSERT INTO #WhichDatabase (dbName) SELECT [name] FROM master.sys.databases WHERE [name] NOT IN ('master', 'model', 'msdb', 'tempdb', 'ReportServerTempDB') AND [name] NOT IN (SELECT primary_database FROM msdb.dbo.log_shipping_primary_databases) AND DATABASEPROPERTYEX([name], 'IsInStandBy') = 0 AND DATABASEPROPERTYEX([name], 'Status') = 'ONLINE' ORDER BY [name] ELSE IF @version = '8' INSERT INTO #WhichDatabase (dbName) SELECT [name] FROM master.dbo.sysdatabases WHERE [name] NOT IN ('master', 'model', 'msdb', 'tempdb', 'ReportServerTempDB') AND DATABASEPROPERTYEX([name], 'IsInStandBy') = 0 AND DATABASEPROPERTYEX([name], 'Status') = 'ONLINE' ORDER BY [name] ELSE INSERT INTO #WhichDatabase (dbName) SELECT [name] FROM master.sys.databases WHERE [name] NOT IN ('master', 'model', 'msdb', 'tempdb', 'ReportServerTempDB') AND DATABASEPROPERTYEX([name], 'IsInStandBy') = 0 AND DATABASEPROPERTYEX([name], 'Status') = 'ONLINE' ORDER BY [name]ENDELSE -- no databases to be backed upBEGIN SET @rc = 9 GOTO EXIT_ROUTINEEND... Tara Kizer |
 |
|
jocampo
Starting Member
48 Posts |
Posted - 2006-09-07 : 14:34:35
|
quote: Originally posted by Kristen What a horrid bodge - you are being too kind Tara!!jocampo: Add another optional parameter @SingleDatabaseBackupName or somesuch and use that as the name of the DB to back up.IMHO @dbType is much better constrained to a sensible size for its intended purpose of holding the TYPE - rather than lose constraints and dual-duty storing something which clearly has nothing to do with the TYPE!Kristen
I did not write the modified code/line. I'm an SQL admin but do not have a great expertise in T-SQL. That's why i'm asking help ... |
 |
|
tkizer
Almighty SQL Goddess
38200 Posts |
Posted - 2006-09-07 : 14:38:16
|
So what we posted hasn't helped yet?Tara Kizer |
 |
|
jocampo
Starting Member
48 Posts |
Posted - 2006-09-07 : 14:42:51
|
quote: Originally posted by tkizer I agree. That part of the code that he posted isn't in my original version.If you really are using @dbType to store the database name instead of how I originally wrote it, then you do need to change the data type. Then you'll need:IF EXISTS (SELECT [name] FROM master.dbo.sysdatabases WHERE [name] = @dbType)INSERT INTO #WhichDatabase (dbName) VALUES (@dbType)Get rid of the IF check for @dbType <> ''.Tara Kizer
Thanks a lot for your help Tara. I'll appreciated if you can indicate to me how the final code should look like. I don't know much about T-SQL.Thanks,Jose. |
 |
|
tkizer
Almighty SQL Goddess
38200 Posts |
Posted - 2006-09-07 : 14:45:39
|
I'm not sure how it will work actually as I don't know what the problem is yet. I made a suggestion to get rid of one of the IF statements. I don't see a reason to check if @dbType equals ''. That isn't in my original version, so someone added that code.Tara Kizer |
 |
|
jocampo
Starting Member
48 Posts |
Posted - 2006-09-07 : 14:52:59
|
quote: Originally posted by tkizer I'm not sure how it will work actually as I don't know what the problem is yet. I made a suggestion to get rid of one of the IF statements. I don't see a reason to check if @dbType equals ''. That isn't in my original version, so someone added that code.Tara Kizer
If i drop that line i get this error:ERROR 156: Incorrect syntax near the keyword 'ELSE'This is the part of the code with i'm working on:IF @dbType != '' IF EXISTS (SELECT [name] FROM master.dbo.sysdatabases WHERE [name] = @dbType) INSERT INTO #WhichDatabase (dbName) SELECT @dbType after changeIF EXISTS (SELECT [name] FROM master.dbo.sysdatabases WHERE [name] = @dbType) INSERT INTO #WhichDatabase (dbName) SELECT @dbType when i do that, i get the above error ... |
 |
|
tkizer
Almighty SQL Goddess
38200 Posts |
Posted - 2006-09-07 : 14:59:22
|
Well you would need to get rid of the corresonding BEGINs, ENDs, and ELSEs for it as well. Have you tried modifying the data type of @dbType to see if that works as mentioned by Kristen? I recommend sysname or nvarchar(256) for that variable since that's the data type of database names. Tara Kizer |
 |
|
tkizer
Almighty SQL Goddess
38200 Posts |
Posted - 2006-09-07 : 15:03:11
|
If you have no need to backup anything but a single database, then I'd use this (untested as I just modified it):CREATE PROC isp_Backup(@Path VARCHAR(100), @dbName sysname, @Retention INT = 2)ASSET NOCOUNT ONDECLARE @Now CHAR(14) -- current date in the form of yyyymmddhhmmssDECLARE @cmd SYSNAME -- stores the dynamically created DOS commandDECLARE @Result INT -- stores the result of the dir DOS commandDECLARE @RowCnt INT -- stores @@ROWCOUNTDECLARE @filename VARCHAR(200) -- stores the path and file name of the BAK file-- Get the current date using style 120, remove all dashes, spaces, and colonsSELECT @Now = REPLACE(REPLACE(REPLACE(CONVERT(VARCHAR(50), GETDATE(), 120), '-', ''), ' ', ''), ':', '')-- Build the .BAK path and file nameSELECT @filename = @Path + @DBName + '\' + @dbName + '_' + @Now + '.BAK'-- Build the dir command that will check to see if the directory existsSELECT @cmd = 'dir ' + @Path + @dbName-- Run the dir command, put output of xp_cmdshell into @resultEXEC @result = master.dbo.xp_cmdshell @cmd, NO_OUTPUT-- If the directory does not exist, we must create itIF @result <> 0BEGIN -- Build the mkdir command SELECT @cmd = 'mkdir ' + @Path + @dbName -- Create the directory EXEC master.dbo.xp_cmdshell @cmd, NO_OUTPUTEND-- The directory exists, so let's delete files older than two daysELSEBEGIN -- 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 '% %' OR SUBSTRING(DirInfo, 1, 10) >= GETDATE() - @Retention -- 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 = @@ROWCOUNTENDDROP TABLE #DeleteOldFiles-- Backup the databaseBACKUP DATABASE @dbNameTO DISK = @filenameWITH INITRETURN 0GO Tara Kizer |
 |
|
Kristen
Test
22859 Posts |
Posted - 2006-09-07 : 15:04:25
|
"That's why i'm asking help ..."I thought I'll already given some:I expect the problem is the@dbType VARCHAR(6)declaration - which does not allow for a very long database name!!Changing your originally posted code to:CREATE PROC isp_Backup(@Path VARCHAR(100), @dbType VARCHAR(100), @Retention INT = 2)AS should fix the problem, but I haven't tested it ...Kristen |
 |
|
jocampo
Starting Member
48 Posts |
Posted - 2006-09-07 : 15:09:22
|
You're so kind! Thanks for your patience ... yes, i have need to backup more than one ... and in other case, just one ... i would like to re-use your orginal code ... |
 |
|
Kristen
Test
22859 Posts |
Posted - 2006-09-07 : 15:10:39
|
"It's not a secret if it's documented. I didn't see a reason to declare another variable, which would use additional memory, when the code flows using @dbType."Well its not my Sproc, so I don't mind overly-muchly ... but this type of "from-QA" utility tends to only be "documented" if you are in a position to look at the source code, or if it will provide a ResultSet showing some Help Text if you EXEC it with, say, no parameters - which is what we do for our "Junior DBA Sprocs"But I also think that if the user doessp_help 'isp_Backup'and the parameter list has one called, say, @SingleDatabaseBackupName the young-DBA is then going to try:exec isp_Backup @SingleDatabaseBackupName='MyDatabase'and if that then works as expected its a nice self-documenting tool.But that's just my two-pennyworth Kristen |
 |
|
jocampo
Starting Member
48 Posts |
Posted - 2006-09-07 : 15:12:50
|
quote: Originally posted by Kristen "That's why i'm asking help ..."I thought I'll already given some:I expect the problem is the@dbType VARCHAR(6)declaration - which does not allow for a very long database name!!Changing your originally posted code to:CREATE PROC isp_Backup(@Path VARCHAR(100), @dbType VARCHAR(100), @Retention INT = 2)AS should fix the problem, but I haven't tested it ...Kristen
No, it does not solve the problem. It runs, yes, but do nothing. |
 |
|
tkizer
Almighty SQL Goddess
38200 Posts |
Posted - 2006-09-07 : 15:19:06
|
Could you post the statement that you are using to execute it?Put this at the bottom of the stored procedure prior to the RETURN statement:SELECT *FROM #WhichDatabaseExecute the stored procedure in Query Analyzer. Post the results of it. You should have a row returned due to the SELECT statement you added.Tara Kizer |
 |
|
Next Page
|
|
|
|
|