我已经为类项目的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)
上找到该表的模式答案 0 :(得分:0)
因为您的函数在自治事务中执行其DML(即与调用事务的单独会话),所以它无法查看调用会话未提交的数据。在您的代码提交之前,它所做的更改对任何其他会话都不可见,包括您的函数使用的会话。
这与需要编译函数无关。编译导致它突然看到数据的原因是因为DDL总是发出提交,因此具有提交已插入数据的副作用。