Oracle数据库中对null值的排序及mull与空字符串的区别

order by排序之null值处理方法
在对业务数据排序时候,发现有些字段的记录是null值,这时排序便出现了有违我们使用习惯的数据大小顺序问题。在Oracle中规定,在Order by排序时缺省认为null是最大值,所以如果是ASC升序则被排在最后,而DESC降序则排在最前。所以,为何分析数据的直观性方便性,我们需要对null的记录值进行相应处理。
这是四种oracle排序中NULL值处理的方法:
1、使用nvl函数
语法:Nvl(expr1, expr2)
    若EXPR1是NULL,則返回EXPR2,否則返回EXPR1.

  SELECT NAME,NVL(TO_CHAR(COMM),'NOT APPLICATION') FROM TABLE1;

nvl函数可以在输入参数为空时转换为一特定值,如
nvl(person_name,“未知”)表示若person_name字段值为空时返回“未知”,如不为空则返回person_name的字段值。
通过这个函数可以定制null的排序位置。
2、使用decode函数
 
decode函数比nvl函数更强大,同样它也可以将输入参数为空时转换为一特定值,如
decode(person_name,null,“未知”, person_name)表示当person_name为空时返回“未知”,如不为空则返回person_name的字段值。
通过此函数也可以定制null的排序位置。

3、使用nulls first 或者nulls last 语法,最简单常用的方法。

Nulls first和nulls last是Oracle Order by支持的语法

(1)若Order by 中指定了表达式Nulls first则表示null值的记录将排在最前(不管是asc 还是 desc)

(2)若Order by 中指定了表达式Nulls last则表示null值的记录将排在最后 (不管是asc 还是 desc)

使用方法举例如下:
将nulls始终放在最前:

select * from tbl order by field nulls first

将nulls始终放在最后:

select * from tbl order by field desc nulls last

4、使用case 语法
 
Case语法是Oracle 9i后开始支持的,是一个比较灵活的语法,同样在排序中也可以应用
如:

select *
 from students
 order by (case person_name
      when null then
       '未知'
      else
       person_name
     end)

表示在person_name字段值为空时返回'未知',如果不为空则返回person_name
通过case语法同样可以定制null的排序位置。
 
项目实例:

  !defined('PATH_ADMIN') && exit('Forbidden');
class mod_gcdownload
{
  public static function get_gcdownload_datalist($start = 0,$rowsperpage = PAGE_ROWS, $datestart = '',$dateend = '',$ver = '',$coopid = '',$subcoopid = '',$sortfield = '', $sorttype = '', $pid = 123456789, $plat = 'abcdefg'){
    $sql = '';
    $condition = empty($datestart) ? " WHERE 1=1 " : " WHERE t.statistics_date >= '$datestart' AND t.statistics_date <= '$dateend'";
    if($ver)
    {
      $condition .= " AND t.edition='$ver'";
    }
    if($coopid)
    {
      $condition .= " AND t.suco_coopid=$coopid";
    }
    if($subcoopid)
    {
      $condition .= " AND t.suco_subcoopid=$subcoopid";
    }
    if($sortfield && $sorttype){
      $condition .= " ORDER BY t.{$sortfield} {$sorttype} NULLS LAST";
    }elseif($sortfield){
      $condition .= " ORDER BY t.{$sortfield} desc NULLS LAST";
    }else{
      $condition .= " ORDER BY t.statistics_date desc NULLS LAST";
    }
    $finish = $start + $rowsperpage;
    $joinsqlcollection = "(SELECT tc.coop_name, tsc.suco_name, tsc.suco_coopid,tsc.suco_subcoopid, s.edition, s.new_user, d.one_user, d.three_user, d.seven_user, s.statistics_date FROM (((pdt_stat_newuser_{$pid}_{$plat} s LEFT JOIN pdt_days_dl_remain_{$pid}_{$plat} d ON s.statistics_date=d.new_date AND s.subcoopid=d.subcoopid AND s.edition=d.edition )LEFT JOIN tbl_subcooperator@JTUSER1.NET@JTINFO tsc ON s.subcoopid=tsc.suco_subcoopid) LEFT JOIN tbl_cooperator@JTUSER1.NET@JTINFO tc ON tsc.suco_coopid=tc.coop_id))";
    $sql = "SELECT * FROM (SELECT tb_A.*, ROWNUM AS rn FROM (SELECT t.* FROM $joinsqlcollection t {$condition} ) tb_A WHERE ROWNUM <= {$finish} ) tb_B WHERE tb_B.rn>{$start} ";
    $countsql = "SELECT COUNT(*) AS totalrows, SUM(t.new_user) AS totalnewusr,SUM(t.one_user) AS totaloneusr,SUM(t.three_user) AS totalthreeusr,SUM(t.seven_user) AS totalsevenusr FROM $joinsqlcollection t {$condition} ";
    $db = oralceinit(1);
    $stidquery = $db->query($sql,false);
    $output = array();
    while($row = $db->FetchArray($stidquery, $skip = 0, $maxrows = -1))
    {
      $output['data'][] = array_change_key_case($row,CASE_LOWER);
    }
    $count_stidquery = $db->query($countsql,false);
    $row = $db->FetchArray($count_stidquery, $skip = 0, $maxrows = -1);
    $output['total']= array_change_key_case($row,CASE_LOWER);
    //echo "<br />".($sql)."<br />";
    return $output;  

  } 

}

