2

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
0

2 Answers 2

5

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
0
2

@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;

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.