UTL_COMPRESS 包

为了在DM上兼容ORACLE的UTL_COMPRESS包,提供功能上与ORACLE基本一致的UTL_COMPRESS包。UTL_COMPRESS包提供对输入的BLOB、VARBINARY或BFILE类型数据进行压缩或解压的功能。压缩与解压的格式兼容gzip(-n),压缩时支持指定压缩等级,且支持分段压缩或解压。

调用UTL_COMPRESS包中的相关函数和过程时需要保证DM安装目录的bin子目录下存在libz.dll(windows)或libz.so(linux)库文件,否则报错。

43.1 相关方法

下面对各个函数和过程进行详细说明。

  1. LZ_COMPRESS

对数据进行压缩。

语法如下:

FUNCTION LZ_COMPRESS(

	SRC			IN		VARBINARY,

   	QUALITY		IN		INTEGER DEFAULT 6
   
) RETURN VARBINARY;

FUNCTION LZ_COMPRESS(

	SRC			IN		BLOB,

   	QUALITY		IN		INTEGER DEFAULT 6
   
) RETURN BLOB;

FUNCTION LZ_COMPRESS(

	SRC			IN		BFILE,

   	QUALITY		IN		INTEGER DEFAULT 6
   
) RETURN BLOB;

PROCEDURE LZ_COMPRESS(

	SRC			IN		BLOB,

	DST			IN OUT 	BLOB,

   	QUALITY		IN		INTEGER DEFAULT 6
   
);

PROCEDURE LZ_COMPRESS(

	SRC			IN		BFILE,

	DST			IN OUT 	BLOB,

   	QUALITY		IN		BINARY_INTEGER DEFAULT 6
   
);

参数详解

● SRC 输入参数,VARBINARY、BLOB或BFILE类型的待压缩数据。

● QUALITY 输入参数,压缩等级。取值范围1~9:1表示1级压缩;2表示2级压缩;9表示9级压缩。压缩级别越高,压缩速度越慢,但压缩比越高。默认值为6。

● DST 输入输出参数,压缩结果。

返回值

压缩结果。若待压缩数据类型为VARBINARY,则压缩结果的数据类型也为VARBINARY;若待压缩数据类型为BLOB或BFILE,则压缩结果的数据类型均为BLOB。

使用说明:

(1) 待压缩数据不能为空,否则报错;

(2) 若压缩结果的数据类型为VARBINARY,且压缩结果的数据长度超过32767个字节,则返回空;

(3) 若待压缩数据类型为BFILE,则需要首先调用DBMS_LOB.FILEOPEN打开BFILE,否则报错;

(4) 压缩等级必须在合法范围内,否则报错;

(5) 若返回值类型为BLOB,或输出参数为临时BLOB大对象,则需要调用DBMS_LOB.FREETEMPORARY释放临时的BLOB大对象;

(6) ORACLE与DM对数据的压缩结果不一定完全相同,但得到压缩数据都可以被ORACLE或DM解压。

  1. LZ_UNCOMPRESS

对数据进行解压。

语法如下:

FUNCTION LZ_UNCOMPRESS(

	SRC			IN		VARBINARY

) RETURN VARBINARY;

FUNCTION LZ_UNCOMPRESS(

	SRC			IN		BLOB

) RETURN BLOB;

FUNCTION LZ_UNCOMPRESS(

	SRC			IN		BFILE

) RETURN BLOB;

PROCEDURE LZ_UNCOMPRESS(

	SRC			IN		BLOB,

	DST			IN OUT	BLOB
);

PROCEDURE LZ_UNCOMPRESS(

	SRC			IN		BFILE,

	DST			IN OUT	BLOB

);

参数详解

● SRC 输入参数,VARBINARY、BLOB或BFILE类型的待解压数据。

● DST 输入输出参数,解压结果。

返回值

解压结果。若待解压数据类型为VARBINARY,则解压结果的数据类型也为VARBINARY;若待解压数据类型为BLOB或BFILE,则解压结果的数据类型均为BLOB。

使用说明:

(1) 待解压数据不能为空,否则报错;

(2) 若解压结果的数据类型为VARBINARY,且解压结果的数据长度超过32767个字节,则返回空;

(3) 若待解压数据类型为BFILE,则需要首先调用DBMS_LOB.FILEOPEN打开BFILE,否则报错;

(4) 若返回值类型为BLOB,或输出参数为临时BLOB大对象,则需要调用DBMS_LOB.FREETEMPORARY释放临时的BLOB大对象。

  1. ISOPEN

判断句柄是否打开。

语法如下:

FUNCTION ISOPEN(

	HANDLE			IN	INTEGER

) RETURN BOOLEAN;

参数详解

● HANDLE 输入参数,句柄。用1~5之间的5个整型数字表示句柄,详细介绍请参考LZ_COMPRESS_OPEN函数的使用说明。

返回值

TRUE:句柄已打开。

FALSE:句柄未打开。

  1. LZ_COMPRESS_OPEN

打开一个压缩句柄,指定一个BLOB大对象用于存放压缩结果。

语法如下:

FUNCTION LZ_COMPRESS_OPEN (

	DST			IN OUT	BLOB,

   	QUALITY   	IN		INTEGER DEFAULT 6
   
) RETURN INTEGER;

参数详解

● DST 输入输出参数,用于存放压缩结果的BLOB大对象。

● QUALITY 输入参数,压缩等级。取值范围1~9:1表示1级压缩;2表示2级压缩;9表示9级压缩。压缩级别越高,压缩速度越慢,但压缩比越高。默认值为6。

返回值

压缩句柄的对应值。

使用说明:

(1) BLOB大对象不能为空,否则报错;

(2) 压缩等级必须在合法范围内,否则报错;

(3) 每个会话最多打开5个压缩或解压句柄,分别用1~5之间的5个整数表示,若打开句柄的个数超过5个,则报错。调用LZ_COMPRESS_OPEN函数时会优先打开已关闭的句柄中值较小的句柄,例如:新建一个会话,打开三个句柄,则返回三个值为1、2、3的句柄,关闭值为2的句柄,再打开三个句柄,则返回三个值为2、4、5的句柄,由于此时打开的句柄个数为5个,若继续打开句柄,则报错。

  1. LZ_COMPRESS_ADD

按照压缩句柄指定的压缩等级,压缩数据。

语法如下:

PROCEDURE LZ_COMPRESS_ADD (

	HANDLE 		IN		INTEGER,

	DST			IN OUT	BLOB,

	SRC 		IN		VARBINARY

);

参数详解

● HANDLE 输入参数,压缩句柄。用1~5之间的5个整型数字表示句柄,详细介绍请参考LZ_COMPRESS_OPEN函数的使用说明。

● DST 输入输出参数,压缩句柄对应的BLOB大对象,用于存放压缩结果。

● SRC 输入参数,待压缩数据。

使用说明:

(1) 用户需要提前打开压缩句柄,否则报错;

(2) 压缩句柄必须与BLOB大对象相对应,否则报错;

(3) 待压缩数据与BLOB大对象均不能为空,否则报错;

(4) LZ_COMPRESS_ADD执行过程中会随时将压缩数据更新到BLOB大对象中,更新的压缩数据将被添加到BLOB大对象的末尾。

  1. LZ_COMPRESS_CLOSE

将缓存中的压缩数据全部写入BLOB大对象,关闭压缩句柄。

语法如下:

PROCEDURE LZ_COMPRESS_CLOSE (

	HANDLE 		IN		INTEGER,

	DST			IN OUT	BLOB

);

参数详解

● HANDLE 输入参数,压缩句柄。用1~5之间的5个整型数字表示句柄,详细介绍请参考LZ_COMPRESS_OPEN函数的使用说明。

● DST 输入输出参数,压缩句柄对应的BLOB大对象,用于存放压缩结果。

使用说明:

(1) 若压缩句柄已经处于关闭状态,则报错;

(2) 压缩句柄必须与BLOB大对象相对应,否则报错;

(3) 若执行LZ_COMPRESS_OPEN后并未执行LZ_COMPRESS_ADD,则压缩结果为空,即BLOB大对象为空,执行LZ_COMPRESS_OPEN时BLOB大对象的初始值不会影响最后的结果。

  1. LZ_UNCOMPRESS_OPEN

打开一个解压句柄,指定一个待解压的BLOB大对象。

语法如下:

FUNCTION LZ_UNCOMPRESS_OPEN(

	SRC			IN	BLOB

) RETURN BINARY_INTEGER;

参数详解

● SRC 输入参数,待解压的BLOB大对象。

返回值

解压句柄的对应值。

使用说明:

(1) BLOB大对象不能为空,否则报错;

(2) 该函数返回句柄值的策略与LZ_COMPRESS_OPEN相同,详细介绍请参考LZ_COMPRESS_OPEN函数的使用说明。

  1. LZ_UNCOMPRESS_EXTRACT

从上次解压结束的位置,继续解压句柄对应的BLOB大对象。

语法如下:

PROCEDURE LZ_UNCOMPRESS_EXTRACT(

	HANDLE 		IN	INTEGER,

	DST			OUT	VARBINARY

);

PROCEDURE LZ_UNCOMPRESS_EXTRACT(

	HANDLE 		IN	INTEGER,

	DST			OUT	VARBINARY,

	OUTLEN		IN	INTEGER

);

参数详解

● HANDLE 输入参数,解压句柄。用1~5之间的5个整型数字表示句柄,详细介绍请参考LZ_COMPRESS_OPEN函数的使用说明。

● DST 输出参数,解压结果。

● OUTLEN 输入参数,指定解压的数据长度。取值范围为[0,32767],单位:字节。

使用说明:

(1) 用户需要提前打开解压句柄,否则报错;

(2) 若调用LZ_UNCOMPRESS_EXTRACT时解压句柄对应的BLOB大对象已经全部解压完成,则报错;

(3) 若待解压数据过长导致无法被完全解压,则ORACLE会根据输出参数DST的定义长度,解压相应长度的数据存放在DST中,DM不支持上述策略,当待解压数据无法被完全解压时,调用两个参数的LZ_UNCOMPRESS_EXTRACT将始终解压32767个字节长度的数据,为此,DM提供三个参数的LZ_UNCOMPRESS_EXTRACT,用户可通过OUTLEN参数指定解压的数据长度;

(4) 若调用LZ_UNCOMPRESS_EXTRACT时,解压句柄对应的BLOB大对象还未开始解压,则将检查该BLOB大对象是否有GZIP格式的压缩头,若没有则报错;

(5) 若解压句柄对应的BLOB大对象已经解压完成,则会对该BLOB大对象进行CRC校验,若校验失败则报错;

(6) ORACLE对第一次执行LZ_UNCOMPRESS_EXTRACT时的待解压BLOB大对象中的内容进行解压,而DM对执行LZ_UNCOMPRESS_OPEN时的待解压BLOB大对象中的内容进行解压。即若用户在执行LZ_UNCOMPRESS_OPEN之后,且在第一次执行LZ_UNCOMPRESS_EXTRACT之前修改了待解压BLOB大对象中的内容,则ORACLE的解压结果会相应改变,但DM的解压结果不会发生变化。但若用户在执行LZ_UNCOMPRESS_EXTRACT之后修改了待解压BLOB大对象中的内容,则ORACLE和DM的解压结果均不会发生变化。

  1. LZ_UNCOMPRESS_CLOSE

关闭解压句柄。

语法如下:

PROCEDURE LZ_UNCOMPRESS_CLOSE(

	HANDLE 		IN	INTEGER

);

参数详解

● HANDLE 输入参数,解压句柄。用1~5之间的5个整型数字表示句柄,详细介绍请参考LZ_COMPRESS_OPEN函数的使用说明。

使用说明:

若解压句柄已经处于关闭状态,则报错。

43.2 举例说明

使用包内的过程和函数之前,如果还未创建过系统包。请先调用系统过程SP_CREATE_SYSTEM_PACKAGES(1)创建系统包。

SP_CREATE_SYSTEM_PACKAGES(1);

准备如下数据:

CREATE TABLE BFILE_TABLE(ID NUMBER,BFILE_COLUMN BFILE);

CREATE DIRECTORY MYBFILE AS 'D:\testxml\bfile';

INSERT INTO BFILE_TABLE VALUES (1,BFILENAME('MYBFILE','bfiletest.txt'));

CREATE TABLE BLOB_TABLE(ID NUMBER,BLOB_COLUMN BLOB);

COMMIT;

其中,D:\testxml\bfile目录下的bfiletest.txt文件中的内容如下:

《红楼梦》写的是封建贵族的青年贾宝玉、林黛王、薛宝钗之间的恋爱和婚姻悲剧,而且以此为中心,写出了当时具有代表性的贾、王、史、薛四大家族的兴衰,其中又以贾府为中心,揭露了封建社会后期的种种黑暗和罪恶,及其不可克服的内在矛盾,对腐朽的封建统治阶级和行将崩溃的封建制度作了有力的批判,使读者预感到它必然要走向覆灭的命运。

例1 LZ_COMPRESS函数的使用。

一 从BFILE文件中读取数据并进行压缩。

DECLARE

  SRC_BFILE BFILE;
  
  DST_BLOB BLOB;
  
BEGIN

  SELECT BFILE_COLUMN INTO SRC_BFILE FROM BFILE_TABLE WHERE ID=1 FOR UPDATE;
  
  DBMS_LOB.OPEN(SRC_BFILE);  --打开BFILE文件
  
  DST_BLOB := UTL_COMPRESS.LZ_COMPRESS(SRC_BFILE,6);  --进行数据压缩
  
  INSERT INTO BLOB_TABLE VALUES(1,DST_BLOB);

END;

二 查询压缩结果。

SELECT * FROM BLOB_TABLE WHERE ID=1;

查询结果为:

ID		   BLOB_COLUMN

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

1  

0x1F8B08000000000000034D90D16E82301486EFF7D4A096A1A8A05B86933AA243D1250833C8B4157D187B4ECBD55E61AD2ECB925E347F4FBEEF3FBD5A3DC916B83CE16275B53C705EE5B483931C0A1B3853E51E435F27CD6C0CC7529567D8CEE4B07BB56C7C0B1B1EC9A1A7EFEA25D279330EC5D16BC2D2106C4FBA9F30EEC3660A29C7D60EBAE9F7A9AFACBE383C0BBEC42C1107260E195CDA3AD75E78648239503F615801F942DA15FC5DCDD768A51AA8D55A74D781BFFB95461124296CAB7B4920A59A1786462A43F65D2D329D19FDEF423F6BE8CEB86E3BCAE42C4E53088648630D91E9409F868F701AEAFEB2FE40BB324CBF77C30EC0CF81784807C6E810A06B1947323A9B99FCA84880B4364F77388F71C79B492559AA696ADE87C2817283ACFD37036E056C256AAA2BE9ADA117990FEC1EC14D3453D4179573659166D1C14E0C6E01DB365C88EC546A65AB7D01C148AD1C69670638AAD525B85AAD871F26B4024BD8010000

例2 LZ_UNCOMPRESS函数的使用。

一 对给定的压缩数据进行解压。

DECLARE

  SRC_BLOB BLOB;

  DST_BLOB BLOB;

