Purpose

Reference KB 2645392 (will update with the link to the article when it is published)

This Script fixes the issue where the App-V SoftGrid Database (APPVIRT): Check Usage History job fails when run on SQL 2008 with the following error messages:

Execution of job 'SoftGrid Database (APPVIRT): Check Usage History' failed. See the history log for details.

To find the "History log for details"

Date  11/15/2011 1:25:13 PM
Log  Job History (SoftGrid Database (APPVIRT): Check Usage History)

Step ID  1
Server  AppVSQL_Server_Name
Job Name  SoftGrid Database (APPVIRT): Check Usage History
Step Name  Check Usage History
Duration  00:00:00
Sql Severity  15
Sql Message ID  2528
Operator Emailed 
Operator Net sent 
Operator Paged 
Retries Attempted  0

Message
Executed as user: dbo. DBCC execution completed. If DBCC printed error messages, contact your system administrator. [SQLSTATE 01000] (Message 2528)  'TRUNCATE_ONLY' is not a recognized BACKUP option. [SQLSTATE 42000] (Error 155)  DBCC execution completed. If DBCC printed error messages, contact your system administrator. [SQLSTATE 01000] (Error 2528).  The step failed.

Cause

The stored procedure (sp_SFTcleanupusage) executed by the 'Check Usage History' job uses the Trucate_only option which is no longer supported in SQL 2008 therefore the job fails.

How to run the script

SQL server Sysadmin rights are required to run this script, specifically rights to modify the App-V Database (APPVIRT by default). Open Microsoft SQL Server Management Studio on the SQL 2008 server hosting the App-V Database , navigate to and highlight the App-V database, click on New Query  and either copy and paste the script into the Query window, or drag the sp_SFTcleanupusage_update.sql file to the window. Click on the check icon (Parse) to verify all is well, and then click on ! Execute, if all goes well you should see “Command(s) completed successfully” in the messages window.

