Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2895845
  • 博文数量: 599
  • 博客积分: 16398
  • 博客等级: 上将
  • 技术积分: 6875
  • 用 户 组: 普通用户
  • 注册时间: 2009-11-30 12:04
个人简介

WINDOWS下的程序员出身,偶尔也写一些linux平台下小程序, 后转行数据库行业,专注于ORACLE和DB2的运维和优化。 同时也是ios移动开发者。欢迎志同道合的朋友一起研究技术。 数据库技术交流群:58308065,23618606

文章分类

全部博文(599)

文章存档

2014年(12)

2013年(56)

2012年(199)

2011年(105)

2010年(128)

2009年(99)

分类: Oracle

2013-02-05 13:56:15

今天同事遇到下面一个问题:

order by decode(column_id,1,null,2,null,3,null,column_id);
有个问题,就是当列数大于10列时,column_id 的顺序成10,11,12,13,4,5,6,7,8,9了


这个排序的主要目的是让前3列排在后面,这3列的顺序无所谓。


对于小于10列的表是没问题的:


SQL> create table t(c1 number,c2 number,c3 number,c4 number,c5 number);

表已创建。

SQL> col column_name format a20
SQL> select column_name,column_id
  2  from  user_tab_columns
  3  where table_name='T'
  4  order by decode(column_id,1,null,2,null,3,null,column_id);


COLUMN_NAME           COLUMN_ID
-------------------- ----------
C4                            4
C5                            5
C2                            2
C1                            1
C3                            3

但是当表的列数大于10的时候就会混乱了。


SQL> select column_name,column_id, decode(column_id,1,null,2,null,3,null,column_id) sortcolumn
  2  from  user_tab_columns
  3  where table_name='T'
  4  order by decode(column_id,1,null,2,null,3,null,column_id)
  5  /


COLUMN_NAME           COLUMN_ID SORTCOLUMN
-------------------- ---------- --------------------
C10                          10 10
C11                          11 11
C12                          12 12
C4                            4 4
C5                            5 5
C6                            6 6
C7                            7 7
C8                            8 8
C9                            9 9
C3                            3
C2                            2
C1                            1


已选择12行。


显然ORACLE把SORTCOLUMN列作为为字符类型排序了。

加个TO_NUMBER即可解决这个问题。


SQL> select column_name,column_id, decode(column_id,1,null,2,null,3,null,column_id) sortcolumn
  2  from  user_tab_columns
  3  where table_name='T'

  4  order by to_number(decode(column_id,1,null,2,null,3,null,column_id));


COLUMN_NAME           COLUMN_ID SORTCOLUMN
-------------------- ---------- --------------------
C4                            4 4
C5                            5 5
C6                            6 6
C7                            7 7
C8                            8 8
C9                            9 9
C10                          10 10
C11                          11 11
C12                          12 12
C1                            1
C3                            3
C2                            2


已选择12行。

但是为什么会导致这个问题,DECODE函数为何返回了字符类型。


这个问题yangtingkun大师专门写个几篇文章介绍。
有兴趣的可以找找看看。


在这里我借花献佛简单稍微说一下:
对于NULL 类型,ORACLE的默认返回类型是VARCHAR。
对于DECODE函数 ORACLE返回的类型依赖于第一个值。

如下所示:


SQL> CREATE TABLE A AS SELECT DECODE(DUMMY,'X',1,'Y','2',DUMMY) C1, <---由于第一个返回的值1是整数类型,因此整个表达式返回整数类型
  2  DECODE(DUMMY,'X','1','Y',2,DUMMY) C2 , <---由于第一个返回的值'1'是字符类型,因此整个表达式返回CHAR类型
  3  DECODE(DUMMY,'X',NULL,'Y','HUATENG',DUMMY) C3 FROM DUAL; <---由于第一个返回的值是NULL,因此整个表达式返回CHAR类型

表已创建。

SQL> DESC A
 名称                                      是否为空? 类型
 ----------------------------------------- -------- ----------------------------
 C1                                                 NUMBER
 C2                                                 VARCHAR2(1)
 C3                                                 VARCHAR2(7)
 
也正是因为DECODE函数的这种依赖于第一次的值类型作为返回类型,对于其他返回的值如果和第一个类型不匹配
,可能会让你遇到很蛋疼的问题:

SQL> DESC A;
 名称                                      是否为空? 类型
 ----------------------------------------- -------- ----------------------------
 C1                                                 NUMBER
 C2                                                 VARCHAR2(1)
 C3                                                 VARCHAR2(7)
 
SQL> INSERT INTO A VALUES(2,2,2);

已创建 1 行。

SQL> SELECT * FROM A;

        C1 C2 C3
---------- -- --------------
         1 1
         2 2  2


SQL> SELECT DECODE(C1,1,1,2,'E',C1) FROM A;
ERROR:
ORA-01722: 无效数字

未选定行

SQL> SELECT DECODE(C1,1,1,2,'E',C1) FROM A WHERE C1=1;

DECODE(C1,1,1,2,'E',C1)
-----------------------
                      1

SQL> SELECT DECODE(C1,1,1,2,'E',C1) FROM A WHERE C1=2;
SELECT DECODE(C1,1,1,2,'E',C1) FROM A WHERE C1=2
                       *
第 1 行出现错误:
ORA-01722: 无效数字


上面的问题主要是字符'E'无法转为整数类型导致的。
阅读(4041) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~