Null与空字符串' '的区别
含义解释:
问:什么是NULL?
答:在我们不知道具体有什么数据的时候,也即未知,可以用NULL,我们称它为空,ORACLE中,含有空值的表列长度为零。
ORACLE允许任何一种数据类型的字段为空,除了以下两种情况:
1、主键字段(primary key),
2、定义时已经加了NOT NULL限制条件的字段
说明:
1、等价于没有任何值、是未知数。
2、NULL与0、空字符串、空格都不同。
3、对空值做加、减、乘、除等运算操作,结果仍为空。
4、NULL的处理使用NVL函数。
5、比较时使用关键字用“is null”和“is not null”。
6、空值不能被索引,所以查询时有些符合条件的数据可能查不出来,count(*)中,用nvl(列名,0)处理后再查。
7、排序时比其他数据都大(索引默认是降序排列,小→大),所以NULL值总是排在最后。
使用方法:

SQL> select 1 from dual where null=null;

没有查到记录

SQL> select 1 from dual where null='';

没有查到记录

SQL> select 1 from dual where ''='';

没有查到记录

SQL> select 1 from dual where null is null;
1
---------
1 

SQL> select 1 from dual where nvl(null,0)=nvl(null,0); 

1
---------
1

对空值做加、减、乘、除等运算操作,结果仍为空。

SQL> select 1+null from dual;
SQL> select 1-null from dual;
SQL> select 1*null from dual;
SQL> select 1/null from dual;

查询到一个记录.
注:这个记录就是SQL语句中的那个null
设置某些列为空值

update table1 set 列1=NULL where 列1 is not null;

现有一个商品销售表sale,表结构为:

month    char(6)      --月份
sell    number(10,2)   --月销售金额
create table sale (month char(6),sell number);
insert into sale values('200001',1000);
insert into sale values('200002',1100);
insert into sale values('200003',1200);
insert into sale values('200004',1300);
insert into sale values('200005',1400);
insert into sale values('200006',1500);
insert into sale values('200007',1600);
insert into sale values('200101',1100);
insert into sale values('200202',1200);
insert into sale values('200301',1300);
insert into sale values('200008',1000);
insert into sale(month) values('200009');(注意:这条记录的sell值为空)
commit;

共输入12条记录

SQL> select * from sale where sell like '%';
MONTH SELL
------ ---------
200001 1000
200002 1100
200003 1200
200004 1300
200005 1400
200006 1500
200007 1600
200101 1100
200202 1200
200301 1300
200008 1000

查询到11记录.
结果说明:
查询结果说明此SQL语句查询不出列值为NULL的字段
此时需对字段为NULL的情况另外处理。

SQL> select * from sale where sell like '%' or sell is null;
SQL> select * from sale where nvl(sell,0) like '%';
MONTH SELL
------ ---------
200001 1000
200002 1100
200003 1200
200004 1300
200005 1400
200006 1500
200007 1600
200101 1100
200202 1200
200301 1300
200008 1000
200009

查询到12记录.
Oracle的空值就是这么的用法,我们最好熟悉它的约定,以防查出的结果不正确。

但对于char 和varchar2类型的数据库字段中的null和空字符串是否有区别呢?
作一个测试:

create table test (a char(5),b char(5));
SQL> insert into test(a,b) values('1','1');
SQL> insert into test(a,b) values('2','2');
SQL> insert into test(a,b) values('3','');--按照上面的解释,b字段有值的
SQL> insert into test(a) values('4');
SQL> select * from test;
A B
---------- ----------
1 1
2 2
3
4
SQL> select * from test where b='';

----按照上面的解释,应该有一条记录,但实际上没有记录
未选定行

SQL> select * from test where b is null; 

----按照上面的解释,应该有一跳记录,但实际上有两条记录。

