为什么在更新表时需要重新编译这个Oracle PLSQL函数?

时间:2014-11-14 02:49:37

标签: oracle function plsql

我已经为类项目的Oracle数据库编写了这个函数:

create or replace Function loginUser ( name_in IN varchar2, pass_in IN varchar2 )
Return Number
IS
   cursor c1 is
   SELECT u_id
     FROM userinfo
     WHERE username = name_in AND pass = pass_in AND lockedout='N';

  user_id_return  number;
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN 

   open c1;
   fetch c1 into user_id_return;

   if c1%notfound then
    user_id_return := 0;
    INSERT INTO LoginAttempt(username, whenattempted, attempt_status) VALUES (name_in, SYSDATE, 'N');
    commit;
   ELSE
    INSERT INTO LoginAttempt(username, whenattempted, attempt_status) VALUES (name_in, SYSDATE, 'Y');
    commit;
   END IF;

   close c1;

Return user_id_return;

EXCEPTION
WHEN OTHERS THEN
   raise_application_error(-20001,'An error was encountered - '||SQLCODE||' -ERROR- '||SQLERRM);
END;

效果很好,当你调用

时,我会在LoginAttempt的表中插入一个插入
SELECT loginUser('name','pass') FROM DUAL;

然而,问题是新的记录和对userinfo的更新没有反映在函数顶部的SELECT语句中。

每次更新userinfo表时都必须重新编译该函数。

这是为什么?这是SELECT语句的功能如何工作?编译函数时是否编译了SELECTED表?

这与PRAGME AUTONOMOUS_TRANSACTION位相关吗?

可以在github(https://github.com/tmsimont/cs3810schema/blob/master/export.sql

上找到该表的模式

1 个答案:

答案 0 :(得分:0)

因为您的函数在自治事务中执行其DML(即与调用事务的单独会话),所以它无法查看调用会话未提交的数据。在您的代码提交之前,它所做的更改对任何其他会话都不可见,包括您的函数使用的会话。

这与需要编译函数无关。编译导致它突然看到数据的原因是因为DDL总是发出提交,因此具有提交已插入数据的副作用。