【Oracle】容易犯的错误和技巧集合
引言
此文记录日常开发中容易遇到的oracle编程误区和一些使用技巧,不定期更新.
1.sum(),max(),min(),avg()等函数会得到null值
declare n_num number(5):=''; begin select sum(1) into n_num from dual where 1=2 ; n_num:= n_num+2; dbms_output.put_line(n_num); end;
上面代码描述了我们日常开发的一个场景,将某个表的数据求和,然后再各种计算.正常情况是没有问题的,但是求和表没有数据的,我们就会得到一个空值,然后导致后面的一系列计算都是空值,
造成业务误差.
处理办法:加上nvl()函数处理这种异常,如下:
declare n_num number(5):=''; begin select nvl(sum(1),0) into n_num from dual where 1=2 ; n_num:= n_num+2; dbms_output.put_line(n_num); end;
2.超长字符拼接
我们一般用函数wm_concat拼接字段,但是拼接超长字符串(长度大于32767)时,就抛错了.后来找到一个自定义函数能够无压力拼接超长字符串,代码是抄下来了,但是出处网址没记下来.......函数如下:
CREATE OR REPLACE TYPE t_long_concat AUTHID CURRENT_USER AS OBJECT ( CURR_STR clob, STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT t_long_concat) RETURN NUMBER, MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT t_long_concat, P1 IN VARCHAR2) RETURN NUMBER, MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN t_long_concat, RETURNVALUE OUT clob, FLAGS IN NUMBER) RETURN NUMBER, MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT t_long_concat, SCTX2 IN t_long_concat) RETURN NUMBER ); CREATE OR REPLACE TYPE BODY t_long_concat IS STATIC FUNCTION ODCIAGGREGATEINITIALIZE(SCTX IN OUT t_long_concat) RETURN NUMBER IS BEGIN SCTX := t_long_concat(NULL) ; RETURN ODCICONST.SUCCESS; END; MEMBER FUNCTION ODCIAGGREGATEITERATE(SELF IN OUT t_long_concat, P1 IN VARCHAR2) RETURN NUMBER IS BEGIN IF(CURR_STR IS NOT NULL) THEN CURR_STR := CURR_STR || ',' || P1; ELSE CURR_STR := P1; END IF; RETURN ODCICONST.SUCCESS; END; MEMBER FUNCTION ODCIAGGREGATETERMINATE(SELF IN t_long_concat, RETURNVALUE OUT clob, FLAGS IN NUMBER) RETURN NUMBER IS BEGIN RETURNVALUE := CURR_STR ; RETURN ODCICONST.SUCCESS; END; MEMBER FUNCTION ODCIAGGREGATEMERGE(SELF IN OUT t_long_concat, SCTX2 IN t_long_concat) RETURN NUMBER IS BEGIN IF(SCTX2.CURR_STR IS NOT NULL) THEN SELF.CURR_STR := SELF.CURR_STR || ',' || SCTX2.CURR_STR ; END IF; RETURN ODCICONST.SUCCESS; END; END; CREATE OR REPLACE FUNCTION long_concat(P1 VARCHAR2) RETURN clob AGGREGATE USING t_long_concat ;
3.Group by 和 Having
通常我们在存储过程中判断表的字段中有没有重复数据,可能会用到下面的SQL
select count(*) into N_Count from T_Table t Group by t.Name having count(*)>1; if N_Count>0 then --操作 end if;
然而这种写法是有问题的.1.当没有重复数据时会引发NO_DATA_FOUND异常.2.当有多个重复组时会引发返回多行异常,正确的写法应该是这样的.
select count(*) into N_Count from ( select t.Name from T_Table t group by t.Name having count(*)>1 ) if N_Count>0 then --操作 end if;
4.行转列
有时候要将行数据转换为列.下面给出一个例子,目的是将成绩排名数据转成列显示.
select * from ( select 100 score, 1 ranknum, '一班' nam from dual union all select 99 score, 2 ranknum, '一班' nam from dual union all select 98 score, 1 ranknum, '二班' nam from dual union all select 90 score, 2 ranknum, '二班' nam from dual ) PIVOT( max(score) --要转成行的字段 for ranknum --根据哪个字段的信息进行转换 IN(1 as col1, 2 as col2, 3 as col3)--根据字段信息生成对应的列 )