Oggi un mio collega mi ha posto un quesito al quale risposi tempo fa su
microsoft.public.it.sql: "Sai un metodo per killare tutti i processi in una botta sola?"
Sappiamo tutti che SQL Server permette di terminare una connessione ed internamente tutte le transazioni associate tramite la funzione
KILL, specificando come argomento il
ProcessID.
A volte può essere comodo chiudere tutte le connessioni ad un database in una volta sola, senza la necessità di rendere lo stato permanente mediante il comando:
ALTER DATABASE [nome db]
SET SINGLE_USER
WITH ROLLBACK IMMEDIATE
Purtroppo SQL Server non offre una simile funzionalità, però nessuno ci vieta di aguzzare l'ingegno
Le stored procedure di sistema
sp_who e sp_who2 (non documentata) ci forniscono diverse informazioni sugli utenti e le conessioni attive, così ho pensato di utilizzare queste procedure per definire una nuova stored procedure che in base al database passato come argomento, chiude tutte le connessioni attive ad esso ad esclusione di quella corrente:
USE tempdb
GO
/* Creo la Stored Procedure dbo.up_CloseSessions */
CREATE PROCEDURE dbo.up_CloseSessions(
@dbname nchar(128)
)
AS
/* Processo corrente */
DECLARE @spid smallint
/* Statement SQL */
DECLARE @strSQL varchar(10)
/* Creo la tabella temporanea dbo.#tmpProcesses */
CREATE TABLE dbo.#tmpProcesses(
spid smallint,
ecid smallint,
status nchar(30),
loginame nchar(128),
hostname nchar(128),
blk char(5),
dbname nchar(128),
cmd nchar(16)
)
/* La popolo */
INSERT dbo.#tmpProcesses
EXEC sp_who
/* Dichiaro il cursore */
DECLARE curKill CURSOR FOR
SELECT spid
FROM dbo.#tmpProcesses
WHERE dbname = @dbname AND
spid <> @@spid
/* Apro il cursore */
OPEN curKill
/* Prima lettura */
FETCH NEXT FROM curKill
INTO @spid
/* Loop */
WHILE @@FETCH_STATUS = 0
BEGIN
/* Chiudo la sessione corrente */
SET @strSQL = 'KILL ' + CAST(@spid AS varchar)
EXEC (@strSQL)
/* Letture successive */
FETCH NEXT FROM curKill
INTO @spid
END
/* Dealloco e chiudo il cursore */
CLOSE curKill
DEALLOCATE curKill
GO
E' possibile verificarne il funzionamento aprendo ad esempio 5 o 6 connessioni al database Northwind tramite il Query Analyzer ed eseguendo il seguente script:
/* Visualizzo i processi attivi */
EXEC sp_who
GO
/* Disconnetto tutti gli utenti
** (tranne me) da Northwind
*/
EXEC dbo.up_CloseSessions 'Northwind'
GO
/* Visualizzo i processi attivi */
EXEC sp_who
GO
Se preferite potete definire la stored procedure direttamente nel database
master in modo che sia sempre disponibile