好奇,说我有这个Seeded函数 FND_GLOBAL.USER_ID
返回当前登录用户的User_ID,我有一个自定义包(下面)更新了一堆表(问题末尾的表dml和ddl) .
一个过程对 FND_GLOBAL.USER_ID
进行一次调用并将其分配给局部变量,另一个过程对 FND_GLOBAL.USER_ID
进行多次调用:
create or replace package call_pkg_var is
procedure call_once (p_trx_no number);
procedure call_multi (p_trx_no number);
end call_pkg_var;
/
create or replace package body call_pkg_var is
procedure call_once (p_trx_no number)
is
l_user_id number := fnd_global.user_id;
begin
update table_a
set user_id = l_user_id
where trx_no = p_trx_no;
update table_b
set user_id = l_user_id
where trx_no = p_trx_no;
update table_c
set user_id = l_user_id
where trx_no = p_trx_no;
end call_once;
procedure call_multi (p_trx_no number)
is
begin
update table_a
set user_id = FND_GLOBAL.USER_ID
where trx_no = p_trx_no;
update table_b
set user_id = FND_GLOBAL.USER_ID
where trx_no = p_trx_no;
update table_c
set user_id = FND_GLOBAL.USER_ID
where trx_no = p_trx_no;
end call_multi;
end call_pkg_var;
/
在单独的会话中,我运行下面的脚本以使用 call_pkg_var.call_once
更新表:
set timing on;
begin
for i in 1 .. 10000 loop
call_pkg_var.call_once(i);
end loop;
commit;
end;
这个使用 call_pkg_var.call_multi
:
set timing on;
begin
for i in 1 .. 10000 loop
call_pkg_var.call_multi(i);
end loop;
commit;
end;
结果:
Run# call_pkg_var.call_once
------- -----------------------
1 00:00:02.248
2 00:00:02.100
3 00:00:02.101
4 00:00:02.069
5 00:00:02.136
6 00:00:02.113
------ -------------
Average 00:00:02.128
Run# call_pkg_var.call_multi
------- -----------------------
1 00:00:02.051
2 00:00:02.047
3 00:00:02.054
4 00:00:02.071
5 00:00:02.054
6 00:00:02.051
------ -------------
Average 00:00:02.055
这是否以某种方式说多次调用函数比仅将函数分配给变量更好?如果没有,最好的方法是什么?
Table DML and DDLs
create table table_a
(
user_id number,
trx_no number
);
create table table_b
(
user_id number,
trx_no number
);
create table table_c
(
user_id number,
trx_no number
);
insert into table_a (trx_no, user_id) values (1, null);
insert into table_b (trx_no, user_id) values (1, null);
insert into table_c (trx_no, user_id) values (1, null);
2 回答
我同意brian的观点 . 总是尝试在构建函数中使用oracle来获得所需的输出 . 你可以使用sys_context来获取当前用户,我不确定你正在使用的是什么方法 . 试着避免sql和sql之间的切换上下文PL / SQL
大多数人可能不知道的是
FND_GLOBAL
是Oracle Corporation作为其Oracle电子商务套件的一部分提供的软件包 .如果您查看该软件包的源代码,您将看到
FND_GLOBAL
已在PL / SQL变量中缓存USER_ID
,即e-BS用户ID而非Oracle数据库用户ID . 所以,你的"call once"和"call multi"的工作量几乎完全相同 .我希望"call multi"仍然可以做更多的工作 - 并且如果你进行了大量的测试并且在统计上评估了结果,你就能够发现它 .
但是,如果您使用的是Oracle 12c,我不确定该版本是否删除了PL / SQL优化器只能内联调用同一程序单元中的函数的限制 . 如果启用PL / SQL警告,如果正在进行任何类型的内联,则应该收到警告 .
作为参考,这是你如何做到这一点: