expunge_users


IF EXISTS (SELECT * FROM sysobjects 
           WHERE id = OBJECT_ID('dbo.expunge_users') 
           AND sysstat & 0xf = 4)
	DROP PROCEDURE dbo.expunge_users
GO

CREATE PROCEDURE expunge_users
     @dbName VARCHAR(30) = ' ',
     @target VARCHAR(30) = ' ',
     @targetPassword VARCHAR(30) = ' ',
     @saPassword VARCHAR(30) = ' ',
     @path VARCHAR(50) = ' ',
     @debug VARCHAR(5) = 'false'
AS
DECLARE @bail SMALLINT,
        @CMD VARCHAR(255), 
        @CMDstatus INT,
        @myName VARCHAR(30), 
        @spidToKill VARCHAR(5)    

/* 
  Procedure expunge_users will attempt to remove all users
  from a database. Misbehaved code that leaves zombies will
  prevent the zombie spid from stopping (because its not really
  active). Long running atomic processes like a huge insert or
  update may require more time to end than a WAITING COMMAND spid.
*/

IF (@dbName <> ' ') AND (@target <> ' ') AND (@path <> ' ')
  BEGIN
    SELECT @myName = 'admin.expunge_users'
    /* If every one is not being killed, increase the @bail threshold */
    SELECT @bail = 10 
    WHILE (@bail > 0)
      BEGIN
        DELETE messenger where spid = @@SPID
        SELECT @CMD = "SELECT max(spid) FROM master..sysprocesses " +
                      "WHERE dbid = (SELECT dbid FROM master..sysdatabases " +
                      "WHERE name = '" + @dbName + "')"
        SELECT @CMD = 'isql -Usa -P' + @targetPassword + ' -S' + @target + 
                      ' -dmaster -Q"' + @CMD + '" -o' + @path +
                      '\userCount.txt'
        EXEC @CMDstatus = dispatch @CMD, @myName, @debug
        IF (@CMDstatus <> 0) return @CMDstatus

        EXEC hold_semaphore 'textreader'
          TRUNCATE TABLE textreader
          SELECT @CMD = 'bcp admin..textreader in ' + @path + 
                        '\userCount.txt -c -Usa -P' + @saPassword +
                        ' -S' + @@SERVERNAME 
          EXEC @CMDstatus = dispatch @CMD, @myName, @debug
          IF (@CMDstatus <> 0) return @CMDstatus
          INSERT messenger SELECT @@SPID, text from textreader
          TRUNCATE TABLE textreader 
          SELECT @CMD = 'isql -Usa -P' + @targetPassword + ' -S' + @target + 
                        ' -dmaster -Q"master..xp_cmdshell ' + "'del " + 
                        @path + "\userCount.txt'" + '"'
          EXEC @CMDstatus = dispatch @CMD, @myName, @debug
          IF (@CMDstatus <> 0) return @CMDstatus
          INSERT messenger 
          SELECT @@SPID, RTRIM(LTRIM(text)) 
          FROM textreader
          TRUNCATE TABLE textreader     
        EXEC release_semaphore 'textreader'

        SELECT @spidToKill = (SELECT min(info) FROM messenger 
                                               WHERE spid = @@SPID
                                               AND info <> " " 	
                                               AND info NOT LIKE "---%"
                                               AND info NOT LIKE "%affected)%")
        IF (SELECT ISNUMERIC(@spidToKill))= 0
          SELECT @bail = -1
        ELSE
          BEGIN  
            IF (@target = @@SERVERNAME) 
              AND
               (CONVERT(VARCHAR(5), @@SPID) = @spidToKill)
                  BEGIN
                    SELECT @CMD = 'Cannot load database ' + @dbName + ' on ' + @target
                                   + '. This process is running in the database.'
                    EXEC @CMDstatus = dispatch @CMD, @myName, @debug
                    RETURN @CMDStatus
                  END       
            SELECT @CMD = "kill " + @spidToKill
            SELECT @CMD = 'isql -Usa -P' + @targetPassword + ' -S' + @target + 
                          ' -dmaster -Q"' + @CMD + '"'
            EXEC @CMDstatus = dispatch @CMD, @myName, @debug
            IF (@CMDstatus <> 0) return @CMDstatus
            IF @bail = 0
              BEGIN
                SELECT @CMD = 'There are active users in ' + 
                              @dbName + ' on ' + @target + 
                              ' that cannot be disconnected at this time.' 
                EXEC @CMDstatus = dispatch @CMD, @myName, @debug
                IF (@CMDstatus <> 0) return @CMDstatus
              END
            SELECT @bail = @bail - 1  
          END
      END 
    DELETE messenger where spid = @@SPID
    RETURN
  END
ELSE
  BEGIN
    PRINT "      usage: expunge_users [@dbName = <database name>, ]"
    PRINT "                           [@target = <target SQL Server>,         ]"
    PRINT "                           [@targetPassword = <target sa password>,]"
    PRINT "                           [@saPassword = <admin sa password>,     ]"
    PRINT "                           [@path = <output file location>,        ]"
    PRINT "                           [@debug = <debug  - default=false>      ]"
    RETURN 1
  END
GO