ITPub博客

首页 > Linux操作系统 > Linux操作系统 > LOB字段EMPTY_LOB和NULL的区别

LOB字段EMPTY_LOB和NULL的区别

原创 Linux操作系统 作者:yangtingkun 时间:2010-02-22 23:58:38 0 删除 编辑

前不久写过一篇文章,描述如果表包含了触发器,在通过IMP导入数据的时候,原本的EMPTY_LOB将被转化为NULL。有朋友在文章的回复中问,EMPTY_LOB和NULL的区别,这里就简单描述一下。

包含触发器的LOB表执行IMP导致EMPTY_LOB变为空:http://yangtingkun.itpub.net/post/468/495024

 

 

说实话,二者其实差别还是相当大的。一个表示的未知,另一个表示的空的大对象。需要注意空的大对象并不是空的概念:

SQL> CREATE TABLE T_LOB
  2  (ID NUMBER, 
  3  NAME VARCHAR2(30),
  4  CONTENTS CLOB);

表已创建。

SQL> INSERT INTO T_LOB
  2  VALUES (1, 'TEST NULL', NULL);

已创建 1 行。

SQL> INSERT INTO T_LOB
  2  VALUES (2, 'EMPTY LOB', EMPTY_CLOB());

已创建 1 行。

SQL> COMMIT;

提交完成。

SQL> COL CONTENTS FORMAT A30
SQL> SELECT *
  2  FROM T_LOB
  3  WHERE CONTENTS IS NULL;

        ID NAME                           CONTENTS
---------- ------------------------------ ------------------------------
         1 TEST NULL

使用IS NULL作为条件进行判断,EMPTY_LOB是查询不到的。

利用DBMS_LOB.GETLENGTH也可以看出二者的区别:

SQL> SELECT ID, NAME, DBMS_LOB.GETLENGTH(CONTENTS)
  2  FROM T_LOB;

        ID NAME                           DBMS_LOB.GETLENGTH(CONTENTS)
---------- ------------------------------ ----------------------------
         1 TEST NULL
         2 EMPTY LOB                                                 0

从占用空间上二者也有明显的区别:

SQL> DELETE T_LOB WHERE ID = 2;

已删除 1 行。

SQL> BEGIN      
  2  FOR I IN 1..10000 LOOP
  3  INSERT INTO T_LOB
  4  VALUES (1, 'TEST NULL', NULL);
  5  END LOOP;
  6  COMMIT;
  7  END;
  8  /

PL/SQL 过程已成功完成。

SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'T_LOB')

PL/SQL 过程已成功完成。

SQL> SELECT TABLE_NAME, NUM_ROWS, BLOCKS, AVG_ROW_LEN
  2  FROM USER_TABLES
  3  WHERE TABLE_NAME = 'T_LOB';

TABLE_NAME                       NUM_ROWS     BLOCKS AVG_ROW_LEN
------------------------------ ---------- ---------- -----------
T_LOB                               10001         28          13

SQL> TRUNCATE TABLE T_LOB;

表被截断。

SQL> INSERT INTO T_LOB
  2  VALUES (2, 'EMPTY LOB', EMPTY_CLOB());

已创建 1 行。

SQL> BEGIN
  2  FOR I IN 1..10000 LOOP
  3  INSERT INTO T_LOB
  4  VALUES (2, 'EMPTY LOB', EMPTY_CLOB());
  5  END LOOP;
  6  COMMIT;
  7  END;
  8  /

PL/SQL 过程已成功完成。

SQL> EXEC DBMS_STATS.GATHER_TABLE_STATS(USER, 'T_LOB')

PL/SQL 过程已成功完成。

SQL> SELECT TABLE_NAME, NUM_ROWS, BLOCKS, AVG_ROW_LEN
  2  FROM USER_TABLES
  3  WHERE TABLE_NAME = 'T_LOB';

TABLE_NAME                       NUM_ROWS     BLOCKS AVG_ROW_LEN
------------------------------ ---------- ---------- -----------
T_LOB                               10001         80         116

虽然EMPTY_LOB没有包含LOB内容,但是LOB头信息已经存在,因此需要占用不小的空间。

二者最大的区别在于,EMPTY_LOB虽然没有LOB的内容,但是已经做好了插入LOB内容的准备,用户获取到LOB的头信息后就可以直接插入数据了:

SQL> TRUNCATE TABLE T_LOB;

表被截断。

SQL> INSERT INTO T_LOB
  2  VALUES (1, 'TEST NULL', NULL);

已创建 1 行。

SQL> INSERT INTO T_LOB
  2  VALUES (2, 'EMPTY LOB', EMPTY_CLOB());

已创建 1 行。

SQL> COMMIT;

提交完成。

SQL> DECLARE
  2  V_LOB CLOB;
  3  BEGIN
  4  SELECT CONTENTS 
  5  INTO V_LOB
  6  FROM T_LOB
  7  WHERE ID = 2
  8  FOR UPDATE;
  9  DBMS_LOB.WRITEAPPEND(V_LOB, 10, '0123456789');
 10  COMMIT;
 11  END;
 12  /

PL/SQL 过程已成功完成。

SQL> DECLARE
  2  V_LOB CLOB;
  3  BEGIN
  4  SELECT CONTENTS 
  5  INTO V_LOB
  6  FROM T_LOB
  7  WHERE ID = 1
  8  FOR UPDATE;
  9  DBMS_LOB.WRITEAPPEND(V_LOB, 10, '0123456789');
 10  COMMIT;
 11  END;
 12  /
DECLARE
*
第 1 行出现错误:
ORA-06502: PL/SQL:
数字或值错误 : invalid LOB locator specified: ORA-22275
ORA-06512:
在 "SYS.DBMS_LOB", line 833
ORA-06512:
在 line 9

SQL> SELECT *
  2  FROM T_LOB;

        ID NAME                           CONTENTS
---------- ------------------------------ ------------------------------
         1 TEST NULL
         2 EMPTY LOB                      0123456789

而对于NULL来说,显然是不能直接修改的。

 

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/4227/viewspace-627538/ ,如需转载,请注明出处,否则将追究法律责任。

下一篇: LOB段的等同分区
请登录后发表评论 登录
全部评论
暂无介绍

注册时间:2007-12-29

  • 博文量
    1964
  • 访问量
    11077344