If you need to make a quick backup of all databases in a single instance, you can make use of the built-in sp_msforeachdb procedure to iterate through all the databases in your instance and make a backup. While I would not recommend this practice to be used as your ‘normal’ backup procedure, it is helpful when performing maintenance tasks such as making a copy of production databases to move off to a dev server.
EXECUTE sp_msforeachdb 'USE [?] IF DB_NAME() NOT IN(''master'',''msdb'',''tempdb'',''model'') BACKUP DATABASE [?] TO DISK = ''C:\MyBaks\?.bak'' WITH INIT, COPY_ONLY, COMPRESSION'
This statement will back up all the databases except master, msdb, tempdb and model (which you may or may not want) to the location specified at c:\mybaks\. This script specifies COPY_ONLY as to not disrupt your current backup chain along with COMPRESSION to make the files as small and portable as possible should your default settings no be configured to compress your backups.
To set your instance level default to compress backups, execute this statement:
EXEC sys.sp_configure N'backup compression default', N'1' GO RECONFIGURE WITH OVERRIDE GO
There are many other uses of sp_msforeachdb, such as the following statement which sets all of your databases in to FULL recovery mode except for master, msdb, tempdb and model. TempDB is the only database that you are not allowed to set in to FULL recovery mode – so it must be ignored. Notice this script checks to make sure that the database is not already in FULL recovery mode before it changes it.
EXECUTE sp_msforeachdb ' IF (''?'' NOT IN(''master'',''msdb'',''tempdb'',''model'')) BEGIN IF (DATABASEPROPERTYEX (''?'', ''Recovery'') != N''FULL'') BEGIN EXECUTE sp_executesql N''ALTER DATABASE [?] SET RECOVERY FULL'' PRINT ''Updated recovery mode of ? to FULL'' END ELSE BEGIN PRINT ''Recovery mode of ? is already set to FULL'' END END'
There is one last thing to note about the above script, it used sp_executesql to alter the database, because if you execute the script below, you will get an ERROR on tempdb as contrairy to common sense, sp_msforeachdb becomes unstable when there is an ALTER DATABASE in the statement.
EXECUTE sp_msforeachdb ' IF ''?'' NOT IN(''master'',''msdb'',''tempdb'',''model'') ALTER DATABASE [?] SET RECOVERY FULL'
Generates this error:
Msg 5058, Level 16, State 1, Line 3
Option ‘RECOVERY’ cannot be set in database ‘tempdb’.
Another great use of sp_msforeachdb is to set all of the database owners to the same owner – this becomes an issue when you just restored a bunch of databases and now YOU are the current owner. In the case where you are logged in as a domain user and this is not your intended result – you need to current it immediately.
EXECUTE sp_msforeachdb 'USE [?] IF (''?'' NOT IN(''master'',''msdb'',''tempdb'',''model'')) BEGIN DECLARE @currentOwner VARCHAR(50) DECLARE @newOwner VARCHAR(50) = ''sa'' SELECT @currentOwner = suser_sname(owner_sid) from sys.databases where name = ''?'' IF (@currentOwner != @newOwner) BEGIN EXECUTE sp_changedbowner @newOwner PRINT ''Updated owner of [?] to ['' + @newOwner + ''] (was set to ['' + @currentOwner + ''])'' END ELSE BEGIN PRINT ''Owner of [?] is already set to ['' + @newOwner + '']'' END END'
AND one last great use of sp_msforeachdb is to set the compatibility levels to the same value as such:
EXECUTE sp_msforeachdb ' IF (''?'' NOT IN(''master'',''msdb'',''tempdb'',''model'')) BEGIN DECLARE @currentCompatLevel TINYINT DECLARE @newCompatLevel TINYINT = 100 SELECT @currentCompatLevel = compatibility_level from sys.databases where name = ''?'' IF (@currentCompatLevel != @newCompatLevel) BEGIN DECLARE @cmdSql NVARCHAR(200) = N''ALTER DATABASE [?] SET COMPATIBILITY_LEVEL = '' + CONVERT(VARCHAR(5), @newCompatLevel) EXECUTE sp_executesql @cmdSql PRINT ''Updated compatibility level of [?] to ['' + CONVERT(VARCHAR(5), @newCompatLevel) + ''] (was set to ['' + CONVERT(VARCHAR(5), @currentCompatLevel) + ''])'' END ELSE BEGIN PRINT ''Compatibility level of [?] is already set to ['' + CONVERT(VARCHAR(5), @newCompatLevel) + '']'' END END'
Also – don’t forget about sp_msforeachdb’s little brother sp_msforeachtable which loops through all tables in a database.
Happy Looping…
