解决 Oracle 中的“无法在查询中执行 DML”错误
Posted
技术标签:
【中文标题】解决 Oracle 中的“无法在查询中执行 DML”错误【英文标题】:Solving "Cannot perform DML inside a query" error in Oracle 【发布时间】:2012-04-01 16:51:36 【问题描述】:我已经创建了常规函数。它已成功创建。但是当我用
运行它时select reg('awlad','01968688680','545466455','12345') from dual
它给了我这个错误:
ORA-14551: cannot perform a DML operation inside a query
我该如何解决这个问题?
CREATE OR REPLACE FUNCTION reg(
name in varchar2,
cellNo in varchar2,
voterId in varchar2,
pass in varchar2
)
RETURN NUMBER
IS
succ NUMBER;
BEGIN
succ:=0;
insert into logInfo values(loginfo_seq.nextval,cellNo,pass,0);
succ:=1;
insert into passInfo values(name,cellNo,voterId);
succ:=2;
RETURN succ;
END;
【问题讨论】:
【参考方案1】:一个函数应该计算并返回一个结果,而不是改变数据库的状态。如果您想在函数中执行DML
(即,如果您想向表中插入行),则不能在SELECT
语句中调用该函数,因为SELECT
语句无法更改数据库的状态。一般来说,最好将这种东西创建为存储过程而不是存储函数。
您可以像调用存储过程一样从 PL/SQL 块调用此函数
DECLARE
l_success_code NUMBER;
BEGIN
l_success_code := reg('awlad','01968688680','545466455','12345');
END;
如果您想将其创建为过程
CREATE OR REPLACE PROCEDURE reg( name in varchar2,
cellNo in varchar2,
voterId in varchar2,
pass in varchar2,
succ out NUMBER )
AS
BEGIN
succ:=0;
insert into logInfo values(loginfo_seq.nextval,cellNo,pass,0);
insert into passInfo values(name,cellNo,voterId);
succ:=1;
END;
那么您需要通过传入OUT
参数来调用该过程
DECLARE
l_success_code NUMBER;
BEGIN
reg('awlad','01968688680','545466455','12345', l_success_code);
END;
【讨论】:
感谢洞穴。我已经尝试过了,但是当我调用该程序时,它向我显示错误:调用“REG”时参数的数量或类型错误。我的程序是:CREATE OR REPLACE PROCEDURE reg(name in varchar2, cellNo in varchar2, voterId in varchar2, pass in varchar2, succ out NUMBER) AS BEGIN succ:=0;插入 logInfo 值(loginfo_seq.nextval,cellNo,pass,0);插入 passInfo 值(名称,cellNo,voterId);成功:= 1;结束; @AwladLiton - 如果您使用OUT
参数创建过程,则需要传入第五个参数。编辑了我的答案以显示如何做到这一点。【参考方案2】:
如果您只想记录信息,则使用autonomous transaction 进行中间插入是合适的。
CREATE OR REPLACE FUNCTION reg(NAME IN VARCHAR2,
cellNo IN VARCHAR2,
voterId IN VARCHAR2,
pass IN VARCHAR2)
RETURN NUMBER IS
--
PROCEDURE do_loginfo (p_id NUMBER,
p_cellNo VARCHAR2,
p_pass VARCHAR2,
p_x NUMBER) IS
PRAGMA AUTONOMOUS_TRANSACTION
BEGIN
INSERT INTO logInfo VALUES (p_id, p_cellNo, p_pass, p_x);
COMMIT;
END do_loginfo;
PROCEDURE do_passInfo (p_name VARCHAR2,
p_cellNo VARCHAR2,
p_voterId VARCHAR2) IS
PRAGMA AUTONOMOUS_TRANSACTION
BEGIN
INSERT INTO passInfo VALUES (p_name, p_cellNo, p_voterId);
COMMIT;
END do_passInfo;
--
succ NUMBER;
BEGIN
succ := 0;
do_logInfo (loginfo_seq.NEXTVAL, cellNo, pass, 0);
succ := 1;
do_passInfo (NAME, cellNo, voterId);
succ := 2;
RETURN succ;
END;
请注意,它对调试很有用,但由于它不是事务性的,因此不应该用于记录数据(因为即使主事务回滚,插入的行也会保留)。
【讨论】:
以上是关于解决 Oracle 中的“无法在查询中执行 DML”错误的主要内容,如果未能解决你的问题,请参考以下文章