Search code examples
sqlsql-serversql-server-2017

Replace this cursor function to a while loop function


I made this stored procedure that takes as parameters username, password, firstname, lastname, DOB, email from a table I created called newusers and puts them in the corresponding tables which have the fields mentioned. I used this cursor function to do it but they told me that a cursor isn't a good idea so how can I replace this with a while loop function?

ALTER PROCEDURE [dbo].[Savenewuser] 
AS 
    DECLARE @username VARCHAR(100); 
    DECLARE @password VARCHAR(100); 
    DECLARE @firstname VARCHAR(100); 
    DECLARE @lastname VARCHAR(100); 
    DECLARE @address VARCHAR(100); 
    DECLARE @birthdate DATE; 
    DECLARE @email VARCHAR(100); 
BEGIN 
    DECLARE newuser_cursor CURSOR FOR 
        SELECT username, 
               password, 
               firstname, 
               lastname, 
               address, 
               birthdate, 
               email 
        FROM   newuser 

    OPEN newuser_cursor 

    FETCH next FROM newuser_cursor INTO @username, @password, @firstname, 
        @lastname, @address, @birthdate, @email 
END 

WHILE @@FETCH_STATUS = 0 
BEGIN 
    INSERT INTO users (username, password) 
        SELECT @username, @password 

    FETCH next FROM newuser_cursor INTO @username, @password, @firstname, 
          @lastname, @address, @birthdate, @email 
END 

CLOSE newuser_cursor 

BEGIN 
    OPEN newuser_cursor 

    FETCH next FROM newuser_cursor INTO @username, @password, @firstname, 
        @lastname, @address, @birthdate, @email 
END 

WHILE @@FETCH_STATUS = 0 
BEGIN 
    INSERT INTO userdetails (first_name, last_name, user_address, dob) 
          SELECT @firstname, @lastname, @address, @birthdate 

    FETCH next FROM newuser_cursor INTO @username, @password, @firstname, 
        @lastname, @address, @birthdate, @email 
END 

CLOSE newuser_cursor 

BEGIN 
    OPEN newuser_cursor 

    FETCH next FROM newuser_cursor INTO @username, @password, @firstname, 
        @lastname, @address, @birthdate, @email 
END 

WHILE @@FETCH_STATUS = 0 
BEGIN 
    INSERT INTO emailbook (email) 
         SELECT @email 

    FETCH next FROM newuser_cursor INTO @username, @password, @firstname, 
         @lastname, @address, @birthdate, @email 
END 

CLOSE newuser_cursor 

DEALLOCATE newuser_cursor 

Solution

  • It is just for this question, I do not recommend to use this approach in any case.

    Since you want to do this by using cursor only, so refining your query.

    You don't need to open and close your cursor after every insert command, since you'll get the records in first fetch statement then afterward you may write all of your insert command in one go. then close and deallocate cursor.

    
        ALTER PROCEDURE [dbo].[Savenewuser] 
        AS 
        DECLARE @username VARCHAR(100); 
        DECLARE @password VARCHAR(100); 
        DECLARE @firstname VARCHAR(100); 
        DECLARE @lastname VARCHAR(100); 
        DECLARE @address VARCHAR(100); 
        DECLARE @birthdate DATE; 
        DECLARE @email VARCHAR(100); 
        BEGIN 
            DECLARE newuser_cursor CURSOR FOR 
            SELECT username, 
                password, 
                firstname, 
                lastname, 
                address, 
                birthdate, 
                email 
            FROM   newuser 
    
            OPEN newuser_cursor 
    
            FETCH next FROM newuser_cursor INTO @username, @password, @firstname, 
            @lastname, @address, @birthdate, @email 
    
    
            WHILE @@FETCH_STATUS = 0 
            BEGIN 
                INSERT INTO users (username, password) 
                SELECT @username, @password 
    
                INSERT INTO userdetails (first_name, last_name, user_address, dob) 
                SELECT @firstname, @lastname, @address, @birthdate 
    
                INSERT INTO emailbook (email) 
                SELECT @email 
    
                FETCH next FROM newuser_cursor INTO @username, @password, @firstname, 
                @lastname, @address, @birthdate, @email 
            END 
    
            CLOSE newuser_cursor 
    
            DEALLOCATE newuser_cursor 
        END