繁体   English   中英

Oracle 12c SQL函数调用无法按预期运行

[英]Oracle 12c SQL Function call not working as desired

我在SQL中有一个将用户插入USERS的函数。 当我使用SELECT insert_users('user', 'email', 'hash') FROM dual; Oracle 12c应用程序中的函数时SELECT insert_users('user', 'email', 'hash') FROM dual; 它运行,但从异常返回FAIL 运行此SQL语句时,在SQL Developer中也会发生相同的事情,但是,当我直接在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块(直接从运行功能中获取)

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;

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

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

您的函数正在执行DML-即插入表中。 从PL / SQL上下文运行时可以,尽管通常认为最好还是使用过程来完成。 但是由于您的函数正在执行此操作,因此您不能在查询中调用它。

捕获和压榨错误通常被认为是一个错误 您正在做的所有事情都在隐藏有用的信息。 调用者不知道为什么函数调用失败,并且任何调查问题的人都不知道发生了什么。

更好的方法是只执行一个过程。 如果插入有效,那很好。 如果发生任何类型的错误,请传播异常,客户端或调用方将看到该错误并知道实际出了什么问题。 您不能从查询中调用该过程,但可以从匿名块中调用,也可以从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对密码进行哈希处理...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM