`

ORACLE中小心与NULL有关的操作

阅读更多

ORACLE中小心与NULL有关的操作

ORACLE中与NULL有关的操作

1.更新数据时注意NULL操作

(1)更新时,因为NULL导致更新后数据丢失.

创建表test_1和表test_2,两张表的测试数据如下:

SQL> select * from test_1;

 

ID1   ID2

----- -----

1     16

2     17

      21

 

SQL> SELECT * FROM TEST_2;

 

ID1   ID2

----- -----

1     26

2     27

      19

 

接下来利用表TEST_2去更新表TEST_1,关联字段为ID1,用TEST_2表ID2字段的值去更新TEST_1表ID2字段的值.

SQL> update test_1 a set id2=(select id2 from test_2 b where a.id1=b.id1);

 

3 rows updated

 

SQL> SELECT * FROM TEST_1;

 

ID1   ID2

----- -----

1     26

2     27

显然TEST_1表记录被做了更新,但却丢失了一条数据.

SQL> rollback;

 

Rollback complete

 

再利用表TEST_1和表TEST_2进行关联操作如下:

 

SQL> SELECT A.* FROM TEST_1 A,

  2  TEST_2 B

  3  WHERE A.ID1=B.ID1;

 

ID1   ID2

----- -----

1     16

2     17

从上面关联之后的结果来看,很显然所得出的结果跟我们想要的结果不一样,关联之后所得的结果数据中没有ID1为NULL的数据记录.

那么为什么以上操作会造成数据的丢失呢.要回答这个问题,首先得回答下面这个问题.

在ORACLE数据库中NULL=NULL?

对于这个问题有人回答是相等的,也有人回答是不等的,那么到底是相等的还是不相等的呢?下面在ORACLE数据库环境中做下实验.

SQL> select * from dual;

 

DUMMY

-----

 

X

SQL> select * from dual where 1=1;

 

DUMMY

-----

X

SQL> select * from dual where 1=2;

 

DUMMY

-----

 

通过上述SQL操作知道,可以用DUAL表来证明一下NULL等不等于NULL.

SQL> select * from dual where null=null;

 

DUMMY

-----

 

结果显示,NULL等于NULL是不对的.

SQL> select * from dual where null<>null;

 

DUMMY

-----

 

结果显示,NULL不等于NULL是不对的.

从上面SQL可以看出,在ORACLE中null=null和null<>null都是不对的.再看下面SQL

SQL> select * from dual where null is null;

 

DUMMY

-----

X

结果显示,NULL是可能等于NULL的.

由此可以看出,在ORACLE数据库中NULL表示的是一个未知的东西.这跟SQL Server和Sybase等其他版本的数据库是不一样的,他们认为NULL=NULL是正确的.这就可以解释为什么在做更新及关联操作时,结果表中数据丢失的原因了.

 

(2)更新时,因为NULL导致更新后数据出错.

SQL> select * from test_1;

 

ID1   ID2

----- -----

1     16

2     17

      21

3     18

SQL> select * from test_2;

 

ID1   ID2

----- -----

1     26

2     27

4     

利用表TEST_2去更新表TEST_1,关联字段为ID1,用TEST_2表ID2字段的值去更新TEST_1表ID2字段的值.

SQL> update test_1 a set id2=(select id2 from test_2 b where a.id1=b.id1);

 

4 rows updated

 

SQL> select * from test_1;

 

ID1   ID2

----- -----

1     26

2     27

3     

从上面结果可以看出,更新后数据不仅丢失了ID1为空的数据,而且使得ID1=3这条数据发生了改变.可以看出上述更新操作是不合理的,在进行更新操作时并没有考虑NULL的情况.

SQL> rollback;

 

Rollback complete

 

正确的更新操作如下:

SQL> update test_1 a set id2=(select id2 from test_2 b where a.id1=b.id1)

  2  where exists (select 1 from test_2 b where a.id1=b.id1);

 

2 rows updated

 

SQL> SELECT * FROM TEST_1;

 

ID1   ID2

----- -----

1     26

2     27

      21

3     18

 

SQL> COMMIT;

 

Commit complete

 

SQL> SELECT * FROM TEST_1;

 

ID1   ID2

----- -----

1     26

2     27

      21

3     18

 

2.索引与NULL

在ORACLE数据库中含有NULL的字段是不能走索引的,这是很多数据库开发者都知道的.那么为什么含有NULL的字段不能走索引呢.下面通过实验来说明一下原因.

<1>创建测试用的数据表TEST_3.

SQL> drop table test_3;

 

Table dropped

 

SQL> create table TEST_3

  2  (

  3    IP_ID NUMBER(4),

  4    NAMENO  NUMBER(4)

  5  );

 

Table created

 

SQL> INSERT INTO TEST_3 VALUES(1,2);

 

1 row inserted

 

SQL> INSERT INTO TEST_3 VALUES(1,NULL);

 

1 row inserted

 

SQL> INSERT INTO TEST_3 VALUES(NULL,1);

 

1 row inserted

 

SQL> INSERT INTO TEST_3 VALUES(NULL,NULL);

 

1 row inserted

 

SQL> COMMIT;

 

Commit complete

 

SQL> SELECT * FROM TEST_3;

 

IP_ID NAMENO

----- ------

    1      2

    1 

           1

 

<2>根据表test_3的IP_ID和NAMENO字段建立索引in_test_3.

SQL> create unique index in_test_3 on test_3(IP_ID,NAMENO);

 

Index created

 

SQL> analyze index in_test_3 validate structure;

 

Index analyzed

 

<3>查看索引存储的行数,很显然索引中只存储了3行数据,而实际有四行,未存储的就是都为NULL的数据.

SQL> select a.name,a.lf_rows from index_stats a;

 

NAME                              LF_ROWS

------------------------------ ----------

IN_TEST_3                               3

 

SQL> INSERT INTO TEST_3 VALUES(1,NULL);

 

INSERT INTO TEST_3 VALUES(1,NULL)

 

ORA-00001: 违反唯一约束条件 (ACCOUNT.IN_TEST_3)

 

因为建立的是唯一索引,所以再次重复插入违反了唯一约束条件. 

SQL> INSERT INTO TEST_3 VALUES(NULL,NULL);

 

1 row inserted

 

因为索引不能存储NULL,所以当再次插入为NULL的数据记录时,不受索引唯一性的约束.

SQL> COMMIT;

 

Commit complete

 

SQL> SELECT * FROM TEST_3;

 

IP_ID NAMENO

----- ------

    1      2

    1 

           1

 

<4>NULL对COUNT()、MAX()和MIN()影响

SQL> SELECT A.IP_ID,COUNT(A.IP_ID) FROM TEST_3 A GROUP BY A.IP_ID;

 

IP_ID COUNT(A.IP_ID)

----- --------------

    1              2

                   0

 

SQL> SELECT B.IP_ID,B.NAMENO,COUNT(*) FROM TEST_3 B GROUP BY B.IP_ID,B.NAMENO;

 

IP_ID NAMENO   COUNT(*)

----- ------ ----------

           1          1

                      2

    1      2          1

    1                 1

 

SQL> SELECT MIN(A.IP_ID),MAX(A.IP_ID) FROM TEST_3 A;

 

MIN(A.IP_ID) MAX(A.IP_ID)

------------ ------------

           1            1

 

3.在数据库中,NULL与空字符串存储到数据库中之后的表现形式都是一样的,即都是不可见的.那么NULL与空字符串到底有区别没有呢?在ORACLE数据库中' '是一个确定的值,而NULL则可以表示任何的一个值.

<1>创建试验数据表TEST_4.

SQL> create table TEST_4

  2  (

  3    IP_ID VARCHAR2(4),

  4    NAMENO  VARCHAR2(4)

  5  );

 

Table created

 

SQL> INSERT INTO TEST_4 VALUES('1','2');

 

1 row inserted

 

SQL> INSERT INTO TEST_4 VALUES('1',' ');

 

1 row inserted

 

SQL> INSERT INTO TEST_4 VALUES(' ','1');

 

1 row inserted

 

SQL> INSERT INTO TEST_4 VALUES(' ',' ');

 

1 row inserted

 

SQL> COMMIT;

 

Commit complete

 

<2>创建索引及查看索引存储情况,跟上面为NULL进行对比.

SQL> CREATE UNIQUE INDEX IN_TEST_4 ON TEST_4(IP_ID,NAMENO);

 

Index created

 

SQL> ANALYZE INDEX IN_TEST_4 VALIDATE STRUCTURE;

 

Index analyzed

 

SQL> SELECT B.name,B.lf_rows FROM INDEX_STATS B;

 

NAME                              LF_ROWS

------------------------------ ----------

IN_TEST_4                               4

 

在ORACLE数据库中空字符串是可以存储到索引中的,显然这与NULL是不同的.

SQL> INSERT INTO TEST_4 VALUES(' ',' ');

 

INSERT INTO TEST_4 VALUES(' ',' ')

 

ORA-00001: 违反唯一约束条件 (ACCOUNT.IN_TEST_4)

 

因为在数据库中' '被认为是一个确定的值,可以存储在索引中,索引当再次重复插入时,提示违反了唯一约束条件.

SQL> SELECT * FROM TEST_4;

 

IP_ID NAMENO

----- ------

1     2

1     

      1

 

SQL> SELECT MAX(A.IP_ID),MIN(A.IP_ID) FROM TEST_4 A;

 

MAX(A.IP_ID) MIN(A.IP_ID)

------------ ------------

1            

 

与NULL相比,空字符串在数据库中是可以被MIN()与MAX()统计的,而且空字符串比不是空字符串的值要少.

SQL> SELECT A.IP_ID,COUNT(DISTINCT A.IP_ID) FROM TEST_4 A GROUP BY A.IP_ID;

 

IP_ID COUNT(DISTINCTA.IP_ID)

----- ----------------------

                           1

1                          1

与NULL相比,空字符串是可以被COUNT()统计的.

SQL> SELECT A.IP_ID,A.NAMENO,COUNT(*) FROM TEST_4 A GROUP BY A.IP_ID,A.NAMENO;

 

IP_ID NAMENO   COUNT(*)

----- ------ ----------

      1               1

1     2               1

1                     1

                      1

在统计数据表中的记录条数时,NULL跟NULL被认为是不一样的,但却属于同一类型.而空字符串则不同,空字符串被认为不是同一类型的.为形成对比做如下调整.

SQL> select * from test_4 t;

 

IP_ID NAMENO

----- ------

1     2

1     

 

 

SQL> select a.ip_id,a.nameno,count(*)  from test_4 a group by a.ip_id,a.nameno; 

 

IP_ID NAMENO   COUNT(*)

----- ------ ----------

                      1

1     2               1

1                     1

                      1

显然,空字符串在被统计时,被认为是不一样的.

 

  从上面的实验可以看出,在数据库中,不仅要小心与NULL有关的操作,而且还要做到能对NULL和空字符串进行有效的区分.这样能避免某些错误的发生.

分享到:
评论

相关推荐

    sql中null值对count的影响

    因此,在处理`NULL`值时需要格外小心,特别是在执行聚合操作时。 #### COUNT函数与NULL值 `COUNT`函数用于统计表中特定列的行数。根据其参数的不同,`COUNT`函数的行为也会有所不同: - `COUNT(*)`: 统计所有行的...

    Oracle恢复误删除数据,解除锁定的等SQL语句

    在日常操作中,有时可能会发生误操作,如误删除数据或锁定问题,本篇文章将详细讲解如何在Oracle中恢复误删除数据以及解锁相关操作。 1. **恢复误删除数据** 当你不小心删除了数据库表中的数据时,Oracle提供了一...

    Oracle sequence 重置(失效恢复)

    2. **误操作:** 如果不小心删除了Sequence,或者手动修改了Sequence的当前值,也可能导致Sequence失效。 #### 三、Sequence重置方法 下面将详细介绍如何通过SQL脚本来重置Sequence,使其恢复正常功能。 ### SQL...

    oracle基础学习资料

    在Oracle数据库管理和维护过程中,经常需要使用到各种Shell脚本来自动化一些任务或者进行批处理操作,因此确保这些脚本具有执行权限是非常重要的。 #### 二、Oracle数据库的时间类型 - **Timestamp**: Oracle...

    Oracle第9章模式对象.pptx

    Oracle第9章模式对象 Oracle第9章模式对象是Oracle数据库中的一种逻辑结构,用于组织和管理数据库对象。...创建表需要规划和设计,修改表需要权限和安全控制,删除表需要小心操作以免引起数据丢失。

    Oracle公司内部数据库培训资料.pdf

    在处理空值(NULL)时要特别小心。空值表示数据无效或未知,它不同于空字符串或零。在涉及空值的数学运算中,结果也会是空值。例如,`SELECT last_name, 12*salary*commission_pct FROM employees;` 如果commission_...

    深入浅析mybatis oracle BLOB类型字段保存与读取

    总结起来,MyBatis与Oracle结合处理BLOB字段时,关键步骤包括:正确设置数据库表结构,创建相应的Java实体类,以及编写MyBatis映射文件来定义SQL查询和操作。理解这些概念和操作,能帮助你在实际开发中更有效地管理...

    oracle恢复工具-FY_Recover_Data

    步骤1:先把Fy_Recover_Data包拷贝到oracle相关目录下 步骤2:在scott用户下创建test_emp表: SQL&gt; conn scott/tiger; Connected. SQL&gt; select * from tab; TNAME ? ? ? TABTYPE CLUSTERID --------------...

    SQL优化 '%5400%' LIKE操作符

    - **使用 `IS NULL` 和 `IS NOT NULL`**:相比于 `column IS NULL` 和 `column IS NOT NULL`,`column = NULL` 和 `column &lt;&gt; NULL` 的写法是错误的,因为`NULL`值无法通过等于或不等于来判断。 - **合理使用 `&gt;` ...

    SQL开发和应用优化分享

    2. NULL值的理解和处理:在Oracle数据库中,NULL表示的是未知值。对于包含NULL的列进行聚合运算(如SUM、COUNT、AVG等)时,空值会被自动忽略。同时在排序时,空值默认会置于结果集的最后。 3. 使用BETWEEN和LIKE...

    DB2学习记录

    ### DB2学习记录 #### 一、并发机制与隔离级别 ...通过以上对比分析可以看出,尽管DB2与Oracle在很多方面都有所不同,但从Oracle迁移到DB2的过程中仍然有很多可用的工具和技术可以利用,以确保迁移项目的顺利进行。

    数据库培训-高效率sql语句基础.pptx

    3. 小心使用带有通配符的LIKE操作。除非必要,否则应尽量避免在搜索模式的开始处使用通配符,因为这会导致全表扫描。 总的来说,理解Oracle的优化器工作原理和编写高效SQL语句是提升数据库性能的关键。通过优化SQL...

    数据库操作

    运维工作中,为了确保系统的稳定性和安全性,常常需要借助各种监视工具来进行实时监控与故障排查。以下是一些常用的监控工具: 1. **Cacti**: 图形化网络流量监控工具,能够通过Web界面展示网络设备的带宽使用情况...

    PLSQL最佳实践

    9. NULL值处理:在PL/SQL中,NULL值的处理需要特别小心。必须了解NULL作为判断条件的特殊性,以及如何正确使用绑定变量。 10. 性能优化:性能优化是PL/SQL编程中不可避免的话题。合理使用PL/SQL Profiler等工具来...

    语言基础DMLPPT课件.pptx

    未指定`WHERE`时,所有行都会被更新,因此在实际操作中要格外小心。 总的来说,这个课件覆盖了数据库设计的基本概念,以及在Oracle环境中使用DML操作数据的关键技能,是学习数据库管理的宝贵资源。理解和掌握这些...

    sql优化心得

    在当前项目中,我们遇到了一个棘手的问题:需要对多个包含超过千万条记录的大表进行复杂的计算、连接(JOIN)以及其他高级查询操作。为了提高系统的响应速度和资源利用率,对SQL语句进行优化变得尤为重要。在此过程...

    Orcal 数据库触发器文件

    Oracle数据库触发器是数据库管理系统中的一种重要特性,它允许开发者在特定的数据操作(如INSERT、UPDATE、DELETE)之前或之后执行自定义的SQL代码或PL/SQL块。这些代码可以用来实现业务规则、数据验证、审计跟踪等...

    处理百万级以上的数据查询提高效率的办法

    如果数据表中存在聚簇索引,则数据行的物理顺序与索引键的顺序一致。因此,在选择聚簇索引时要特别注意,确保其能有效支持常见的查询模式。 #### 15. 合理使用 `VARCHAR` 和 `CHAR` 在需要存储较短文本的地方,...

    DB2手册pdf

    尽管文档中提到CURSOR不能定义为WITH UR,但在实际操作中,DB2允许使用`WITH UR`关键字与CURSOR结合。 #### CURSOR ORDER BY 以后不能FOR UPDATE DB2中确实存在这样的限制:带有`ORDER BY`子句的CURSOR不能使用`FOR...

Global site tag (gtag.js) - Google Analytics