【问题标题】:Oracle procedure with SYS_REFCURSOR as OUT parameter displays only old values使用 SYS_REFCURSOR 作为 OUT 参数的 Oracle 过程仅显示旧值
【发布时间】:2021-06-08 13:11:38
【问题描述】:

我创建了名为 APP_USERS 的下表,其中包含九列:

我想通过调用以 SYS_REFCURSOR 作为 OUT 参数的过程从单个记录中获取所有数据:代码如下所示:

create or replace PACKAGE BODY USER_LOGIN AS  
    PROCEDURE getUserToLogIn(comp_id NUMBER, user_id APP_USERS.USER_ID%TYPE, pass APP_USERS.ACC_PASSWORD%TYPE, v_IS_ADMIN IN char, 
        curs out sys_refcursor)
        IS 
        lala APP_USERS%ROWTYPE;
    BEGIN 
        OPEN curs FOR
        SELECT USER_ID,FIRST_NAME,MIDDLE_NAME,LAST_NAME,SEX,COMPANY_ID,IS_ADMIN,ACC_PASSWORD,IS_ACTIVE 
        FROM APP_USERS
        WHERE COMPANY_ID = comp_id and USER_ID = TRIM(user_id) and ACC_PASSWORD = pass and IS_ADMIN = v_IS_ADMIN;
        
        DBMS_OUTPUT.PUT_LINE(comp_id);
        DBMS_OUTPUT.PUT_LINE(user_id);
        DBMS_OUTPUT.PUT_LINE(pass);
        DBMS_OUTPUT.PUT_LINE(v_IS_ADMIN);
        DBMS_OUTPUT.PUT_LINE('--------------------------------------');
        
        LOOP
            FETCH curs INTO lala;
            exit when curs%notfound;
            DBMS_OUTPUT.PUT_LINE(lala.USER_ID);
            DBMS_OUTPUT.PUT_LINE(lala.COMPANY_ID);
            DBMS_OUTPUT.PUT_LINE(lala.ACC_PASSWORD);
            DBMS_OUTPUT.PUT_LINE(lala.IS_ADMIN);
        END LOOP;
        CLOSE curs;
    END getUserToLogIn; 
END USER_LOGIN; 

起初我通过运行一个简单的匿名块来调用一个过程,如下所示:

declare
curs sys_refcursor;
begin
USER_LOGIN.getUserToLogIn(1000,'EU1002','UCFE3M0N','N',curs);
end;

我得到了以下结果:

下次我用错误的数据再次运行匿名块,导致程序找不到它们,但结果不正确:

第一次,当我输入正确的数据时,我的程序会显示它们,但第二次尝试输入错误的数据会导致显示前一次的数据。 我的问题是为什么:

exit when curs%notfound;

这部分代码被忽略了吗?

【问题讨论】:

  • 那不完全正确。你应该在你的过程中打开 curs 并让调用者循环并关闭它。
  • 你能通过修改我的代码来解释一下吗?

标签: sql oracle plsql


【解决方案1】:

这不是使用 refcursor 的正确方法。这是您的代码中的一个简化示例:

create or replace PROCEDURE getUserToLogIn( user_id APP_USERS.USER_ID%TYPE,
         curs  in out sys_refcursor)
 IS 
   BEGIN 
       OPEN curs FOR  SELECT * FROM APP_USERS; -- where blah, blah
  end ;


    declare
           lala APP_USERS%ROWTYPE;
           my_cursor sys_refcursor;
    begin        
            getUserToLogIn('xxx', my_cursor);
        LOOP
                FETCH my_cursor INTO lala;
                exit when my_cursor%notfound;
                DBMS_OUTPUT.PUT_LINE('output= ' || lala.USER_ID);
        end loop;
        close my_cursor;
    end; 

所以标准方法是调用创建所需 SELECT 语句的过程,然后只调用 OPEN 游标参数。然后调用者取回光标,迭代思考,然后关闭它。 Heres也是教程。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-27
    相关资源
    最近更新 更多