使用确定性用户定义函数的虚拟列
Virtual Column using deterministic user defined function
我正在使用具有确定性用户定义函数的虚拟列 (oracle 11g),该函数将行的主键作为参数,returns 是一个简单的标量值。虚拟列更新没有任何问题,但是当我更新 table 时它会抛出错误:- ora-00054 资源繁忙并获取指定的 nowait 或超时在 oracle 中过期。我的table结构和功能,如下:-
-----------------------------------------------------------------------
id employee_name employee_dept employee_leaves (vir column)
-----------------------------------------------------------------------
2 patrick mgmt getEmpLeaves(id)
3 jack sales "
-----------------------------------------------------------------------
create or replace function getEmpLeaves(empId number)
return number
DETERMINISTIC
is
emp_leaves number;
begin
select leaves into emp_leaves from tbl_emp_leaves
where tbl_emp_leaves.id = empId;
return emp_leaves;
end ;
-------------------------------------------------------------
如何克服这个错误?
我不会去寻找这个错误的原因。
一个简短的回答是:从 table 中删除这个虚拟列,然后创建一个视图:
create view vw_employees AS
SELECT t.id, t.employee_name, t.employee_dept, x.leaves As employee_leaves
FROM tbl_employees t
JOIN tbl_emp_leaves x
ON t.id = x.id;
长答案:请看下面的简单测试用例:
create table tbl_emp_leaves as
select object_id as id, trunc(dbms_random.value(0,100)) as leaves
from all_objects;
alter table tbl_emp_leaves add primary key( id );
create or replace function getEmpLeaves(empId number)
return number
DETERMINISTIC
is
emp_leaves number;
begin
select leaves into emp_leaves from tbl_emp_leaves
where tbl_emp_leaves.id = empId;
return emp_leaves;
end ;
/
create table tbl_employees as
select object_id as id, object_name as employee_name, object_type as employee_dept
from all_objects;
alter table tbl_employees
add employee_leaves as ( getEmpLeaves(id));
create view vw_employees AS
SELECT t.id, t.employee_name, t.employee_dept, x.leaves As employee_leaves
FROM tbl_employees t
JOIN tbl_emp_leaves x
ON t.id = x.id;
现在比较两个简单查询的性能:
SQL> set timing on;
SQL> select sum(employee_leaves) from vw_employees;
SUM(EMPLOYEE_LEAVES)
--------------------
3675425
Elapsed: 00:00:00.07
SQL> select sum(employee_leaves) from tbl_employees;
SUM(EMPLOYEE_LEAVES)
--------------------
3675425
Elapsed: 00:00:03.09
3.09 秒 vs. 0.07 秒 - 您会看到基于函数的虚拟列比简单连接慢 44 倍(即:4400%)。
我在创建一个 select 另一个 table 的函数时遇到了类似的问题。
关键字DETERMINISTIC
表示函数始终 returns 给定输入参数的相同值。开发人员有责任确保这一点。
Oracle 允许这样的函数:
create or replace function getNumber(x number)
return number DETERMINISTIC is
begin
return DBMS_RANDOM.RANDOM;
end;
尽管这实际上与 确定性 函数相反。
Return 函数的值在 UPDATE tbl_emp_leaves SET leaves = ...
语句后发生变化。
所以,我不得不同意 kordirko 的回答:删除这个虚拟列并创建一个视图或使用触发器来设置列 employee_leaves
的值。
我正在使用具有确定性用户定义函数的虚拟列 (oracle 11g),该函数将行的主键作为参数,returns 是一个简单的标量值。虚拟列更新没有任何问题,但是当我更新 table 时它会抛出错误:- ora-00054 资源繁忙并获取指定的 nowait 或超时在 oracle 中过期。我的table结构和功能,如下:-
-----------------------------------------------------------------------
id employee_name employee_dept employee_leaves (vir column)
-----------------------------------------------------------------------
2 patrick mgmt getEmpLeaves(id)
3 jack sales "
-----------------------------------------------------------------------
create or replace function getEmpLeaves(empId number)
return number
DETERMINISTIC
is
emp_leaves number;
begin
select leaves into emp_leaves from tbl_emp_leaves
where tbl_emp_leaves.id = empId;
return emp_leaves;
end ;
-------------------------------------------------------------
如何克服这个错误?
我不会去寻找这个错误的原因。
一个简短的回答是:从 table 中删除这个虚拟列,然后创建一个视图:
create view vw_employees AS
SELECT t.id, t.employee_name, t.employee_dept, x.leaves As employee_leaves
FROM tbl_employees t
JOIN tbl_emp_leaves x
ON t.id = x.id;
长答案:请看下面的简单测试用例:
create table tbl_emp_leaves as
select object_id as id, trunc(dbms_random.value(0,100)) as leaves
from all_objects;
alter table tbl_emp_leaves add primary key( id );
create or replace function getEmpLeaves(empId number)
return number
DETERMINISTIC
is
emp_leaves number;
begin
select leaves into emp_leaves from tbl_emp_leaves
where tbl_emp_leaves.id = empId;
return emp_leaves;
end ;
/
create table tbl_employees as
select object_id as id, object_name as employee_name, object_type as employee_dept
from all_objects;
alter table tbl_employees
add employee_leaves as ( getEmpLeaves(id));
create view vw_employees AS
SELECT t.id, t.employee_name, t.employee_dept, x.leaves As employee_leaves
FROM tbl_employees t
JOIN tbl_emp_leaves x
ON t.id = x.id;
现在比较两个简单查询的性能:
SQL> set timing on;
SQL> select sum(employee_leaves) from vw_employees;
SUM(EMPLOYEE_LEAVES)
--------------------
3675425
Elapsed: 00:00:00.07
SQL> select sum(employee_leaves) from tbl_employees;
SUM(EMPLOYEE_LEAVES)
--------------------
3675425
Elapsed: 00:00:03.09
3.09 秒 vs. 0.07 秒 - 您会看到基于函数的虚拟列比简单连接慢 44 倍(即:4400%)。
我在创建一个 select 另一个 table 的函数时遇到了类似的问题。
关键字DETERMINISTIC
表示函数始终 returns 给定输入参数的相同值。开发人员有责任确保这一点。
Oracle 允许这样的函数:
create or replace function getNumber(x number)
return number DETERMINISTIC is
begin
return DBMS_RANDOM.RANDOM;
end;
尽管这实际上与 确定性 函数相反。
Return 函数的值在 UPDATE tbl_emp_leaves SET leaves = ...
语句后发生变化。
所以,我不得不同意 kordirko 的回答:删除这个虚拟列并创建一个视图或使用触发器来设置列 employee_leaves
的值。