首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用户定义的函数只能具有select语句。

用户定义的函数只能具有select语句。
EN

Stack Overflow用户
提问于 2018-04-27 13:06:13
回答 2查看 1.7K关注 0票数 0

UDF和SP的主要区别之一是,UDF只能在其中包含select语句,而不能插入/更新/delete语句。有谁能解释一下背后的原因吗?以下功能:

代码语言:javascript
运行
复制
create function test(..)
...
BEGIN 
insert into EMPLOYEE('22',12000,'john');
return 0;
END

是无效的。但为什么会这样呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-04-27 14:03:10

函数中的insert语句缺少values关键字;

代码语言:javascript
运行
复制
insert into EMPLOYEE('22',12000,'john');

应该是

代码语言:javascript
运行
复制
insert into EMPLOYEE values ('22',12000,'john');

不过,最好也包括列名列表。从代码的一小部分来看,这是唯一无效的部分。您遗漏的位中可能有其他错误。(如果表中的第一列是数字列,则不应该传递字符串--它可以工作,但可以进行隐式转换,最好避免。如果这个列是一个字符串,它真的应该是吗?)

UDF只能有select语句,而不能插入/更新/删除语句。

那是不对的。可以在函数中使用DML (insert/update/delete),但只能从PL/SQL上下文调用DML(尽管在PL/SQL中,人们常说函数应该查询数据而不产生副作用,只有过程应该修改数据;但这不受语言本身的限制):

代码语言:javascript
运行
复制
create table employee (id varchar2(3), salary number, name varchar2(10));

Table EMPLOYEE created.

create function test(unused number)
return number as
BEGIN 
  insert into EMPLOYEE (id, salary, name)
  values ('22',12000,'john');
  return 0;
END;
/

Function TEST compiled


declare
  rc number;
begin
  rc := test(42);
end;
/

PL/SQL procedure successfully completed.

select * from employee;

ID      SALARY NAME      
--- ---------- ----------
22       12000 john      

但是不能从SQL上下文调用它:

代码语言:javascript
运行
复制
select test(42) from dual;

ORA-14551: cannot perform a DML operation inside a query 
ORA-06512: at "MYSCHEMA.TEST", line 4

文档列出对从SQL调用的函数的限制。将在此警告中详细说明。

因为SQL是一种声明性语言,而不是命令式(或过程性)语言,所以您无法知道一个SQL语句调用的函数将运行多少次--即使函数是用PL/SQL (一种命令式语言)编写的。

如果允许函数执行DML,那么您将无法控制执行DML的次数。例如,如果它正在进行插入,它可能尝试插入同一行两次,或者重复数据,或者违反约束。

票数 6
EN

Stack Overflow用户

发布于 2018-04-27 14:01:30

为了总结这些注释,可以在PL/函数中使用。

您不能做的是从SQL调用该函数,因为select语句也不应该将更新和删除等应用于隐藏的副作用。

首先,SQL语言保留按任何顺序以任何方式执行查询的权利,以及它决定使用的任何缓存。(它甚至可能在执行期间停止并重新启动。这取决于SQL引擎。)因此,您的函数可能会按任何顺序被调用一次或一百次,这取决于执行计划,因此结果是不可预测的。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50063080

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档