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和空字符串进行有效的区分.这样能避免某些错误的发生.
相关推荐
因此,在处理`NULL`值时需要格外小心,特别是在执行聚合操作时。 #### COUNT函数与NULL值 `COUNT`函数用于统计表中特定列的行数。根据其参数的不同,`COUNT`函数的行为也会有所不同: - `COUNT(*)`: 统计所有行的...
在日常操作中,有时可能会发生误操作,如误删除数据或锁定问题,本篇文章将详细讲解如何在Oracle中恢复误删除数据以及解锁相关操作。 1. **恢复误删除数据** 当你不小心删除了数据库表中的数据时,Oracle提供了一...
2. **误操作:** 如果不小心删除了Sequence,或者手动修改了Sequence的当前值,也可能导致Sequence失效。 #### 三、Sequence重置方法 下面将详细介绍如何通过SQL脚本来重置Sequence,使其恢复正常功能。 ### SQL...
在Oracle数据库管理和维护过程中,经常需要使用到各种Shell脚本来自动化一些任务或者进行批处理操作,因此确保这些脚本具有执行权限是非常重要的。 #### 二、Oracle数据库的时间类型 - **Timestamp**: Oracle...
Oracle第9章模式对象 Oracle第9章模式对象是Oracle数据库中的一种逻辑结构,用于组织和管理数据库对象。...创建表需要规划和设计,修改表需要权限和安全控制,删除表需要小心操作以免引起数据丢失。
在处理空值(NULL)时要特别小心。空值表示数据无效或未知,它不同于空字符串或零。在涉及空值的数学运算中,结果也会是空值。例如,`SELECT last_name, 12*salary*commission_pct FROM employees;` 如果commission_...
总结起来,MyBatis与Oracle结合处理BLOB字段时,关键步骤包括:正确设置数据库表结构,创建相应的Java实体类,以及编写MyBatis映射文件来定义SQL查询和操作。理解这些概念和操作,能帮助你在实际开发中更有效地管理...
步骤1:先把Fy_Recover_Data包拷贝到oracle相关目录下 步骤2:在scott用户下创建test_emp表: SQL> conn scott/tiger; Connected. SQL> select * from tab; TNAME ? ? ? TABTYPE CLUSTERID --------------...
- **使用 `IS NULL` 和 `IS NOT NULL`**:相比于 `column IS NULL` 和 `column IS NOT NULL`,`column = NULL` 和 `column <> NULL` 的写法是错误的,因为`NULL`值无法通过等于或不等于来判断。 - **合理使用 `>` ...
2. NULL值的理解和处理:在Oracle数据库中,NULL表示的是未知值。对于包含NULL的列进行聚合运算(如SUM、COUNT、AVG等)时,空值会被自动忽略。同时在排序时,空值默认会置于结果集的最后。 3. 使用BETWEEN和LIKE...
### DB2学习记录 #### 一、并发机制与隔离级别 ...通过以上对比分析可以看出,尽管DB2与Oracle在很多方面都有所不同,但从Oracle迁移到DB2的过程中仍然有很多可用的工具和技术可以利用,以确保迁移项目的顺利进行。
3. 小心使用带有通配符的LIKE操作。除非必要,否则应尽量避免在搜索模式的开始处使用通配符,因为这会导致全表扫描。 总的来说,理解Oracle的优化器工作原理和编写高效SQL语句是提升数据库性能的关键。通过优化SQL...
运维工作中,为了确保系统的稳定性和安全性,常常需要借助各种监视工具来进行实时监控与故障排查。以下是一些常用的监控工具: 1. **Cacti**: 图形化网络流量监控工具,能够通过Web界面展示网络设备的带宽使用情况...
9. NULL值处理:在PL/SQL中,NULL值的处理需要特别小心。必须了解NULL作为判断条件的特殊性,以及如何正确使用绑定变量。 10. 性能优化:性能优化是PL/SQL编程中不可避免的话题。合理使用PL/SQL Profiler等工具来...
未指定`WHERE`时,所有行都会被更新,因此在实际操作中要格外小心。 总的来说,这个课件覆盖了数据库设计的基本概念,以及在Oracle环境中使用DML操作数据的关键技能,是学习数据库管理的宝贵资源。理解和掌握这些...
在当前项目中,我们遇到了一个棘手的问题:需要对多个包含超过千万条记录的大表进行复杂的计算、连接(JOIN)以及其他高级查询操作。为了提高系统的响应速度和资源利用率,对SQL语句进行优化变得尤为重要。在此过程...
Oracle数据库触发器是数据库管理系统中的一种重要特性,它允许开发者在特定的数据操作(如INSERT、UPDATE、DELETE)之前或之后执行自定义的SQL代码或PL/SQL块。这些代码可以用来实现业务规则、数据验证、审计跟踪等...
如果数据表中存在聚簇索引,则数据行的物理顺序与索引键的顺序一致。因此,在选择聚簇索引时要特别注意,确保其能有效支持常见的查询模式。 #### 15. 合理使用 `VARCHAR` 和 `CHAR` 在需要存储较短文本的地方,...
尽管文档中提到CURSOR不能定义为WITH UR,但在实际操作中,DB2允许使用`WITH UR`关键字与CURSOR结合。 #### CURSOR ORDER BY 以后不能FOR UPDATE DB2中确实存在这样的限制:带有`ORDER BY`子句的CURSOR不能使用`FOR...