BEGIN

  SRC_BLOB:=HEXTORAW('1F8B080000000000000BBB70EEC8B56B17CE1DB940777A204D24CF0E004F3D66292C010000');    --符合校验的压缩数据
  
  DST_BLOB := UTL_COMPRESS.LZ_UNCOMPRESS(SRC_BLOB);  --进行数据解压
  
  INSERT INTO BLOB_TABLE VALUES(2,DST_BLOB);
  
END;

二 查询解压结果。

SELECT * FROM BLOB_TABLE WHERE ID=2;

查询结果为:

ID		   BLOB_COLUMN

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

2  

0xD0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CED0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CED0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CED0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0

例3 分段压缩。

一 对给定的数据进行分段压缩。

DECLARE

  V_HANDLE BINARY_INTEGER;
  
  DST_BLOB BLOB;
  
  SRC_VAR VARBINARY;
  
BEGIN

SRC_VAR:=HEXTORAW('D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CED0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CED0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CED0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0');
  
  DBMS_LOB.CREATETEMPORARY(DST_BLOB, TRUE);  --创建临时BLOB大对象
  
  V_HANDLE :=UTL_COMPRESS.LZ_COMPRESS_OPEN(DST_BLOB,5);  --打开压缩句柄
  
  UTL_COMPRESS.LZ_COMPRESS_ADD(V_HANDLE,DST_BLOB,SRC_VAR);  --进行分段压缩
  
  UTL_COMPRESS.LZ_COMPRESS_CLOSE(V_HANDLE,DST_BLOB);  --关闭压缩句柄
  
  INSERT INTO BLOB_TABLE VALUES(3,DST_BLOB);
  
  DBMS_LOB.FREETEMPORARY(DST_BLOB);  --释放临时BLOB大对象
  
END;

二 查询分段压缩结果。

SELECT * FROM BLOB_TABLE WHERE ID=3;

查询结果为:

ID		   BLOB_COLUMN

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

3            0x1F8B0800000000000003BB70EEC8B56B17CE1DB940779AB00A5269C22A4857894C03004F3D66292C010000

例4 分段解压。

一 对给定的压缩数据进行分段解压。

DECLARE

  SRC_BLOB BLOB;
  
  DST_TEMP VARBINARY;
  
  DST_OUT BLOB;
  
  V_HANDLE BINARY_INTEGER;
  
BEGIN

  SRC_BLOB:=HEXTORAW('1F8B080000000000000BBB70EEC8B56B17CE1DB940777A204D24CF0E004F3D66292C010000');  --符合校验的压缩数据
  
  V_HANDLE :=UTL_COMPRESS.LZ_UNCOMPRESS_OPEN(SRC_BLOB); --打开解压句柄
  
  DBMS_LOB.CREATETEMPORARY(DST_OUT, TRUE);  --创建临时BLOB大对象
  
  --利用循环结构进行分段解压
  
  LOOP
  
    BEGIN
  
      UTL_COMPRESS.LZ_UNCOMPRESS_EXTRACT(V_HANDLE, DST_TEMP);
  
      EXCEPTION
  
        WHEN OTHERS THEN
  
      EXIT;
  
    END;
  
    DBMS_LOB.APPEND(DST_OUT, DST_TEMP);
  
  END LOOP;
  
  UTL_COMPRESS.LZ_UNCOMPRESS_CLOSE(V_HANDLE);	--关闭解压句柄
  
  INSERT INTO BLOB_TABLE VALUES(4,DST_OUT);
  
  DBMS_LOB.FREETEMPORARY(DST_OUT);  --释放临时BLOB大对象
  
END;

二 查询分段解压结果。

SELECT * FROM BLOB_TABLE WHERE ID=4;

查询结果为:

ID		   BLOB_COLUMN

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

4  

0xD0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CED0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CED0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CED0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0CEC4D0CEC4D6D6D0
微信扫码
分享文档
扫一扫
联系客服