Question

I am trying to write a cursor. I have created a table for capturing login name and time from sys.dm_exec_sessions. Now, I need to write a cursor to update the login time to last login time if the login already exists and insert a row in case login does not exists in my table. I have come up with following, but unfortunately I am getting an error with subquery returning more than one value for it. Any ideas???

declare @log as varchar(200)
declare @log_time as datetime
declare LoginsSize cursor for
        SELECT  login_name, login_time
        FROM sys.dm_exec_sessions 
open LoginsSize
            fetch next from LoginsSize into @log, @log_time
            while( @@fetch_status = 0)
        begin                                                           
          If (Select Login from [dbo].[LoginsForDBUserList])  = @log 

             Begin
             UPDATE  [dbo].[LoginsForDBUserList]
             SET     LastLoginTime = @log_time
             WHERE   [login]= @log
             END

             Else 

             Begin
             Insert Into [dbo].[LoginsForDBUserList]
             SELECT  login_name, login_time
             FROM sys.dm_exec_sessions
             END

        fetch next from LoginsSize into @log, @log_time
        close LoginsSize
        deallocate LoginsSize

end
Was it helpful?

Solution

I think that error is being generated because of this line

If (Select Login from [dbo].[LoginsForDBUserList])  = @log

Multiple rows are being returned from the left side of the equal sign and is attempting to be compared to the single value @log.

I've made some adjustments to your original query and it works for me. Give this a try:

--demo setup
DROP TABLE IF EXISTS LoginsForDBUserList 
GO
CREATE TABLE LoginsForDBUserList (
    LOGIN VARCHAR(200)
    ,LastLoginTime DATETIME
    )

--Adjustments to your original process
DECLARE @log AS VARCHAR(200)
DECLARE @log_time AS DATETIME

DECLARE LoginsSize CURSOR
FOR
SELECT login_name
    ,login_time
FROM sys.dm_exec_sessions

OPEN LoginsSize

FETCH NEXT
FROM LoginsSize
INTO @log
    ,@log_time

WHILE (@@fetch_status = 0)
BEGIN
    IF EXISTS (
            SELECT LOGIN
            FROM LoginsForDBUserList
            WHERE LOGIN = @log
            )
    BEGIN
        UPDATE LoginsForDBUserList
        SET LastLoginTime = @log_time
        WHERE [login] = @log
    END
    ELSE
    BEGIN
        INSERT INTO LoginsForDBUserList
        SELECT login_name
            ,login_time
        FROM sys.dm_exec_sessions
    END

    FETCH NEXT
    FROM LoginsSize
    INTO @log
        ,@log_time
END

CLOSE LoginsSize

DEALLOCATE LoginsSize

SELECT *
FROM LoginsForDBUserList

OTHER TIPS

@Scott has already given the answer to your question. But I hope you can ditch that cursor and use a SET based code here.

UPDATE a
   SET LastLoginTime = b.login_time
  FROM [dbo].[LoginsForDBUserList] a
  JOIN sys.dm_exec_sessions b
    ON a.login = b.login_name;

IF EXISTS (   SELECT      1
                FROM      sys.dm_exec_sessions b
                LEFT JOIN [dbo].[LoginsForDBUserList] a
                  ON a.login = b.login_name
               WHERE      a.login IS NULL)
BEGIN
    INSERT INTO [dbo].[LoginsForDBUserList]
    SELECT      login_name,
                login_time
      FROM      sys.dm_exec_sessions b
      LEFT JOIN [dbo].[LoginsForDBUserList] a
        ON a.login = b.login_name
     WHERE      a.login IS NULL;
END;
Licensed under: CC-BY-SA with attribution
Not affiliated with dba.stackexchange
scroll top