I am trying to pull the input buffer data (DBCC INPUTBUFFER(@SPID)
) for each record returned for a database when querying the SYSPROCESSES
table. I am interested to hear if there is a better way to accomplish this, but would also appreciate correction to what I currently have working for learning purposes.
DECLARE @Max [int]
DECLARE @Min [int] = 1
SELECT @Max = COUNT(SPID)
FROM MASTER.DBO.SYSPROCESSES
WHERE DB_NAME(DBID) = 'Northwinds' AND DBID != 0
CREATE TABLE开发者_开发知识库 #Results (
EventType [nvarchar](1024),
Parameters [int],
EventInfo [nvarchar](1024),
SPID [int],
STATUS [nvarchar](255),
PROGRAM_NAME [nvarchar](1024),
CMD [nvarchar](255),
LOGINAME [nvarchar](255)
)
WHILE @Min <= @Max
BEGIN
DECLARE @SPID [int]
WITH SelectedRow AS (
SELECT SPID, ROW_NUMBER() OVER (ORDER BY SPID) AS RowNumber
FROM MASTER.DBO.SYSPROCESSES
WHERE DB_NAME(DBID) = 'Northwinds' AND DBID != 0
)
SELECT @SPID = SPID
FROM SelectedRow
WHERE RowNumber = @Min
DECLARE @InputBuffer TABLE (
EventType [nvarchar](1024),
Parameter [int],
EventInfo [nvarchar](1024)
)
DECLARE @SysProcesses TABLE (
SPID [int],
STATUS [nvarchar](255),
PROGRAM_NAME [nvarchar](1024),
CMD [nvarchar](255),
LOGINAME [nvarchar](255)
)
INSERT @InputBuffer
EXEC('DBCC INPUTBUFFER('+@SPID+')')
INSERT @SysProcesses
SELECT SPID, STATUS, PROGRAM_NAME, CMD, LOGINAME
FROM MASTER.DBO.SYSPROCESSES
WHERE DB_NAME(DBID) = 'Northwinds' AND DBID != 0 AND SPID = @SPID
INSERT INTO #TempResults(EventType, Parameters, EventInfo, SPID, STATUS, PROGRAM_NAME, CMD, LOGINAME)
SELECT *
FROM @InputBuffer, @SysProcesses
SET @Min = (@Min + 1)
END
Now when I execute the following query:
SELECT SPID
FROM MASTER.DBO.SYSPROCESSES
WHERE DB_NAME(DBID) = 'Northwinds' AND DBID != 0
it returns 31 rows...
However when I SELECT * FROM #TempResults
after executing the above loop I am returning mass amounts of duplicates in the temp table...to the sum of 10751.
Again this is mostly for learning, but would be a pretty handy function to have as well. I am looking for information on what I'm missing causing the duplicate records to be returned, as well as a possible better solution.
You are doing this:
INSERT #Results
SELECT *
FROM @InputBuffer, @SysProcesses
This is effectively a cross join, so if either table has more than one row, you're going to have COUNT(left side) * COUNT(right side)
rows as a result. Maybe you should use SELECT DISTINCT column list
instead or, as I suggested in my comment, stop looping through sysprocesses
(deprecated) and retrieving info from DBCC INPUTBUFFER
- even for educational purposes that is painful.
Please refer below query for better result
DEclare @SPID [int]
DEclare @database_name [nvarchar](1024)
DEclare @hostname [nvarchar](1024)
DEclare @PROGRAM_NAME [nvarchar](1024)
DEclare @LOGINNAME [nvarchar](255)
DEclare @Inputbuffer [nvarchar] (4000)
CREATE TABLE #TempResults (
SPID [int],
database_name [nvarchar](1024),
hostname [nvarchar](1024),
PROGRAM_NAME [nvarchar](1024),
LOGINAME [nvarchar](255),
EventType [nvarchar](1024),
Parameters [int],
EventInfo [nvarchar](4000)
)
DECLARE db_cursor CURSOR FOR
select spid,db_name(dbid), hostname,program_name,loginame from sys.sysprocesses where dbid in(11,10,13,14,15,16)
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO @spid,@database_name,@hostname,@program_name,@loginname
WHILE @@FETCH_STATUS = 0
BEGIN
create table #InputBuffer1 (
EventType [nvarchar](1024),
Parameter [int],
EventInfo [nvarchar](4000)
)
INSERT into #InputBuffer1
EXEC('DBCC INPUTBUFFER('+@SPID+')')
create TABLE #SysProcesses (
SPID [int],
database_name [nvarchar](1024),
hostname [nvarchar](1024),
PROGRAM_NAME [nvarchar](1024),
LOGINAME [nvarchar](255)
)
INSERT INTO #SysProcesses(spid,database_name,hostname,program_name,LOGINAME)
SELECT @spid,@database_name,@hostname,@program_name,@loginname
insert into #TempResults
select * from #SysProcesses,#InputBuffer1
drop table #InputBuffer1
drop table #SysProcesses
FETCH NEXT FROM db_cursor INTO @spid,@database_name,@hostname,@program_name,@loginname
END
CLOSE db_cursor
DEALLOCATE db_cursor
select * from #TempResults
May be is later, but for anyone interested, MASTER.DBO.sysprocesses returns a row for each parel procees and sys.sysprocesses only the parent process.
精彩评论