这是一个展示如何做到这一点的示例。
首先,测试用例。 MD5 函数什么都不做;它只是返回 IN 参数的值。
SQL> CREATE TABLE users
2 (
3 student_id VARCHAR2 (10),
4 password VARCHAR2 (20)
5 );
Table created.
SQL> INSERT INTO users (student_id, password)
2 VALUES ('100', 'Stack');
1 row created.
SQL> CREATE OR REPLACE FUNCTION md5 (par_password IN VARCHAR2)
2 RETURN VARCHAR2
3 IS
4 BEGIN
5 RETURN par_password;
6 END;
7 /
Function created.
SQL>
您应该使用 procedure 来修改密码,而不是函数,因为您不能在函数中执行 DML(好吧,你可以,但你不应该' t. 稍后我会告诉你这样做)。
该过程返回更新的行数;如果你愿意,你可以返回getcount(这是选择行的数量)。
SQL> CREATE OR REPLACE PROCEDURE updatepassword (p_currentp IN VARCHAR2,
2 p_newpwd IN VARCHAR2,
3 p_studentid IN VARCHAR2,
4 retval OUT NUMBER)
5 IS
6 getcount INTEGER := 0;
7 BEGIN
8 SELECT COUNT (*)
9 INTO getcount
10 FROM users
11 WHERE student_id = p_studentid
12 AND password = md5 (p_currentp);
13
14 IF getcount = 1
15 THEN
16 UPDATE users
17 SET password = md5 (p_newpwd)
18 WHERE student_id = p_studentid
19 AND password = md5 (p_currentp);
20
21 retval := SQL%ROWCOUNT;
22 END IF;
23 END;
24 /
Procedure created.
SQL>
测试:将密码从“堆栈”更改为“溢出”:
SQL> SET SERVEROUTPUT ON;
SQL>
SQL> DECLARE
2 l_retval NUMBER;
3 BEGIN
4 updatepassword ('Stack',
5 'Overflow',
6 '100',
7 l_retval);
8 DBMS_OUTPUT.put_line ('retval = ' || l_retval);
9 END;
10 /
retval = 1
PL/SQL procedure successfully completed.
SQL> SELECT * FROM users;
STUDENT_ID PASSWORD
---------- --------------------
100 Overflow
SQL>
似乎还可以。
这就是你不能使用函数的原因:
SQL> DROP PROCEDURE updatepassword;
Procedure dropped.
SQL> CREATE OR REPLACE FUNCTION updatepassword (p_currentp IN VARCHAR2,
2 p_newpwd IN VARCHAR2,
3 p_studentid IN VARCHAR2)
4 RETURN NUMBER
5 IS
6 getcount INTEGER := 0;
7 BEGIN
8 SELECT COUNT (*)
9 INTO getcount
10 FROM users
11 WHERE student_id = p_studentid
12 AND password = md5 (p_currentp);
13
14 IF getcount = 1
15 THEN
16 UPDATE users
17 SET password = md5 (p_newpwd)
18 WHERE student_id = p_studentid
19 AND password = md5 (p_currentp);
20 END IF;
21
22 RETURN getcount;
23 END;
24 /
Function created.
SQL> SELECT updatepassword ('Overflow', 'Littlefoot', '100') FROM DUAL;
SELECT updatepassword ('Overflow', 'Littlefoot', '100') FROM DUAL
*
ERROR at line 1:
ORA-14551: cannot perform a DML operation inside a query
ORA-06512: at "SCOTT.UPDATEPASSWORD", line 16
SQL>
最后,一个 函数 表明您可以执行 DML(但您真的不想这样做) - 使用 pragma autonomous_transaction 指示 Oracle 在该函数中执行代码 与外部交易分开。它要求您提交(或回滚)。
SQL> CREATE OR REPLACE FUNCTION updatepassword (p_currentp IN VARCHAR2,
2 p_newpwd IN VARCHAR2,
3 p_studentid IN VARCHAR2)
4 RETURN NUMBER
5 IS
6 PRAGMA AUTONOMOUS_TRANSACTION;
7 getcount INTEGER := 0;
8 BEGIN
9 SELECT COUNT (*)
10 INTO getcount
11 FROM users
12 WHERE student_id = p_studentid
13 AND password = md5 (p_currentp);
14
15 IF getcount = 1
16 THEN
17 UPDATE users
18 SET password = md5 (p_newpwd)
19 WHERE student_id = p_studentid
20 AND password = md5 (p_currentp);
21 END IF;
22
23 COMMIT;
24
25 RETURN getcount;
26 END;
27 /
Function created.
SQL> SELECT updatepassword ('Overflow', 'Littlefoot', '100') FROM DUAL;
UPDATEPASSWORD('OVERFLOW','LITTLEFOOT','100')
---------------------------------------------
1
SQL> select * from users;
STUDENT_ID PASSWORD
---------- --------------------
100 Littlefoot
SQL>