Oracle 12c SQL函数调用无法正常工作

时间:2017-02-09 19:13:45

标签: sql oracle oracle-sqldeveloper oracle12c sql-function

我在SQL中有一个将用户插入USERS的函数。当我使用SELECT insert_users('user', 'email', 'hash') FROM dual;调用Oracle 12c应用程序中的函数时,它会运行,但会从异常中返回FAIL。 SQL Developer在运行此SQL语句时也会发生同样的事情,但是当我在SQL Developer中直接运行或调试该函数时,它会成功执行。所以我认为问题出在SQL语句中。那么需要改变什么才能让它发挥作用呢?

SQL函数

create or replace FUNCTION insert_users(p_user_name in varchar2, 
    p_user_email in varchar2, p_user_password in varchar2)
RETURN VARCHAR2 AS

    p_salt varchar2(20) := '';
BEGIN
    select dbms_random.string('P', 20) str
    into p_salt
    from dual;
INSERT INTO USERS(USER_ID, USER_NAME, USER_EMAIL, SALT, USER_PASSWORD)
    VALUES (seq_users.nextval, p_user_name, p_user_email, p_salt, p_user_password);
return 'SUCCESS';
EXCEPTION
    WHEN others THEN
    RETURN 'FAIL';
END;

SQL调用

SELECT insert_users('user', 'email', 'hash') FROM dual;

PL / SQL Block(直接从运行函数)

DECLARE
  P_USER_NAME VARCHAR2(200);
  P_USER_EMAIL VARCHAR2(200);
  P_USER_PASSWORD VARCHAR2(200);
  v_Return VARCHAR2(200);
BEGIN
  P_USER_NAME := 'user';
  P_USER_EMAIL := 'email';
  P_USER_PASSWORD := 'hash';

  v_Return := USER.INSERT_USERS(
    P_USER_NAME => P_USER_NAME,
    P_USER_EMAIL => P_USER_EMAIL,
    P_USER_PASSWORD => P_USER_PASSWORD
  );
  :v_Return := v_Return;
--rollback; 
END;

1 个答案:

答案 0 :(得分:3)

如果你没有挤压异常,你会看到:

  

ORA-14551:无法在查询中执行DML操作

您的功能正在执行DML - 即插入您的表格。从PL / SQL上下文运行时可以,但通常认为最好使用一个过程。但由于您的功能正在执行此操作,因此无法将其作为查询的一部分进行调用。

Catching and squashing errors is often considered a bug。你所做的就是隐藏有用的信息。调用者不知道为什么函数调用失败,任何调查问题的人都不知道发生了什么。

更好的方法是拥有一个程序。如果插入工作没问题。如果发生任何类型的错误,请让异常传播,客户端或调用者将看到它并知道实际出错的地方。您无法从查询中调用该过程,但您可以从匿名块或围绕匿名块的SQL * Plus和SQL Developer execute包装器调用它。

create or replace PROCEDURE insert_users(p_user_name in varchar2, 
    p_user_email in varchar2, p_user_password in varchar2) AS
BEGIN
    INSERT INTO USERS(USER_ID, USER_NAME, USER_EMAIL, SALT, USER_PASSWORD)
    VALUES (seq_users.nextval, p_user_name, p_user_email, dbms_random.string('P', 20), p_user_password);
END;
/

Procedure INSERT_USERS compiled

EXEC insert_users('user', 'email', 'hash');

PL/SQL procedure successfully completed.

select * from users;

   USER_ID USER_NAME            USER_EMAIL           SALT                 USER_PASSWORD                                                   
---------- -------------------- -------------------- -------------------- ----------------------------------------------------------------
         1 user                 email                Er-U1zL-v0lP%1m*Tz&t hash                                                            

你真的不需要p_salt变量,你可以将dbms_random作为插入的一部分来调用,所以我删除了它。

您可能希望在存储密码之前使用salt来密码密码...