对于Oracle,对于数据修改的操作通过存储过程处理,而对于函数一般不进行数据修改操作。同时,函数可以通过 Select 进行调用,而存储过程则不行。
一、Oracle 行为
创建函数:
create or replace function fun01 return number as
begin
insert into t1 values(1);
return 1;
end;
create or replace function fun02 return number as
v_cnt number;
begin
select count(*) into v_cnt from t1;
return v_cnt;
end;
1、函数有修改操作,不允许select 调用
有修改操作,不允许 select 调用:
SQL> select fun01() from dual;
select fun01() from dual
*
ERROR at line 1:
ORA-14551: cannot perform a DML operation inside a query
ORA-06512: at "SYS.FUN01", line 3
没有修改操作,可以select 调用:
SQL> select fun02() from dual;
FUN02()
----------
2
有修改操作的函数,只能通过call 调用
SQL> var a number;
SQL> call fun01() into :a;
Call completed.
2、视图包含函数的情景
create or replace view v_t2 as select id, fun01() as t1_cnt from t2;
test=# select count(*) from v_t2;
count
-------
2
(1 row)
经验证,虽然 fun01 含有 insert 操作,但实际函数(fun01)是没有调用的,也就是函数内的 insert 没有执行。这个个人理解应该是个不严谨的地方。
二、PostgreSQL 行为
创建函数:
create or replace function fun01() returns number as
$$
begin
insert into t1 values(1);
return 1;
end;
$$
language plpgsql;
1、函数有修改操作,可以通过Select 调用
test=# select count(*) from t1;
count
-------
3
(1 row)
test=# select fun01();
fun01
-------
1
(1 row)
test=# select count(*) from t1;
count
-------
4
(1 row)
2、视图包含函数的情景
create or replace view v_t2 as select id, fun01() as t1_cnt from t2;
test=# select count(*) from v_t2;
count
-------
2
(1 row)
经验证,查询视图时,针对每一行,都会调用fun01 函数一次,也就是 insert 操作实际发生的。
三、性能“问题”
对于 select count(*) from v_t2 (视图),由于 oracle 并不执行函数 ,因此,性能肯定更快。而对于 postgresql,针对每条都要调用一次函数,性能上肯定更慢。