Устранение ошибки «Не удается выполнить DML внутри запроса» в Oracle - PullRequest
4 голосов
/ 01 апреля 2012

Я создал обычную функцию. Он был успешно создан. Но когда я запускаю его с

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;

Ответы [ 2 ]

6 голосов
/ 01 апреля 2012

Функция должна вычислять и возвращать результат, а не изменять состояние базы данных.Если вы хотите сделать 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;
3 голосов
/ 02 апреля 2012

Если все, что вы хотите сделать, - это записать информацию, было бы целесообразно использовать автономную транзакцию для выполнения промежуточной вставки.

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;

Обратите внимание, что это будет полезно для целей отладки, но, поскольку оно не является транзакционным, его не следует использовать для записи данных (поскольку вставленные строки останутся даже в случае отката основной транзакции).

...