SQL Server: Filter output sp_who2


191

Di bawah SQL Server, apakah ada cara mudah untuk memfilter output sp_who2? Katakanlah saya ingin hanya menunjukkan baris untuk database tertentu, misalnya.


2
sebagai @Nick telah mengisyaratkan, pandangan manajemen dinamis (DMVs) juga layak untuk dilihat.
Mitch Wheat

Saya telah menambahkan jawaban yang menggunakan DMV bukan sp_who2
N30

Jawaban:


349

Anda dapat mencoba sesuatu seperti

DECLARE @Table TABLE(
        SPID INT,
        Status VARCHAR(MAX),
        LOGIN VARCHAR(MAX),
        HostName VARCHAR(MAX),
        BlkBy VARCHAR(MAX),
        DBName VARCHAR(MAX),
        Command VARCHAR(MAX),
        CPUTime INT,
        DiskIO INT,
        LastBatch VARCHAR(MAX),
        ProgramName VARCHAR(MAX),
        SPID_1 INT,
        REQUESTID INT
)

INSERT INTO @Table EXEC sp_who2

SELECT  *
FROM    @Table
WHERE ....

Dan filter pada apa yang Anda butuhkan.


+1 @ bo-flexson memiliki ekstensi yang bagus untuk pendekatan ini.
Lankymart

115

Anda bisa menyimpan hasilnya ke tabel temp , tetapi akan lebih baik untuk langsung menuju ke sumber master.dbo.sysprocesses.

Berikut permintaan yang akan mengembalikan hasil yang hampir sama persis dengan sp_who2:

SELECT  spid,
        sp.[status],
        loginame [Login],
        hostname, 
        blocked BlkBy,
        sd.name DBName, 
        cmd Command,
        cpu CPUTime,
        physical_io DiskIO,
        last_batch LastBatch,
        [program_name] ProgramName   
FROM master.dbo.sysprocesses sp 
JOIN master.dbo.sysdatabases sd ON sp.dbid = sd.dbid
ORDER BY spid 

Sekarang Anda dapat dengan mudah menambahkan ORDER BYatau WHEREklausa yang Anda sukai untuk mendapatkan hasil yang berarti.


Atau, Anda dapat mempertimbangkan menggunakan Monitor Aktivitas di SSMS ( Ctrl+ Alt+ A) juga


diblokir berbeda dengan BlkBy. diblokir adalah korban yang sedang menunggu untuk melepaskan kunci. BlkBy adalah penjahat yang menyebabkan kunci. Jadi menggunakan BlkBy alias ke kolom yang diblokir benar-benar salah. Jika sp_who mengembalikan 1 sebagai SPID, 2 sebagai BlkBy, 1 diblokir oleh 2.
doctorgu

25

Salah satu caranya adalah membuat tabel temp:

CREATE TABLE #sp_who2 
(
   SPID INT,  
   Status VARCHAR(1000) NULL,  
   Login SYSNAME NULL,  
   HostName SYSNAME NULL,  
   BlkBy SYSNAME NULL,  
   DBName SYSNAME NULL,  
   Command VARCHAR(1000) NULL,  
   CPUTime INT NULL,  
   DiskIO INT NULL,  
   LastBatch VARCHAR(1000) NULL,  
   ProgramName VARCHAR(1000) NULL,  
   SPID2 INT
) 
GO

INSERT INTO #sp_who2
EXEC sp_who2
GO

SELECT *
FROM #sp_who2
WHERE Login = 'bla'
GO

DROP TABLE #sp_who2
GO

pilih * dari sp_who2 di mana login = 'bla' - haruskah tabel referensi di sini oleh # sp_who2?
Peter Schofield

Mendapatkan "Nama kolom atau jumlah nilai yang disediakan tidak cocok dengan definisi tabel." menjalankan ini pada SQL 2008 R2
TheLegendaryCopyCoder

11

berdasarkan http://web.archive.org/web/20080218124946/http://sqlserver2005.databases.aspfaq.com/how-do-i-mimim-sp-who2.html