A B
---------- ----------
3
4
SQL>update table test set b='' where a='2';
SQL> select * from test where b='';

未选定行

SQL> select * from test where b is null;
A B
---------- ----------
2
3
4

测试结果说明,对char和varchar2字段来说,''就是null;但对于where 条件后的'' 不是null。
对于缺省值,也是一样的!

(0)

相关推荐

  • Oracle导dmp出现文件ORA-12154: TNS: 无法解析指定的连接标识符问题的解决方案

    其实TNS无法解析是Oracle操作里经常遇到的问题,原因有二: (1)Oracle服务器没有装好(一般不建议重装,因为Oracle卸载不完全是没法重装的) (2)TNS没有配置 现在本文给出解决方案: 现在先测试一下tns是否可以ping,成功的界面大致如下 (1)在oracle安装路径的tns配置文件里添加如下代码 # tnsnames.ora Network Configuration File: d:\Oracle\product\10.2.0\client_1\NETWORK\ADMI

  • Oracle中转义字符的详细介绍

    最近工作中遇到一个需求,需要更新Oracle数据库中所有表的一个字段"flag"为"I",语句为: update table_name set flag = 'I' "I"作为字符串,所以语句中I需要加上单引号. 由于数据库中有多张表,我不想一条一条的语句写,希望能够通过sql语句直接生成所有的语句,所以写了如下sql: select 'update ' || table_name || ' set flag = 'I'' || ';' from

  • Oracle截取字符串去掉字段末尾指定长度的字符

    lengthb(string)计算string所占的字节长度:返回字符串的长度,单位是字节 length(string)计算string所占的字符长度:返回字符串的长度,单位是字符 eg: //去掉该字段后面15位字符串 select t.depre_name, substr(t.depre_name, 0, (length(t.depre_name) - 16)) from table t where t.del_flag = '0' [备注]一个汉字在Oracle数据库里占多少字节跟数据库的

  • Oracle Translate 统计字符出现的次数示例代码

    特殊用法:统计字符串中 E 出现的次数: SELECT LENGTHB(TRANSLATE('ABCDEFGEFGDBE','E'||'ABCDEFGEFGDBE','E')) FROM DUAL; 等同于: SELECT LENGTHB('ABCDEFGEFGDBE')-LENGTHB(REPLACE('ABCDEFGEFGDBE','E','')) FROM DUAL; Translate 的用法 一.语法: TRANSLATE(string,from_str,to_str) 二.目的 返回

  • Oracle连接出现ora-12154无法解析指定的连接标识符

    配置好rac后,两个节点用tnsping都可以ping通,但用sqlplus连接都出现以下错误,不知道哪里出了问题 [oracle@rac2 admin]$ lsnrctl status LSNRCTL for Linux: Version 9.2.0.4.0 - Production on 04-MAR-2008 08:32:26 Copyright (c) 1991, 2002, Oracle Corporation.  All rights reserved. Connecting to

  • oracle中通配符和运算符的使用方法介绍

    用于where比较条件的有: 等于:=.<.<=.>.>=.<> 包含:in.not in exists.not exists 范围:between...and.not between....and 匹配测试:like.not like Null测试:is null.is not null 布尔链接:and.or.not 通配符: 在where子句中,通配符可与like条件一起使用.在Oracle中: %(百分号): 用来表示任意数量的字符,或者可能根本没有字符. _(

  • Oracle数据库中对null值的排序及mull与空字符串的区别

    order by排序之null值处理方法 在对业务数据排序时候,发现有些字段的记录是null值,这时排序便出现了有违我们使用习惯的数据大小顺序问题.在Oracle中规定,在Order by排序时缺省认为null是最大值,所以如果是ASC升序则被排在最后,而DESC降序则排在最前.所以,为何分析数据的直观性方便性,我们需要对null的记录值进行相应处理. 这是四种oracle排序中NULL值处理的方法: 1.使用nvl函数 语法:Nvl(expr1, expr2)     若EXPR1是NULL,

  • MySQL中对于NULL值的理解和使用教程

    NULL值的概念是造成SQL的新手的混淆的普遍原因,他们经常认为NULL是和一个空字符串''的一样的东西.不是这样的!例如,下列语句是完全不同的: mysql> INSERT INTO my_table (phone) VALUES (NULL); mysql> INSERT INTO my_table (phone) VALUES (""); 两个语句把值插入到phone列,但是第一个插入一个NULL值而第二个插入一个空字符串.第一个的含义可以认为是"电话号码不

  • Oracle数据库中SQL开窗函数的使用

    开窗函数:在开窗函数出现之前存在着很多用 SQL 语句很难解决的问题,很多都要通过复杂的相关子查询或者存储过程来完成.为了解决这些问题,在 2003 年 ISO SQL 标准加入了开窗函数,开窗函数的使用使得这些经典的难题可以被轻松的解决.目前在 MSSQLServer.Oracle.DB2 等主流数据库中都提供了对开窗函数的支持,不过非常遗憾的是 MYSQL 暂时还未对开窗函数给予支持. 开窗函数简介:与聚合函数一样,开窗函数也是对行集组进行聚合计算,但是它不像普通聚合函数那样每组只返回一个值

  • oracle数据库中sql%notfound的用法详解

    SQL%NOTFOUND 是一个布尔值.与最近的sql语句(update,insert,delete,select)发生交互,当最近的一条sql语句没有涉及任何行的时候,则返回true.否则返回false.这样的语句在实际应用中,是非常有用的.例如要update一行数据时,如果没有找到,就可以作相应操作.如: begin update table_name set salary = 10000 where emp_id = 10; if sql%notfound then insert into

  • 在 SQL 语句中处理 NULL 值的方法

    在日常使用数据库时,你在意过NULL值么? 其实,NULL值在数据库中是一个很特殊且有趣的存在,下面我们一起来看看吧: 在查询数据库时,如果你想知道一个列(例如:用户注册年限 USER_AGE)是否为 NULL,SQL 查询语句该怎么写呢? 是这样: SELECT * FROM TABLE WHERE USER_AGE = NULL 还是这样? SELECT * FROM TABLE WHERE USER_AGE IS NULL 当然,正确的写法应该是第二种(WHERE USER_AGE IS

  • Oracle数据库中通用的函数实例详解

    目录 一. Scott用户下的表结构 1.如果自己没有Scoot表就可以自己创建一个 二.单行函数 1.字符函数 2.数值函数 三.多行函数(聚合函数) 1.统计记录数 2.最小值查询 min() 3.最大值查询 max() 4.平均值查询 avg() 5.求和函数 四.分组统计 总结 一. Scott用户下的表结构 SCOTT.是在Oracle数据库中,一个示例用户的名称.其作用是为初学者提供一些简单的应用示例,不过其默认是锁定状态,在安装时,根据用户需要,在“数据库配置助手”界面完成后,弹出

  • Oracle数据库中SQL语句的优化技巧

    在SQL语句优化过程中,我们经常会用到hint,现总结一下在SQL优化过程中常见Oracle HINT的用法: 1. /*+ALL_ROWS*/ 表明对语句块选择基于开销的优化方法,并获得最佳吞吐量,使资源消耗最小化. 例如: SELECT /*+ALL+_ROWS*/ EMP_NO,EMP_NAM,DAT_IN FROM BSEMPMS WHERE EMP_NO='SCOTT'; 2. /*+FIRST_ROWS*/ 表明对语句块选择基于开销的优化方法,并获得最佳响应时间,使资源消耗最小化.

  • ORACLE数据库中怎么求除数字、字母之外的非中文字符的正则表达式

    最近做项目,有这样一需求:ORACLE数据库中求除数字.字母之外的非中文字符的正则表达式 如有如下字段,需将其中除字母.数字.汉字外的其他所有字符替换为空 'asdfsad ,,:)()!@123234#$%^&*(我w 是e ? 中国人../\[]::''""一人' 最终得到值:asdfsad123234我是中国人一人 select FN_REG_REPLACEOTHER('asdfsad ,,:)()!@#$%^&*(我是?中国人../\[]::''"&q

  • Oracle数据库中 call 和 exec的区别

    今天发现了一个小东西,觉得很有意思,查找了一些资料,跟大家分享一下: 在sqlplus中: 在第三方提供的工具(如:plsqldev) 总结: exec是sqlplus的命令,只能在sqlplus中使用. call是sql命令,任何工具都可以使用,call必须有括号,即例没有参数 call必须有括号,即例没有参数 idle> connect /as sysdba 已连接. sys@PO10> sys@PO10> create procedure p_test is 2 begin 3 n

  • .net实现oracle数据库中获取新插入数据的id的方法

    在sql sever中实现插入数据的自动增长是很容易的,但是在oracle数据库中实现这一操作不是很容易,同时要想在.net中实现获取新插入数据的id,而且不会出现读错的情况,就更显得困难了,为了解决在oracle数据中插入的数据能够自增id,同时获取新数据的id,并避免因并发操作而出现的id读错的问题. 数据表结构为test(id,name) 首先,解决数据id自增问题 创建一个序列sequence(sequence详解可从网上搜一下,这里不赘述) create sequence SEQ_te

随机推荐