Showing posts with label sys.databases. Show all posts
Showing posts with label sys.databases. Show all posts

Tuesday, February 17, 2015

Display All Databases Using FULL Recovery Model, Yet Having No Log Backups

If a database is using the FULL Recovery Model, it obviously needs to be doing log backups - otherwise the log will eventually fill the disk (your "eventually" may vary). If you don't need log backups, change the database to SIMPLE Recovery Model and sleep easier at night. But, you know how it is - one way or another, databases wind up in this mongrel state. Run this script on your oldest server - you'll probably be surprised.

This script also prints out the T-SQL command to set each database to SIMPLE Recovery Model, so you can just copy and paste.

-- Find databases in FULL Recovery Model with no log backups. 
   SELECT d.name                                            AS 'DatabaseName'
        , MAX(db.recovery_model_desc)                       AS 'Model'
        , MAX(ISNULL(b.backup_finish_date, '1900-01-01'))   AS 'LogBackupFinishDate'
        , 'ALTER DATABASE ' + QUOTENAME(d.name) 
        + '  SET RECOVERY SIMPLE WITH NO_WAIT'              AS 'SqlStatement'
     FROM sys.sysdatabases   d
     JOIN sys.databases      db
       ON d.dbid = db.database_id
LEFT JOIN msdb..backupset    b
       ON b.database_name = d.name
      AND b.type          = 'L'
    WHERE db.recovery_model_desc = 'FULL'
      AND db.state_desc          = 'ONLINE'
      AND db.database_id         > 4
      AND db.is_read_only        = 0
 GROUP BY d.name
   HAVING MAX(ISNULL(b.backup_finish_date, '1900-01-01')) < DATEADD(Day, -180, GETDATE())
 ORDER BY d.name

Friday, December 5, 2014

Find all Databases with AutoShrink Turned On

As far as I can tell, the only thing that all SQL Server DBAs agree on is that AutoShrink should be turned off. You never even see anyone say, "It depends." This level of agreement is, I think, unique in all of SQL Server-land. I mean, you would think we'd all agree that clustering on a non-sequential GUID is a Very Bad Idea, but there's actually people who argue in favor of it. Go figure.

So anyway, the script below will find all the databases (SQL Server 2000 and up) that for some mysterious reason have it turned on. (Of course, we all know the reason is that some yo-yo doesn't understand that big, empty databases run faster than small, full databases, but that's another story...) If you run this script on CMS, it will work across all the servers in the group (that's why we cursor through the resultsets instead of just returning them - it makes the output in CMS much easier to read).

-- Find all databases with AutoShrink turned on. 
declare @DatabaseName sysname

if left(convert(nvarchar, serverproperty('productversion')), 1) <> '8'
begin
    declare cur cursor local fast_forward for
        select name   as 'Database Name'
          from sys.databases
         where is_auto_shrink_on = 1
           and state_desc = 'ONLINE'
           and database_id > 4

    open cur
    fetch next from cur into @DatabaseName

    while @@fetch_status = 0
    begin
        print @DatabaseName
        fetch next from cur into @DatabaseName
    end

    close cur
    deallocate cur
end
else
begin
    declare cur cursor local fast_forward for
        select name   as 'Database Name'
          from master..sysdatabases
         where status & 4194304 = 4194304
           and status & 512 = 0
           and dbid > 4

    open cur
    fetch next from cur into @DatabaseName

    while @@fetch_status = 0
    begin
        print @DatabaseName
        fetch next from cur into @DatabaseName
    end

    close cur
    deallocate cur
end

Monday, March 22, 2010

Using sp_MsForEachDb and sp_MsForEachTable Together

Ever wanted to run a T-SQL command on every user table in every user database? Here's how to nest the undocumented sp_MsForEachTable system stored procedure inside the undocumented sp_MsForEachDB system stored procedure.

DECLARE @Sql NVARCHAR(4000) = 
      'IF EXISTS (SELECT * FROM sys.databases WHERE name = ''''#'''' AND owner_sid = 0x01) RETURN '
    + 'RAISERROR(''''Reclaiming space on table ' + QUOTENAME('#') + '.?'''', 10, 1) WITH NOWAIT '
    + 'USE ' + QUOTENAME('#') + ' '
    + 'DBCC CLEANTABLE(''''#'''', ''''?'''', 10000) WITH NO_INFOMSGS '

SET @Sql = 'USE ' + QUOTENAME('#') + ' EXEC sp_MsForEachTable ''' + @Sql + ''''

EXEC sp_MsForEachDb @Sql, @replacechar = '#'

The trick is the @replacechar parameter to the sp_MsForEachDb stored procedure: it's how we keep the placeholders for the database and the table separate. If there's an easier way, I'd love to see it.