saya telah membuat skrip berikut,
yang memutuskan menemukan koneksi aktif ke basis data apa pun menggunakan DMV ini berfungsi di bawah sql 2005, 2008 dan 2008R2

Script berikut menggunakan sys.dm_exec_sessions , sys.dm_exec_requests , sys.dm_exec_connections , sys.dm_tran_locks

Declare @dbName varchar(1000)
set @dbName='abc'

;WITH DBConn(SPID,[Status],[Login],HostName,DBName,Command,LastBatch,ProgramName)
As
(
SELECT 
    SPID = s.session_id,
    Status = UPPER(COALESCE
        (
            r.status,
            ot.task_state,
            s.status, 
        '')),
    [Login] = s.login_name,
    HostName = COALESCE
        (
            s.[host_name],
            '  .'
        ),
    DBName = COALESCE
        (
            DB_NAME(COALESCE
            (
                r.database_id,
                t.database_id
            )),
            ''
        ),
    Command = COALESCE
        (
            r.Command,
            r.wait_type,
            wt.wait_type,
            r.last_wait_type,
            ''
        ),
    LastBatch = COALESCE
        (
            r.start_time,
            s.last_request_start_time
        ),
    ProgramName = COALESCE
        (
            s.program_name, 
            ''
        )
FROM
    sys.dm_exec_sessions s
LEFT OUTER JOIN
    sys.dm_exec_requests r
ON
    s.session_id = r.session_id
LEFT OUTER JOIN
    sys.dm_exec_connections c
ON
    s.session_id = c.session_id
LEFT OUTER JOIN
(
    SELECT 
        request_session_id,
        database_id = MAX(resource_database_id)
    FROM
        sys.dm_tran_locks
    GROUP BY
        request_session_id
) t
ON
    s.session_id = t.request_session_id
LEFT OUTER JOIN
    sys.dm_os_waiting_tasks wt
ON 
    s.session_id = wt.session_id
LEFT OUTER JOIN
    sys.dm_os_tasks ot
ON 
    s.session_id = ot.session_id
LEFT OUTER JOIN
(
    SELECT
        ot.session_id,
        CPU_Time = MAX(usermode_time)
    FROM
        sys.dm_os_tasks ot
    INNER JOIN
        sys.dm_os_workers ow
    ON
        ot.worker_address = ow.worker_address
    INNER JOIN
        sys.dm_os_threads oth
    ON
        ow.thread_address = oth.thread_address
    GROUP BY
        ot.session_id
) tt
ON
    s.session_id = tt.session_id
WHERE
    COALESCE
    (
        r.command,
        r.wait_type,
        wt.wait_type,
        r.last_wait_type,
        'a'
    ) >= COALESCE
    (
        '', 
        'a'
    )
)

Select * from DBConn
where DBName like '%'+@dbName+'%'

terlalu rumit jika dibandingkan dengan jawaban lain. tapi pantas mendapat suara positif
Doan Cuong

Tidak selalu berguna oleh DB, lebih suka pendekatan @astander dan @ bo-flexson .
Lankymart

1
Yang ini menunjukkan bagaimana cara bergabung dengan proses OS induk, yang saya inginkan.
redcalx

Saya menemukan bahwa penggunaan sys.dm_tran_locks adalah skrip ini secara besar-besaran memperlambat kode ini jika Anda memiliki banyak kunci transaksi terbuka (misalnya transaksi yang berjalan lama).
Mike

6

Sedikit perbaikan pada jawaban Astander . Saya suka menempatkan kriteria saya di atas, dan membuatnya lebih mudah untuk digunakan kembali sehari-hari:

DECLARE @Spid INT, @Status VARCHAR(MAX), @Login VARCHAR(MAX), @HostName VARCHAR(MAX), @BlkBy VARCHAR(MAX), @DBName VARCHAR(MAX), @Command VARCHAR(MAX), @CPUTime INT, @DiskIO INT, @LastBatch VARCHAR(MAX), @ProgramName VARCHAR(MAX), @SPID_1 INT, @REQUESTID INT

    --SET @SPID = 10
    --SET @Status = 'BACKGROUND'
    --SET @LOGIN = 'sa'
    --SET @HostName = 'MSSQL-1'
    --SET @BlkBy = 0
    --SET @DBName = 'master'
    --SET @Command = 'SELECT INTO'
    --SET @CPUTime = 1000
    --SET @DiskIO = 1000
    --SET @LastBatch = '10/24 10:00:00'
    --SET @ProgramName = 'Microsoft SQL Server Management Studio - Query'
    --SET @SPID_1 = 10
    --SET @REQUESTID = 0

    SET NOCOUNT ON 
    DECLARE @Table TABLE(
            SPID INT,
            Status VARCHAR(MAX),
            LOGIN VARCHAR(MAX),
            HostName VARCHAR(MAX),
            BlkBy VARCHAR(MAX),
            DBName VARCHAR(MAX),
            Command VARCHAR(MAX),
            CPUTime INT,
            DiskIO INT,
            LastBatch VARCHAR(MAX),
            ProgramName VARCHAR(MAX),
            SPID_1 INT,
            REQUESTID INT
    )
    INSERT INTO @Table EXEC sp_who2
    SET NOCOUNT OFF
    SELECT  *
    FROM    @Table
    WHERE
    (@Spid IS NULL OR SPID = @Spid)
    AND (@Status IS NULL OR Status = @Status)
    AND (@Login IS NULL OR Login = @Login)
    AND (@HostName IS NULL OR HostName = @HostName)
    AND (@BlkBy IS NULL OR BlkBy = @BlkBy)
    AND (@DBName IS NULL OR DBName = @DBName)
    AND (@Command IS NULL OR Command = @Command)
    AND (@CPUTime IS NULL OR CPUTime >= @CPUTime)
    AND (@DiskIO IS NULL OR DiskIO >= @DiskIO)
    AND (@LastBatch IS NULL OR LastBatch >= @LastBatch)
    AND (@ProgramName IS NULL OR ProgramName = @ProgramName)
    AND (@SPID_1 IS NULL OR SPID_1 = @SPID_1)
    AND (@REQUESTID IS NULL OR REQUESTID = @REQUESTID)

4

Ada beberapa prosedur baik yang disimpan pengguna sp_who3 di luar sana - Saya yakin Adam Machanic melakukan yang benar-benar bagus, AFAIK.

Adam menyebutnya Who Is Active: http://whoisactive.com


Saya mencoba ini, itu tidak mudah ... Saya memposting cara lain yang mirip dengan beberapa posting lain ini (tetapi sudah teruji dan benar).
Don Rolling

4

Mirip dengan jawaban KyleMit , mungkin untuk memilih langsung tabel yang digunakan oleh SP_WHO2, meskipun saya pikir itu hanya perlu tabel dbo.sysprocesses.

Jika seseorang membuka SP ini, ia bisa mengerti apa fungsinya. Ini adalah pilihan terbaik saya untuk memiliki output yang sama dengan SP_WHO2

select convert(char(5),sp.spid) as SPID
        ,  CASE lower(sp.status)
                 When 'sleeping' Then lower(sp.status)
                 Else  upper(sp.status)
              END as Status
        , convert(sysname, rtrim(sp.loginame)) as LOGIN
        , CASE sp.hostname
                 When Null  Then '  .'
                 When ' ' Then '  .'
                 Else    rtrim(sp.hostname)
              END as HostName
        , CASE isnull(convert(char(5),sp.blocked),'0')
                 When '0' Then '  .'
                 Else isnull(convert(char(5),sp.blocked),'0')
              END as BlkBy
        , case when sp.dbid = 0 then null when sp.dbid <> 0 then db_name(sp.dbid) end as DBName
        , sp.cmd as Command
        , sp.cpu as CPUTime
        , sp.physical_io as DiskIO
        , sp.last_batch as LastBatch
        , sp.program_name as ProgramName 
        from master.dbo.sysprocesses sp (nolock)
  ;

Selama pemilihan ini, Anda dapat memilih bidang yang Anda butuhkan dan memiliki urutan yang Anda inginkan.


Bekerja sangat baik untuk saya
Shai Alon

3

