将此游标函数替换为 while 循环函数

Replace this cursor function to a while loop function

我创建了这个存储过程,它从我创建的名为 newusers 的 table 中获取参数 username, password, firstname, lastname, DOB, email,并将它们放入具有字段的相应 table 中提及。我使用这个游标函数来完成它,但他们告诉我游标不是一个好主意,所以我如何用 while 循环函数替换它?

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 

您根本不需要游标。整个事情可以(并且应该 - sql 服务器总是不鼓励对逐行完成的数据集进行操作)作为 INSERT ... SELECT

ALTER PROCEDURE [dbo].[Savenewuser] 
AS 

BEGIN 


      INSERT INTO users 
                  (username, 
                   password) 
      SELECT username, 
             password 
      FROM newuser;

      INSERT INTO userdetails 
                  (first_name, 
                   last_name, 
                   user_address, 
                   dob) 
      SELECT firstname, 
             lastname, 
             address, 
             birthdate 
      FROM newuser;

等等

虽然不太确定您对主键做了什么..

如前所述,始终尝试将一百万条记录作为一百万条记录的单个块来处理,而不是一次拉出一条记录的游标,一百万次

只是为了这个问题,我不建议在任何情况下使用这种方法。

由于您只想使用游标来执行此操作,因此请优化您的查询。

您不需要在每个 insert 命令后打开和关闭光标,因为您将在第一个 fetch 语句中获得记录,然后您可以写入所有 insert命令一气呵成。然后 closedeallocate 光标。


    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 

正如我在您的代码中看到的那样,您正在拆分列数据并插入到相应的表中。我认为在这种情况下,您仅使用 join 即可实现。


 Insert into #users(username,password)
 Select username,password from #newuser

 Insert into #userdetails(username,firstname, lastname, address, birthdate)
 Select u.username, n.firstname, n.lastname, n.address, n.birthdate 
 from #newuser n join #users u on n.username=u.username

 Insert into #emailbook(username,email)
 Select u.username,n.email 
 from #newuser n join #users u on n.username=u.username