Oracle NVL和DECODE函数的漏洞
在Oracle中,即使条件不符合, NVL函数也会执行条件不符合的选项,对于DECODE函数,如果里面有自定义函数,则decode不会执行不符合条件的函数,但是如果decode里面有sequence.nextval,不管条件是否符合,sequence都会自增。
1 --创建一个函数,当被调用时打印“the functionss is executed” 2 CREATE OR REPLACE FUNCTION f_print_str 3 RETURN NUMBER 4 AS 5 BEGIN 6 7 DBMS_OUTPUT.PUT_LINE('the funcionts is executed'); 8 RETURN 1; 9 10 END f_print_str;
NVL:
比如下面的例子,即使nvl第一个参数不为空,返回第一个参数的值-11,但是函数f_print_str还是会被执行,打印"the function is eceucted"
1 SQL> set serveroutput on 2 SQL> select nvl('11',f_print_str) from dual; 3 4 NVL('11',F_PRINT_STR) 5 ---------------------------------------- 6 11 7 8 the funcionts is executed 9 10 SQL>
DECODE:
decode函数不会执行不符合条件的选项,下面的例子没有打印“the functions is exeucted”
1 SQL> set serveroutput on 2 SQL> select decode('10','10','is same',f_print_str) from dual; 3 4 DECODE('10','10','ISSAME',F_PR 5 ---------------------------------------- 6 is same 7 8 SQL>
如果decode函数里面包含sequence.nextval,则不管条件是否符合,sequence值都会变化。
1 SQL> CREATE SEQUENCE SEQ_TEST MINVALUE 1 MAXVALUE 200 START WITH 1 INCREMENT BY 1 NOCYCLE NOCACHE; 2 3 Sequence created 4 5 SQL> select seq_test.nextval from dual; 6 7 NEXTVAL 8 ---------- 9 1 10 11 SQL> select decode('10','10','is same',seq_test.nextval) from dual; --此处sequence条件不成立,但是也被执行 12 13 DECODE('10','10','ISSAME',SEQ_ 14 ---------------------------------------- 15 is same 16 17 SQL> select seq_test.currval from dual; 18 19 CURRVAL 20 ---------- 21 2 22 23 SQL>
为了解决上面的问题,可以创建一个函数用于返回sequence.nextval的值,如果条件不成立,sequence的值不会变动。
1 --创建一个函数,用于返回sequence.nextval的值 2 CREATE OR REPLACE FUNCTION F_GET_SEQ RETURN NUMBER AS 3 V_SEQ_NUM NUMBER; 4 BEGIN 5 SELECT SEQ_TEST.NEXTVAL INTO V_SEQ_NUM FROM DUAL; 6 DBMS_OUTPUT.PUT_LINE('the funcionts is executed'); 7 RETURN V_SEQ_NUM; 8 9 END F_GET_SEQ;
比如下面的例子,f_get_seq处条件不成立,函数f_get_seq不会执行,相应的里面的sequence:seq_test的值也不会有变动
1 SQL> set serveroutput on 2 SQL> select seq_test.currval from dual; 3 4 CURRVAL 5 ---------- 6 3 7 8 SQL> select decode('10','10','is same',f_get_seq) from dual; 9 10 DECODE('10','10','ISSAME',F_GE 11 ---------------------------------------- 12 is same 13 14 SQL> select seq_test.currval from dual; 15 16 CURRVAL 17 ---------- 18 3 19 20 SQL>