Cara yang sangat mudah untuk melakukannya adalah dengan membuat tautan ODBC di EXCEL dan menjalankan SP_WHO2 dari sana.

Anda dapat Menyegarkan kapan pun Anda mau dan karena EXCEL semuanya dapat dimanipulasi dengan mudah!


7
Apakah Anda yakin ini cara termudah?
geomagas

2

Ya, dengan menangkap output sp_who2 ke dalam tabel dan kemudian memilih dari tabel, tapi itu akan menjadi cara yang buruk untuk melakukannya. Pertama, karena sp_who2, terlepas dari popularitasnya, ini merupakan prosedur tidak berdokumen dan Anda tidak boleh bergantung pada prosedur tidak berdokumen. Kedua karena semua sp_who2 dapat melakukan, dan banyak lagi, dapat diperoleh dari sys.dm_exec_requests dan DMV lainnya, dan pertunjukan dapat disaring, dipesan, bergabung, dan semua barang lainnya yang datang dengan rowsets yang cukup bagus.


4
Ini adalah satu kasus di mana saya tidak akan menggunakan DMV connect.microsoft.com/SQLServer/feedback/details/257502/…
gbn

1

Perpanjangan jawaban pertama dan terbaik ... Saya telah membuat prosedur tersimpan pada database master yang kemudian dapat Anda berikan parameternya .. seperti nama database:

USE master
GO

CREATE PROCEDURE sp_who_db
(
    @sDBName varchar(200)   = null,
    @sStatus varchar(200)   = null,
    @sCommand varchar(200)  = null,
    @nCPUTime int           = null
)
AS
DECLARE @Table TABLE
(
    SPID INT,
    Status VARCHAR(MAX),
    LOGIN VARCHAR(MAX),
    HostName VARCHAR(MAX),
    BlkBy VARCHAR(MAX),
    DBName VARCHAR(MAX),
    Command VARCHAR(MAX),
    CPUTime INT,
    DiskIO INT,
    LastBatch VARCHAR(MAX),
    ProgramName VARCHAR(MAX),
    SPID_1 INT,
    REQUESTID INT
)

INSERT INTO @Table EXEC sp_who2

SELECT  *
    FROM    @Table
    WHERE   (@sDBName IS NULL OR DBName = @sDBName)
    AND     (@sStatus IS NULL OR Status = @sStatus)
    AND     (@sCommand IS NULL OR Command = @sCommand)
    AND     (@nCPUTime IS NULL OR CPUTime > @nCPUTime)
GO 

Saya mungkin memperluasnya untuk menambahkan pesanan dengan parameter atau bahkan paramatmer membunuh sehingga membunuh semua koneksi ke data tertentu


0

Saya menulis di sini untuk penggunaan saya sendiri di masa depan. Ini menggunakan sp_who2 dan memasukkan ke dalam variabel tabel bukan tabel temp karena tabel Temp tidak dapat digunakan dua kali jika Anda tidak menjatuhkannya. Dan menunjukkan diblokir dan diblokir pada baris yang sama.

--blocked: waiting becaused blocked by blocker
--blocker: caused blocking
declare @sp_who2 table(
    SPID int,
    Status varchar(max),
    Login varchar(max),
    HostName varchar(max),
    BlkBy varchar(max),
    DBName varchar(max),
    Command varchar(max),
    CPUTime int,
    DiskIO int,
    LastBatch varchar(max),
    ProgramName varchar(max),
    SPID_2 int,
    REQUESTID int
)
insert into @sp_who2 exec sp_who2
select  w.SPID blocked_spid, w.BlkBy blocker_spid, tblocked.text blocked_text, tblocker.text blocker_text
from    @sp_who2 w
        inner join sys.sysprocesses pblocked on w.SPID = pblocked.spid
        cross apply sys.dm_exec_sql_text(pblocked.sql_handle) tblocked
        inner join sys.sysprocesses pblocker on case when w.BlkBy = '  .' then 0 else cast(w.BlkBy as int) end = pblocker.spid
        cross apply sys.dm_exec_sql_text(pblocker.sql_handle) tblocker
where   pblocked.Status = 'SUSPENDED'

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.