SQL
Edit|Remove
/****** Object:  StoredProcedure [dbo].[sp_SFTcleanupusage]    Script Date: 11/08/2010 10:21:11 ******/ 
IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[sp_SFTcleanupusage]'AND type in (N'P'N'PC')) 
DROP PROCEDURE [dbo].[sp_SFTcleanupusageGO 
 
/****** Object:  StoredProcedure [dbo].[sp_SFTcleanupusage]    Script Date: 11/08/2010 10:21:11 ******/ 
SET ANSI_NULLS ON 
GO 
 
SET QUOTED_IDENTIFIER ON 
GO 
 
/* ------------------------------------------------------------------------- *\ 
    Copyright (c) Microsoft Corporation.  All rights reserved. 
 
    File: sp_SFTcleanupusage.sql 
 
     
     
 
    Description: 
 
        Cleans up the messages and usage data from the MESSAGE_LOG and 
        APPLICATION_USAGE tables.  The cutoff date parameter supplied to this 
        procedure is used to determine where the cleanup begins.  Everything 
        prior to the cutoff date is cleaned up. 
 
        The process will only cleanup completed (closed) sessions.  It will 
        not cleanup open transactions unless it can determine for certain that 
        those transactions have been orphaned. 
 
        Transactions for the purposes of this procedure are considered only  
        to be session and license transactional messages. 
 
        Session Transactions: 
 
            40960 - Session Setup 
            40961 - Session Teardown 
            40962 - Session Abnormal Teardown 
            40963 - Session Recovery Teardown 
 
        License Transactions: 
 
            40976 - License Setup 
            40977 - License Teardown 
            40978 - License Abnormal Teardown 
            40979 - License Recovery Teardown 
 
        Everything else for the purposes of this procedure are considered to 
        be non-transactional, however, there are other transactional message 
        types that we care about for other purposes. 
 
        Server Transactions: 
 
            41216 - Dispatcher/Core Initializing 
            41217 - Dispatcher/Core Initialization Succeeded 
            41218 - Dispatcher/Core Shutting Down 
            41219 - Dispatcher/Core Shutdown Succeeded 
 
        Provider Transactions: 
 
            41220 - Provider Initialized 
 
        NOTE:  We currently don't care at all about provider transactions. 
               It has just been listed here for reference. 
 
    Revision History 
    ---------------- 
    MM/DD/YYYY  FML  Description of change. 
\* ------------------------------------------------------------------------- */ 
CREATE PROCEDURE [dbo].[sp_SFTcleanupusage] 
    @p_cutoffdate               datetime = NULL, 
    @p_delcount1                int      = 0    OUTPUT, 
    @p_delcount2                int      = 0    OUTPUT, 
    @p_shrinkfiles              bit      = 0    OUTPUT, 
    @p_truncatelog              bit      = 0    OUTPUT 
AS 
 
/* Error handling and message variables. */ 
DECLARE @err                    int 
DECLARE @rcount                 int 
DECLARE @msg                    nvarchar(2048DECLARE @pname                  nvarchar(128DECLARE @tcount                 int 
 
/* Program specific variables. */ 
DECLARE @db_name                sysname 
DECLARE @filename               nvarchar(128DECLARE @fgreadonly             bit 
 
BEGIN 
    /* Initialize error handling variables. */ 
    SELECT @err = @@ERROR@rcount = @@ROWCOUNT 
    SELECT @tcount = @@TRANCOUNT 
    IF @@TRANCOUNT = 0 BEGIN TRANSACTION 
 
    SELECT @pname = N'sp_SFTcleanupusage' 
 
    EXEC sp_SFTmsg N'TRACEIN',@pname 
 
    /* Initialize environment. */ 
    /* Stops the message indicating the number of rows affected by SQL 
       statements.  @@ROWCOUNT is updated even when SET NOCOUNT is ON. */ 
    SET NOCOUNT ON 
 
    /* Initialize other variables. */ 
    SELECT @p_delcount1 = 0 
    SELECT @p_delcount2 = 0 
    SELECT @p_shrinkfiles = 0 
    SELECT @p_truncatelog = 0 
    SELECT @db_name = DB_NAME() 
 
    /* Check to see if the cutoff date is NULL.  If so, the cleanup process is 
       skipped, but the transaction log is still truncated. */ 
    IF ISNULL(@p_cutoffdateN'') = N'' GOTO TRUNCATE_LOG 
 
    /* Strip the time off the cutoff date parameter. */ 
    EXEC sp_SFTmsg N'DEBUG'@pnameN'Cutoff date BEFORE stripping off time: %s'@p_cutoffdate 
    SELECT @p_cutoffdate = dbo.fn_SFTsettime(@p_cutoffdateN'00:00') 
    EXEC sp_SFTmsg N'DEBUG'@pnameN'Cutoff date AFTER stripping off time:  %s'@p_cutoffdate 
 
    /* --------------------------------------------------------------------- *\ 
       Delete unclosed transactions (i.e. sessions or licenses that are known 
       to be orphaned and will never be closed otherwise) if the start date 
       falls before the cutoff date from the MESSAGE_LOG and APPLICATION_USAGE 
       tables. 
 
       NOTE:  Transactions are known to be orphaned if they start before a 
              server/core shutdown or startup, but do not have an end date. 
              The reason it is orphaned is that the actual transaction must 
              have been closed because stopping the dispatcher or core shuts 
              down all sessions and licenses with which it is associated. 
    \* --------------------------------------------------------------------- */ 
 
    SELECT @msg = N'Deleting orphaned transactions from APPLICATION_USAGE table...' 
    EXEC sp_SFTmsg N'DEBUG'@pname@msg 
 
    /* Delete orphaned transaction from APPLICATION_USAGE table. */ 
    DELETE application_usage 
      FROM application_usage u 
     WHERE u.start_time < @p_cutoffdate 
       AND u.end_time IS NULL 
       AND EXISTS 
           ( 
            SELECT 1 
              FROM message_log l 
             WHERE l.severity = 0 
               AND l.msg_id IN (41216,41217,41218,41219-- dispatcher/core startup/shutdowns 
               AND l.server_hostname = u.server_name 
               AND ( (l.core_pid = u.core_pid AND l.fn_module LIKE N'%Core%'OR 
                     (l.fn_module LIKE N'%Dispatcher%') ) 
               AND l.msg_time > u.start_time 
           ) 
    SELECT @err = @@ERROR@rcount = @@ROWCOUNT 
    IF @err != 0 GOTO ERROR_HANDLER 
 
    IF @rcount > 0 BEGIN 
        /* Add count of rows deleted to APPLICATION_USAGE delete counter. */ 
        SELECT @p_delcount2 = @p_delcount2 + @rcount 
 
        /* Commit the open transaction, then start a new transaction. */ 
        COMMIT 
        SELECT @msg = N'  Transaction committed!  Rows deleted from APPLICATION_USAGE table thus far: %s' 
        EXEC sp_SFTmsg N'DEBUG'@pname@msg@p_delcount2 
        BEGIN TRANSACTION 
    END -- IF 
    ELSE BEGIN 
        SELECT @msg = N'  Nothing to delete!!!  Rows deleted from APPLICATION_USAGE table remains at: %s' 
        EXEC sp_SFTmsg N'DEBUG'@pname@msg@p_delcount2 
    END -- IF 
 
    SELECT @msg = N'Deleting orphaned session transactions from MESSAGE_LOG table...' 
    EXEC sp_SFTmsg N'DEBUG'@pname@msg 
 
    /* Delete orphaned session transaction from MESSAGE_LOG table. */ 
    DELETE message_log 
      FROM message_log s 
     WHERE s.severity = 0 
       AND s.msg_id = 40960 -- session setup 
       AND s.msg_time < @p_cutoffdate 
       AND NOT EXISTS 
           ( 
            SELECT 1 
              FROM message_log e 
             WHERE e.server_hostname = s.server_hostname 
               AND e.core_pid = s.core_pid 
               AND e.username = s.username 
               AND e.package_file = s.package_file 
               AND e.session_id = s.session_id 
               AND e.severity = 0 
               AND e.msg_id IN (40961,40962,40963-- session teardowns 
           ) 
       AND EXISTS 
           ( 
            SELECT 1 
              FROM message_log l 
             WHERE l.severity = 0 
               AND l.msg_id IN (41216,41217,41218,41219-- dispatcher/core startup/shutdowns 
               AND ( (l.core_pid = s.core_pid AND l.fn_module LIKE N'%Core%'OR 
                     (l.fn_module LIKE N'%Dispatcher%') ) 
               AND l.msg_time > s.msg_time 
           ) 
    SELECT @err = @@ERROR@rcount = @@ROWCOUNT 
    IF @err != 0 GOTO ERROR_HANDLER 
 
    IF @rcount > 0 BEGIN 
        /* Add count of rows deleted to MESSAGE_LOG delete counter. */ 
        SELECT @p_delcount1 = @p_delcount1 + @rcount 
 
        /* Commit the open transaction, then start a new transaction. */ 
        COMMIT 
        SELECT @msg = N'  Transaction committed!  Rows deleted from MESSAGE_LOG table thus far: %s' 
        EXEC sp_SFTmsg N'DEBUG'@pname@msg@p_delcount1 
        BEGIN TRANSACTION 
    END -- IF 
    ELSE BEGIN 
        SELECT @msg = N'  Nothing to delete!!!  Rows deleted from MESSAGE_LOG table remains at: %s' 
        EXEC sp_SFTmsg N'DEBUG'@pname@msg@p_delcount1 
    END -- IF 
 
    SELECT @msg = N'Deleting orphaned license transactions from MESSAGE_LOG table...' 
    EXEC sp_SFTmsg N'DEBUG'@pname@msg 
 
    /* Delete orphaned license transaction from MESSAGE_LOG table. */ 
    DELETE message_log 
      FROM message_log s 
     WHERE s.severity = 0 
       AND s.msg_id = 40976 -- license setup 
       AND s.msg_time < @p_cutoffdate 
       AND NOT EXISTS 
           ( 
            SELECT 1 
              FROM message_log e 
             WHERE e.server_hostname = s.server_hostname 
               AND e.core_pid = s.core_pid 
               AND e.username = s.username 
               AND e.package_file = s.package_file 
               AND e.session_id = s.session_id 
               AND e.severity = 0 
               AND e.msg_id IN (40977,40978,40979-- license teardowns 
           ) 
       AND EXISTS 
           ( 
            SELECT 1 
              FROM message_log l 
             WHERE l.severity = 0 
               AND l.msg_id in (41216,41217,41218,41219-- dispatcher/core startup/shutdowns 
               AND ( (l.core_pid = s.core_pid AND l.fn_module LIKE N'%Core%'OR 
                     (l.fn_module LIKE N'%Dispatcher%') ) 
               AND l.msg_time > s.msg_time 
           ) 
    SELECT @err = @@ERROR@rcount = @@ROWCOUNT 
    IF @err != 0 GOTO ERROR_HANDLER 
 
    IF @rcount > 0 BEGIN 
        /* Add count of rows deleted to MESSAGE_LOG delete counter. */ 
        SELECT @p_delcount1 = @p_delcount1 + @rcount 
 
        /* Commit the open transaction, then start a new transaction. */ 
        COMMIT 
        SELECT @msg = N'  Transaction committed!  Rows deleted from MESSAGE_LOG table thus far: %s' 
        EXEC sp_SFTmsg N'DEBUG'@pname@msg@p_delcount1 
        BEGIN TRANSACTION 
    END -- IF 
    ELSE BEGIN 
        SELECT @msg = N'  Nothing to delete!!!  Rows deleted from MESSAGE_LOG table remains at: %s' 
        EXEC sp_SFTmsg N'DEBUG'@pname@msg@p_delcount1 
    END -- IF 
 
    /* --------------------------------------------------------------------- *\ 
       Delete all non-transactional messages (from the MESSAGE_LOG table) 
       that occur prior to the cutoff date. 
 
       NOTE:  Only the session and license transactions should remain. 
    \* --------------------------------------------------------------------- */ 
 
    SELECT @msg = N'Deleting non-transactional messages from MESSAGE_LOG table...' 
    EXEC sp_SFTmsg N'DEBUG'@pname@msg 
 
    /* Delete non-transactional messages from MESSAGE_LOG table. */ 
    DELETE message_log 
      FROM message_log l 
     WHERE ( (l.severity > 0OR 
             (l.severity = 0 AND 
              l.msg_id NOT IN (40960,40961,40962,40963AND -- session transactions 
              l.msg_id NOT IN (40976,40977,40978,40979)) )  -- license transactions 
       AND l.msg_time < @p_cutoffdate 
    SELECT @err = @@ERROR@rcount = @@ROWCOUNT 
    IF @err != 0 GOTO ERROR_HANDLER 
 
    IF @rcount > 0 BEGIN 
        /* Add count of rows deleted to MESSAGE_LOG delete counter. */ 
        SELECT @p_delcount1 = @p_delcount1 + @rcount 
 
        /* Commit the open transaction, then start a new transaction. */ 
        COMMIT 
        SELECT @msg = N'  Transaction committed!  Rows deleted from MESSAGE_LOG table thus far: %s' 
        EXEC sp_SFTmsg N'DEBUG'@pname@msg@p_delcount1 
        BEGIN TRANSACTION 
    END -- IF 
    ELSE BEGIN 
        SELECT @msg = N'  Nothing to delete!!!  Rows deleted from MESSAGE_LOG table remains at: %s' 
        EXEC sp_SFTmsg N'DEBUG'@pname@msg@p_delcount1 
    END -- IF 
 
    /* --------------------------------------------------------------------- *\ 
       Delete all transactions (from the MESSAGE_LOG and APPLICATION_USAGE 
       tables) that have ended (completed) prior to the cutoff date. 
 
       NOTE:  These are the session and license transactions we now cleanup. 
    \* --------------------------------------------------------------------- */ 
 
    SELECT @msg = N'Deleting completed session starts from MESSAGE_LOG table...' 
    EXEC sp_SFTmsg N'DEBUG'@pname@msg 
 
    /* Delete completed session start from MESSAGE_LOG table. */ 
    DELETE message_log 
      FROM message_log s 
     WHERE s.severity = 0 
       AND s.msg_id = 40960 -- session setup 
       AND s.msg_time < @p_cutoffdate 
       AND EXISTS 
           ( 
            SELECT 1 
              FROM message_log e 
             WHERE e.server_hostname = s.server_hostname 
               AND e.core_pid = s.core_pid 
               AND e.username = s.username 
               AND e.package_file = s.package_file 
               AND e.session_id = s.session_id 
               AND e.severity = 0 
               AND e.msg_id IN (40961,40962,40963-- session teardowns 
               AND e.msg_time < @p_cutoffdate 
           ) 
    SELECT @err = @@ERROR@rcount = @@ROWCOUNT 
    IF @err != 0 GOTO ERROR_HANDLER 
 
    IF @rcount > 0 BEGIN 
        /* Add count of rows deleted to MESSAGE_LOG delete counter. */ 
        SELECT @p_delcount1 = @p_delcount1 + @rcount 
 
        /* Commit the open transaction, then start a new transaction. */ 
        COMMIT 
        SELECT @msg = N'  Transaction committed!  Rows deleted from MESSAGE_LOG table thus far: %s' 
        EXEC sp_SFTmsg N'DEBUG'@pname@msg@p_delcount1 
        BEGIN TRANSACTION 
    END -- IF 
    ELSE BEGIN 
        SELECT @msg = N'  Nothing to delete!!!  Rows deleted from MESSAGE_LOG table remains at: %s' 
        EXEC sp_SFTmsg N'DEBUG'@pname@msg@p_delcount1 
    END -- IF 
 
    SELECT @msg = N'Deleting completed session ends from MESSAGE_LOG table...' 
    EXEC sp_SFTmsg N'DEBUG'@pname@msg 
 
    /* Delete completed session end from MESSAGE_LOG table. */ 
    DELETE message_log 
      FROM message_log e 
     WHERE e.severity = 0 
       AND e.msg_id IN (40961,40962,40963-- session teardowns 
       AND e.msg_time < @p_cutoffdate 
    SELECT @err = @@ERROR@rcount = @@ROWCOUNT 
    IF @err != 0 GOTO ERROR_HANDLER 
 
    IF @rcount > 0 BEGIN 
        /* Add count of rows deleted to MESSAGE_LOG delete counter. */ 
        SELECT @p_delcount1 = @p_delcount1 + @rcount 
 
        /* Commit the open transaction, then start a new transaction. */ 
        COMMIT 
        SELECT @msg = N'  Transaction committed!  Rows deleted from MESSAGE_LOG table thus far: %s' 
        EXEC sp_SFTmsg N'DEBUG'@pname@msg@p_delcount1 
        BEGIN TRANSACTION 
    END -- IF 
    ELSE BEGIN 
        SELECT @msg = N'  Nothing to delete!!!  Rows deleted from MESSAGE_LOG table remains at: %s' 
        EXEC sp_SFTmsg N'DEBUG'@pname@msg@p_delcount1 
    END -- IF 
 
    SELECT @msg = N'Deleting completed license starts from MESSAGE_LOG table...' 
    EXEC sp_SFTmsg N'DEBUG'@pname@msg 
 
    /* Delete completed license start from MESSAGE_LOG table. */ 
    DELETE message_log 
      FROM message_log s 
     WHERE s.severity = 0 
       AND s.msg_id = 40976 -- license setup 
       AND s.msg_time < @p_cutoffdate 
       AND EXISTS 
           ( 
            SELECT 1 
              FROM message_log e 
             WHERE e.server_hostname = s.server_hostname 
               AND e.core_pid = s.core_pid 
               AND e.username = s.username 
               AND e.package_file = s.package_file 
               AND e.session_id = s.session_id 
               AND e.severity = 0 
               AND e.msg_id IN (40977,40978,40979-- license teardowns 
               AND e.msg_time < @p_cutoffdate 
           ) 
    SELECT @err = @@ERROR@rcount = @@ROWCOUNT 
    IF @err != 0 GOTO ERROR_HANDLER 
 
    IF @rcount > 0 BEGIN 
        /* Add count of rows deleted to MESSAGE_LOG delete counter. */ 
        SELECT @p_delcount1 = @p_delcount1 + @rcount 
 
        /* Commit the open transaction, then start a new transaction. */ 
        COMMIT 
        SELECT @msg = N'  Transaction committed!  Rows deleted from MESSAGE_LOG table thus far: %s' 
        EXEC sp_SFTmsg N'DEBUG'@pname@msg@p_delcount1 
        BEGIN TRANSACTION 
    END -- IF 
    ELSE BEGIN 
        SELECT @msg = N'  Nothing to delete!!!  Rows deleted from MESSAGE_LOG table remains at: %s' 
        EXEC sp_SFTmsg N'DEBUG'@pname@msg@p_delcount1 
    END -- IF 
 
    SELECT @msg = N'Deleting completed license ends from MESSAGE_LOG table...' 
    EXEC sp_SFTmsg N'DEBUG'@pname@msg 
 
    /* Delete completed license end from MESSAGE_LOG table. */ 
    DELETE message_log 
      FROM message_log e 
     WHERE e.severity = 0 
       AND e.msg_id IN (40977,40978,40979-- license teardowns 
       AND e.msg_time < @p_cutoffdate 
    SELECT @err = @@ERROR@rcount = @@ROWCOUNT 
    IF @err != 0 GOTO ERROR_HANDLER 
 
    IF @rcount > 0 BEGIN 
        /* Add count of rows deleted to MESSAGE_LOG delete counter. */ 
        SELECT @p_delcount1 = @p_delcount1 + @rcount 
 
        /* Commit the open transaction, then start a new transaction. */ 
        COMMIT 
        SELECT @msg = N'  Transaction committed!  Rows deleted from MESSAGE_LOG table thus far: %s' 
        EXEC sp_SFTmsg N'DEBUG'@pname@msg@p_delcount1 
        BEGIN TRANSACTION 
    END -- IF 
    ELSE BEGIN 
        SELECT @msg = N'  Nothing to delete!!!  Rows deleted from MESSAGE_LOG table remains at: %s' 
        EXEC sp_SFTmsg N'DEBUG'@pname@msg@p_delcount1 
    END -- IF 
 
    SELECT @msg = N'Deleting completed transactions from APPLICATION_USAGE table...' 
    EXEC sp_SFTmsg N'DEBUG'@pname@msg 
 
    /* Delete completed transaction from APPLICATION_USAGE table. */ 
    DELETE application_usage 
      FROM application_usage u 
     WHERE u.start_time < @p_cutoffdate 
       AND u.end_time < @p_cutoffdate 
       AND u.end_time IS NOT NULL 
    SELECT @err = @@ERROR@rcount = @@ROWCOUNT 
    IF @err != 0 GOTO ERROR_HANDLER 
 
    IF @rcount > 0 BEGIN 
        /* Add count of rows deleted to APPLICATION_USAGE delete counter. */ 
        SELECT @p_delcount2 = @p_delcount2 + @rcount 
 
        /* Commit the open transaction, then start a new transaction. */ 
        COMMIT 
        SELECT @msg = N'  Transaction committed!  Rows deleted from APPLICATION_USAGE table thus far: %s' 
        EXEC sp_SFTmsg N'DEBUG'@pname@msg@p_delcount2 
        BEGIN TRANSACTION 
    END -- IF 
    ELSE BEGIN 
        SELECT @msg = N'  Nothing to delete!!!  Rows deleted from APPLICATION_USAGE table remains at: %s' 
        EXEC sp_SFTmsg N'DEBUG'@pname@msg@p_delcount2 
    END -- IF 
 
    /* Print debug of output variables. */ 
    EXEC sp_SFTmsg N'DEBUG'@pnameN'Total rows deleted from MESSAGE_LOG table:       %s'@p_delcount1 
    EXEC sp_SFTmsg N'DEBUG'@pnameN'Total rows deleted from APPLICATION_USAGE table: %s'@p_delcount2 
    EXEC sp_SFTmsg N'DEBUG'@pnameN'Usage data cleanup is complete!!!' 
 
SHRINK_FILES: 
 
    /* --------------------------------------------------------------------- *\ 
       Shrink database data files now that some data has been removed. 
    \* --------------------------------------------------------------------- */ 
 
    /* Only execute this section if the user has appropriate permissions. */ 
    IF IS_SRVROLEMEMBER(N'sysadmin') = 1 OR 
       IS_MEMBER(N'db_owner') = 1 BEGIN 
 
        /* Commit any open transactions. */ 
        /* NOTE:  This is required because BACKUP and DBCC commands must be run 
                  outside of a transaction. */ 
        WHILE (@@TRANCOUNT > 0COMMIT 
 
        /* Declare a cursor to loop through the SoftGrid related data files that 
           are set to autogrow (should be all of them as they are set to autogrow 
           by default). */ 
        DECLARE cur_datafiles CURSOR FOR 
            SELECT DISTINCT 
                   RTRIM(f.name), 
                   SIGN(fg.status & 8AS "read_only" 
              FROM sysfiles f INNER JOIN 
                   sysfilegroups fg ON (f.groupid = fg.groupidINNER JOIN 
                   sysindexes i ON (fg.groupid = i.groupidINNER JOIN 
                   sysobjects o ON (i.id = o.id) 
             WHERE f.groupid > 0 
               AND f.growth > 0 
               AND (dbo.fn_SFTisobject(o.name) = 1 OR o.type = N'S') 
 
        /* Open cursor. */ 
        OPEN cur_datafiles 
 
        /* Loop through records. */ 
        WHILE (1=1BEGIN 
 
            FETCH cur_datafiles 
             INTO @filename, 
                  @fgreadonly 
 
            IF NOT (@@FETCH_STATUS = 0 AND @err = 0BREAK 
 
            EXEC sp_SFTmsg N'DEBUG'@pnameN'Shrinking data file %s...',@filename 
 
            /* Shrink the data file as much as possible. */ 
            /* Make sure it is not in a read only filegroup before attempting this. */ 
            IF @fgreadonly = 0 BEGIN 
                /* For some reason, running with TRUNCATEONLY first makes the second 
                   command, which tries to relocate rows to unallocated pages, run 
                   much faster. */ 
                /* NOTE:  Using square brackets [] around database filename to make sure 
                          command is compatible with non standard database filenames such 
                          as those including a hyphen or starting with a number. */ 
                EXEC (N'DBCC SHRINKFILE ([' + @filename + N'], TRUNCATEONLY)') 
                EXEC (N'DBCC SHRINKFILE ([' + @filename + N'])') 
            END -- IF 
 
            SELECT @err = @@ERROR@rcount = @@ROWCOUNT 
            IF @err != 0 BREAK 
 
        END -- WHILE 
 
        /* Loop is complete.  Close the cursor. */ 
        CLOSE cur_datafiles 
        DEALLOCATE cur_datafiles 
 
        /* If an error occurred in the loop, handle the error. */ 
        IF @err != 0 GOTO ERROR_HANDLER 
 
        /* Set flag to indicate shrinking of database data files has occurred. */ 
        SELECT @p_shrinkfiles = 1 
        EXEC sp_SFTmsg N'DEBUG'@pnameN'The database data files have been successfully shrunk.' 
 
    END -- IF 
 
    ELSE BEGIN 
        /* Log message about process not being run due to insufficient privileges. */ 
        EXEC @err = sp_SFTmsg 3009@pnameNULLN'DBCC SHRINKFILE' 
        IF @err != 0 GOTO ERROR_HANDLER 
    END -- IF 
 
TRUNCATE_LOG: 
 
    /* --------------------------------------------------------------------- *\ 
       Cleanup the logical database transaction log and shrink the physical 
       database log files now that some data has been removed. 
    \* --------------------------------------------------------------------- */ 
 
    /* Only execute this section if the user has appropriate permissions. */ 
    IF IS_SRVROLEMEMBER(N'sysadmin') = 1 OR 
       IS_MEMBER(N'db_owner') = 1 OR  
       IS_MEMBER(N'db_backupoperator') = 1 BEGIN 
 
        /* Commit any open transactions. */ 
        /* NOTE:  This is required because BACKUP and DBCC commands must be run 
              outside of a transaction. */ 
        WHILE (@@TRANCOUNT > 0COMMIT 
 
        SELECT @err = @@ERROR@rcount = @@ROWCOUNT 
        IF @err != 0 GOTO ERROR_HANDLER 
 
        /* Only execute this section if the user has appropriate permissions. */ 
        IF IS_SRVROLEMEMBER(N'sysadmin') = 1 OR 
           IS_MEMBER(N'db_owner') = 1 BEGIN 
 
            /* Declare a cursor to loop through the log files that are set to autogrow. */ 
            DECLARE cur_logfiles CURSOR FOR 
                SELECT RTRIM(f.name) 
                  FROM sysfiles f 
                 WHERE f.groupid = 0 
                   AND f.growth > 0 
 
            /* Open cursor. */ 
            OPEN cur_logfiles 
 
            /* Loop through records. */ 
            WHILE (1=1BEGIN 
 
                FETCH cur_logfiles 
                 INTO @filename 
 
                IF NOT (@@FETCH_STATUS = 0 AND @err = 0BREAK 
 
                EXEC sp_SFTmsg N'DEBUG'@pnameN'Shrinking log file %s...'@filename 
 
                /* Shrink the log file as much as possible. */ 
                /* NOTE:  Using square brackets [] around database filename to make sure 
                          command is compatible with non standard database filenames such 
                          as those including a hyphen or starting with a number. */ 
                EXEC (N'DBCC SHRINKFILE ([' + @filename + N'], TRUNCATEONLY)') 
 
                SELECT @err = @@ERROR@rcount = @@ROWCOUNT 
                IF @err != 0 BREAK 
 
            END -- WHILE 
 
            /* Loop is complete.  Close the cursor. */ 
            CLOSE cur_logfiles 
            DEALLOCATE cur_logfiles 
 
            /* If an error occurred in the loop, handle the error. */ 
            IF @err != 0 GOTO ERROR_HANDLER 
 
        END -- IF 
 
        ELSE BEGIN 
            /* Log message about process not being run due to insufficient privileges. */ 
            EXEC @err = sp_SFTmsg 3009@pnameNULLN'DBCC SHRINKFILE' 
            IF @err != 0 GOTO ERROR_HANDLER 
        END -- IF 
 
        /* Set flag to indicate truncating of database transaction log has occurred. */ 
        SELECT @p_truncatelog = 1 
        EXEC sp_SFTmsg N'DEBUG'@pnameN'The database transaction log has been successfully truncated.' 
 
    END -- IF 
 
    ELSE BEGIN 
        /* Log message about process not being run due to insufficient privileges. */ 
        EXEC @err = sp_SFTmsg 3009@pnameNULLN'BACKUP LOG' 
        IF @err != 0 GOTO ERROR_HANDLER 
    END -- IF 
 
    /* Restart transaction(s) to get back to proper transaction count after 
       successful execution of this procedure. */ 
    /* NOTE:  Any procedures calling this procedure expect there to be an open 
              transaction when returning successfully. */ 
 
    /* Restart at least one transaction. */ 
    IF @@TRANCOUNT = 0 BEGIN TRANSACTION 
 
    /* Then, make sure transaction count equals when procedure was entered. */ 
    WHILE (@@TRANCOUNT < @tcountBEGIN TRANSACTION 
 
ERROR_HANDLER: 
    IF @err != 0 BEGIN 
        SELECT @msg = N'Returning with exception from ' + @pname + N'!!!' 
        EXEC sp_SFTmsg N'INFO',@pname,@msg 
        SELECT @msg = N'The error is: ' + CONVERT(nvarchar,@err) 
        EXEC sp_SFTmsg N'INFO',@pname,@msg 
 
        /* Rollback (if necessary) and return the error. */ 
        IF @@TRANCOUNT > 0 ROLLBACK 
        RETURN @err 
    END -- IF 
    WHILE (@@TRANCOUNT > @tcountCOMMIT 
 
    EXEC sp_SFTmsg N'TRACEOUT',@pname 
END 
 
GO