精通Oracle10编程SQL(16)使用LOB对象

/*
 *使用LOB对象
 */
--LOB(Large Object)是专门用于处理大对象的一种数据类型,其所存放的数据长度可以达到4G字节
--CLOB/NCLOB用于存储大批量字符数据,BLOB用于存储大批量二进制数据,而BFILE则存储着指向OS文件的指针

/*
 *综合实例
 */
--建立表空间 
--#指定区尺寸为128k,如不指定,区尺寸默认为64k 
CREATE TABLESPACE EAS_D_HAIYA_STANDARD DATAFILE '/oracleDB/oradata/db/EAS_D_HAIYA_STANDARD.ORA' SIZE 500M;-- UNIFORM SIZE 128k; 

DROP TABLESPACE EAS_D_HAIYA_STANDARD INCLUDING CONTENTS AND DATAFILES;

--建立临时表空间 
CREATE TEMPORARY TABLESPACE EAS_T_HAIYA_STANDARD TEMPFILE '/oracleDB/oradata/db/EAS_T_HAIYA_STANDARD.ORA' SIZE 50M;

DROP TABLESPACE EAS_T_HAIYA_STANDARD INCLUDING CONTENTS AND DATAFILES;

--创建用户并指定表空间
create user haiya identified by kingdee
       default tablespace EAS_D_HAIYA_STANDARD   
       temporary tablespace EAS_T_HAIYA_STANDARD;

drop user haiya cascade;

--建立表空间(这样建立表空间才能不报错) 
Create tablespace EAS_D_HAIYA_STANDARD Datafile '/oracleDB/oradata/db/EAS_D_HAIYA_STANDARD.ORA' size 10000M reuse autoextend on next 2M maxsize unlimited;
	       
Create temporary tablespace EAS_T_HAIYA_STANDARD TEMPFILE '/oracleDB/oradata/db/EAS_T_HAIYA_STANDARD.ORA' size 500M reuse autoextend on next 1M maxsize unlimited;

create user haiya Identified by kingdee Default tablespace EAS_D_HAIYA_STANDARD temporary tablespace EAS_T_HAIYA_STANDARD Quota unlimited on EAS_D_HAIYA_STANDARD;

--给用户赋DBA权限
grant dba to haiya;
revoke dba from haiya;

Grant create session,create table,create procedure,create sequence,create trigger,create view,SELECT ANY DICTIONARY to haiya;
--之后操作以haiya用户登录

--一.查询ORACLE SERVER端的字符集
select userenv('language') from dual;
select * from nls_database_parameters;--来源于props$,表示数据库的字符集

--查询客户端字符集环境
select * from nls_instance_parameters;--来源于v$parameter,表示客户端的字符集的设置,可能是参数文件,环境变量或者是注册表

--查询oracle client端的字符集
--在windows平台下,就是注册表里面相应OracleHome的NLS_LANG。还可以在dos窗口里面自己设置,
--比如: set nls_lang=AMERICAN_AMERICA.ZHS16GBK
--这样就只影响这个窗口里面的环境变量。
   
--在unix平台下,就是环境变量NLS_LANG.$echo $NLS_LANGAMERICAN_AMERICA.ZHS16GBK

--如果检查的结果发现server端与client端字符集不一致,请统一修改为同server端相同的字符集。

--二.修改server端字符集(不建议使用)
       
--1.关闭数据库
--SQL>SHUTDOWN IMMEDIATE
 
--2.启动到Mount
--SQL>STARTUP MOUNT;
--SQL>ALTER SYSTEM ENABLE RESTRICTED SESSION;
--SQL>ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;
--SQL>ALTER SYSTEM SET AQ_TM_PROCESSES=0;
--SQL>ALTER DATABASE OPEN;
--SQL>ALTER DATABASE CHARACTER SET ZHS16GBK;
--SQL>ALTER DATABASE national CHARACTER SET ZHS16GBK;
--SQL>SHUTDOWN IMMEDIATE;
--SQL>STARTUP
--注意:如果没有大对象,在使用过程中进行语言转换没有什么影响,(切记设定的字符集必须是ORACLE支持,不然不能start) 按上面的做法就可以。
 
--若出现‘ORA-12717: Cannot ALTER DATABASE NATIONAL CHARACTER SET when NCLOB data exists’ 这样的提示信息,
--要解决这个问题有两种方法
--1. 利用INTERNAL_USE 关键字修改区域设置,
--2. 利用re-create,但是re-create有点复杂,所以请用internal_use
--SQL>SHUTDOWN IMMEDIATE;
--SQL>STARTUP MOUNT EXCLUSIVE;
--SQL>ALTER SYSTEM ENABLE RESTRICTED SESSION;
--SQL>ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0;
--SQL>ALTER SYSTEM SET AQ_TM_PROCESSES=0;
--SQL>ALTER DATABASE OPEN;
--SQL>ALTER DATABASE NATIONAL CHARACTER SET INTERNAL_USE UTF8;
--SQL>SHUTDOWN immediate;
--SQL>startup;
--如果按上面的做法做,National charset的区域设置就没有问题



--1.使用CLOB数据类型
--创建CLOB_TABLE表如出现超出表空间的空间限量的错误,应重新创建表空间并如上用户
--以haiya用户登录
CREATE TABLE CLOB_TABLE
(
  id NUMBER(3) PRIMARY KEY,
  remark CLOB    --remark:备注 
);
INSERT INTO CLOB_TABLE(id) VALUES(1);  --remark列没有定位器,并且没有数据
INSERT INTO CLOB_TABLE VALUES(2,'ID2'); --remark列有定位器,并且有数据
INSERT INTO CLOB_TABLE VALUES(3,empty_clob());--remark含有定位器,但是没有数据

select * from clob_table for update;

--检索定位器的值:
DECLARE
myLob CLOB; 
BEGIN
  SELECT remark INTO myLob FROM CLOB_TABLE WHERE id=1; --1,2或者3
  IF myLob IS NULL THEN
    DBMS_OUTPUT.PUT_LINE('myLob IS NULL');
  ELSE
    DBMS_OUTPUT.PUT_LINE(myLob );
  END IF;
END;

--修改id为1的remark列,使其具有定位器:
UPDATE CLOB_TABLE SET remark=empty_clob() WHERE id=1;

--向CLOB列追加数据
DECLARE
myLob CLOB;
buffer VARCHAR2(20) := '这是第一次追加的内容';
amount INT;
offset INT;
BEGIN
  --要想能够修改LOB数据,必须指定FOR UPDATE子句 
  SELECT remark INTO myLob FROM CLOB_TABLE WHERE id=2 FOR UPDATE ;
  amount:=LENGTH( buffer );  --获取追加文本的长度 
  offset:=DBMS_LOB.GETLENGTH (myLob)+1;  --获取定位器引用的LOB数据的 长度 
  DBMS_LOB.WRITE(myLob,amount,offset, buffer );-- 向CLOB列追加数据,每次最大追加32767字节。要注意必须先存在定位器才能追加数据,否则会出现invalid LOB locator specified: ORA-22275错误。 
  --DBMS_LOB.WRITEAPPEND(myLob,amount, buffer );--使用这个函数不用考虑offset参数 
END;

--读取CLOB数据
DECLARE
myLob CLOB;
text VARCHAR2(40);
amount INT;
offset INT;
BEGIN
  SELECT remark INTO myLob FROM CLOB_TABLE WHERE id=2;
  amount:=15;
  offset:=3;
  --从LOB数据中的第三个字符开始读取共读取15个字符放入到text变量 
  DBMS_LOB.READ(myLob,amount,offset,text);
  DBMS_OUTPUT.PUT_LINE(text);
END;


--2.使用BFILE数据类型
CREATE DIRECTORY TestDir as 'D:\TestDir'; --注意此语句不会在操作系统上创建文件夹

--创建含有BFile数据类型的列,并插入数据
CREATE TABLE BFILE_TABLE(ID NUMBER PRIMARY KEY,remark BFILE);

--插入数据
insert into bfile_table(id) values(1);
update bfile_table set remark=BFILENAME('TESTDIR','1.txt');
insert into bfile_table(id,remark) values(2,bfilename('TESTDIR','2.doc'));
--注意:BFILE数据类型指向的文件,即可以是文本文件,也可以是二进制文件。
--而且BFILE数据类型不能通过SELECT语句直接查看其内容

--将BFile文件的内容读取到CLOB列(前提是BFile文件是文本文件)
DECLARE
src   BFILE;
des   CLOB;
amount    INT;
src_offset INT :=1;
des_offset INT :=1;
csid INT :=850;
lc   INT :=0;
warning INT;
BEGIN
  SELECT remark INTO src FROM BFile_TABLE WHERE id=1;
  SELECT remark INTO des FROM CLOB_TABLE WHERE id=1 FOR UPDATE ;
  DBMS_LOB.FILEOPEN(src,DBMS_LOB.FILE_READONLY);
  amount:=DBMS_LOB.GETLENGTH(src);
  DBMS_OUTPUT.PUT_LINE(amount);
  DBMS_LOB.LOADCLOBFROMFILE (des,src,amount,des_offset,src_offset,csid,lc,warning);
  DBMS_LOB.CLOSE(src);
END;

--3.使用BLOB数据类型
--创建带有BLOB列的表并插入数据
CREATE TABLE BLOB_TABLE
(
 id NUMBER(3),
 remark BLOB
);

INSERT INTO BLOB_TABLE VALUES(1,EMPTY_BLOB());

select * from blob_table;

--将文件内容插入到BLOB列:
DECLARE
src   BFILE;
des   BLOB;
amount    INT;
src_offset INT :=1;
des_offset INT :=1;
csid INT :=0;
lc   INT :=0;
warning INT;
BEGIN
  src:=BFILENAME('TESTDIR','1.txt');
  SELECT remark INTO des FROM BLOB_TABLE WHERE id=1 FOR UPDATE;
  DBMS_LOB.FILEOPEN(src,DBMS_LOB.FILE_READONLY);
  amount:=DBMS_LOB.GETLENGTH(src);
  DBMS_OUTPUT.PUT_LINE(amount);
  DBMS_LOB.LOADBLOBFROMFILE (des,src,amount,des_offset,src_offset);
  DBMS_LOB.CLOSE(src);
END;


--DBMS_LOB包
--过程APPEND
DECLARE
   dest_lob CLOB;
   src_lob CLOB;
BEGIN
   src_lob:='中国';
   dest_lob:='你好,';
   dbms_lob.append(dest_lob,src_lob);
   dbms_output.put_line(dest_lob);
END;

--过程CLOSE:关闭已经打开的LOB,它不仅适用于CLOB/NCLOB和BLOB类型,也适用于BFILE类型
--语法如下:DBMS_LOB.CLOSE(lob_loc IN OUT NOCOPY BLOB/CLOB/BFILE);

--函数COMPARE
--注意,该函数只能用于比较同类型的LOB变量
--语法如下:
--DBMS_LOB.COMPARE(lob_1 in BLOB/CLOB/BFILE,lob_2 in BLOB/CLOB/BFILE,amount in integer:=4294967295,offset_1 in integer:=1,offset_2 in integer:=1) return integer;
--lob_1用于指定第一个LOB变量,lob_2用于指定第二个LOB变量,amount用于指定字符个数(CLOB)或字节个数(BLOB),offset_1用于指定第一个LOB的起始比较位置,offset_2用于指定第二个LOB的起始比较位置。
--如果比较结果相同,则返回0,如果比较结果不同,则返回一个非0的整数。
DECLARE
   dest_lob CLOB;
   src_lob CLOB;
BEGIN
   src_lob:='中国';
   dest_lob:='&content';
   if dbms_lob.compare(src_lob,dest_lob)=0 then
      dbms_output.put_line('内容相同');
   else
      dbms_output.put_line('内容不同');
   end if;
END;

--过程COPY
--该过程用于将源LOB变量的部分或全部内容复制到目标LOB变量中,它只适用于内部LOB类型(CLOB/NCLOB/BLOB),而不适用于BFILE类型
--语法如下:
--DBMS_LOB.COPY(dest_lob in out NOCOPY BLOB/CLOB/NCLOB,src_lob in BLOB/CLOB/NCLOB,amount in integer,dest_offset in integer:=1,src_offset in integer:=1,src_offset in integer:=1);
--dest_offset用于指定要复制到目标LOB变量的起始位置,src_offset用于指定源LOB变量中开始复制的起始位置。
DECLARE
   dest_lob clob;
   src_lob clob;
   amount int;
BEGIN
   src_lob:='中国';
   dest_lob:='你好,';
   amount:=dbms_lob.getlength(src_lob);
   dbms_lob.copy(dest_lob,src_lob,amount,3);
   dbms_output.put_line(dest_lob);
END;

--过程CREATETEMPORARY
--建立临时LOB,只适用于内部LOB类型(BLOB/CLOB/NCLOB),但不适用于BFILE类型。
--当执行该过程建立临时LOB时,ORACLE会将该临时LOB建立在用户的临时表空间中
--语法如下
--DBMS_LOB.CREATETEMPORARY(lob_loc in out NOCOPY BLOB/CLOB/NCLOB,cache in boolean,dur in pls_integer:=10);
--lob_loc用于指定LOB定位符,cache用于指定是否要将LOB读取到缓冲区,dur用于指定何时清除临时LOB(10:会话结束清除临时LOB,12:调用结束清除临时LOB)
DECLARE
   src_lob CLOB;
begin
   dbms_lob.createtemporary(src_lob,true);
end;

--过程ERASE
--用于删除LOB变量的全部内容或部分内容,只适用于内部LOB类型(BLOB/CLOB/NCLOB),而不适用于BFILE类型
DECLARE
   src_lob clob;
   offset int;
   amount int;
begin
   src_lob:='欢迎使用PL/SQL编程指南';
   amount:=10;
   offset:=5;
   dbms_lob.erase(src_lob,amount,offset);
   dbms_output.put_line(src_lob);
end;

--过程FILECLOSE
--用于关闭已经打开的BFILE定位符所指向的OS文件
DBMS_LOB.fileclose(file_loc in out NOCOPY bfile);

--过程FILECLOSEALL
--用于关闭当前会话已经打开的所有BFILE文件
DBMS_LOB.filecloseall;

--函数FILEEXISTS
--用于确定BFILE定位符所指向的OS文件是否存在
DBMS_LOB.fileexists(file_loc in bfile) return integer;
--如果文件存在,则返回1,如果文件不存在,则返回0

--以system用户登录,给当前用户赋创建directory的权限
grant create any directory to haiya;
grant drop any directory to haiya;--(删除权限)

--以haiya用户登录,创建一个目录
create or replace directory bfile_data as 'D:\';

DECLARE
   file1 BFILE;
begin
   --创建bfile locator,使用bfilename函数,directory是大小写敏感的,一定要大写
   file1:=bfilename('BFILE_DATA','README.DOC');
   if dbms_lob.fileexists(file1) = 0 then
      dbms_output.put_line('文件不存在');
   else
      dbms_output.put_line('文件存在');
   end if;
end;

--过程FILEGETNAME
--用于取得BFILE定位符所对应的目录别名和文件名
DECLARE
   dir_alias varchar2(20);
   filename varchar2(50);
   file_loc bfile;
begin
   select remark into file_loc from BFILE_TABLE where id = &id;
   dbms_lob.filegetname(file_loc,dir_alias,filename);
   dbms_output.put_line('目录别名:'||dir_alias);
   dbms_output.put_line('文件名:'||filename);
end;

--函数FILEISOPEN
--用于确定BFILE所对应的OS文件是否已经打开
--如果文件已经被打开,则返回1,如果文件没有被打开,则返回0
DECLARE
   file1 BFILE;
BEGIN
   file1:=bfilename('TESTDIR','2.doc');
   if dbms_lob.fileisopen(file1)=0 then
      dbms_output.put_line('文件未打开');
   else
      dbms_output.put_line('文件已经打开');
   end if;
END;

--过程FILEOPEN
--用于打开BFILE所对应的OS文件
--注意,OS文件只能以只读方式打开
DECLARE
   file1 BFILE;
BEGIN
   file1:=bfilename('TESTDIR','2.doc');
   if dbms_lob.fileexists(file1) = 1 then
      dbms_lob.fileopen(file1);
      dbms_output.put_line('文件已经被打开');
   end if;
   dbms_lob.fileclose(file1);
END;

--过程FREETEMPORARY
--用于释放在默认临时表空间中的临时LOB
DECLARE
   src_lob clob;
begin
   dbms_lob.createtemporary(src_lob,true);
   src_lob:='中华人民共和国';
   dbms_lob.freetemporary(src_lob);
end;

--函数GETCHUNKSIZE
--当建立包含CLOB列或BLOB列的表时,通过指定CHUNK参数可以指定操纵LOB需要分配的字节数(该值是数据块尺寸的整数倍),如果不指定该参数,其
--默认值为数据块的尺寸。通过使用函数GETCHUNKSIZE,可以取得CHUNK参数对应的值
DECLARE
   src_lob clob;
   chunksize int;
begin
   src_lob:='中华人民共和国';
   chunksize:=dbms_lob.getchunksize(src_lob);
   dbms_output.put_line('CHUNK尺寸:'||chunksize);
end;

--函数GETLENGTH
--用于取得LOB数据的实际长度,不仅适用于CLOB和BLOB类型,也适用于BFILE类型
DECLARE
   file1 bfile;
   length int;
begin
   file1:=bfilename('TESTDIR','2.doc');
   length:=dbms_lob.getlength(file1);
   dbms_output.put_line('文件长度:'||length);
end;

--函数INSTR
--用于返回特定样式数所据在LOB中从某偏移位置开始第n次出现时的具体位置,它不仅适用于BLOB和CLOB类型,也适用于BFILE类型
DECLARE
   src_lob clob;
   location int;
   offset int;
   occurence int;
begin
   src_lob:='中国,中国,伟大的中国';
   offset:=2;
   occurence:=2;
   location:=dbms_lob.instr(src_lob,'中国',offset,occurence);
   dbms_output.put_line('从第'||offset||'字符开始,中国第'||occurence||'次出现的具体位置:'||location);
end;

--函数ISOPEN
--用于确定LOB是否已经被打开,适用于BLOB、CLOB和BFILE类型
--如果LOB已经被打开,则返回1,否则返回0
DECLARE
  src_lob clob;
begin
  src_lob:='中国,中国,伟大的中国';
  if dbms_lob.isopen(src_lob)=0 then
     dbms_lob.open(src_lob,1);
  end if;
  dbms_lob.close(src_lob);
end;

--函数ISTEMPORARY
--用于确定LOB定位符是否为临时LOB
declare
   src_lob clob;
begin
   if dbms_lob.istemporary(src_lob) = 1 then
      dbms_output.put_line('已经是临时LOB');
   else
      dbms_output.put_line('临时LOB需要建立');
      dbms_lob.createtemporary(src_lob,true);
   end if;
   dbms_lob.freetemporary(src_lob);
end;

--过程LOADFROMFILE
--用于将BFILE的部分或者全部内容复制到目标LOB变量(CLOB或者BLOB)中
--注意:当使用该过程将BFILE数据装载到CLOB中时,不会进行字符集转换,因此要确保BFILE数据与数据库具有相同字符集,否则装载后的数据为乱码
DECLARE
   src_lob bfile;
   dest_lob clob;
   amount int;
begin
   src_lob:=bfilename('TESTDIR','1.txt');
   dbms_lob.createtemporary(dest_lob,true);
   dbms_lob.fileopen(src_lob,0);
   amount:=dbms_lob.getlength(src_lob);
   dbms_output.put_line('amount:'||amount);
   dbms_lob.loadfromfile(dest_lob,src_lob,amount);
   dbms_lob.fileclose(src_lob);
   dbms_lob.freetemporary(dest_lob);
end;

--过程LOADBLOBFROMFILE
--用于将BFILE数据装载到BLOB中,并且在装载后可以取得新的偏移位置
DECLARE
   src_lob bfile;
   dest_lob blob;
   amount int;
   src_offset int:=1;
   dest_offset int:=1;
begin
   src_lob:=bfilename('TESTDIR','1.txt');
   dbms_lob.createtemporary(dest_lob,true);
   dbms_lob.fileopen(src_lob,0);
   amount:=dbms_lob.getlength(src_lob);
   dbms_lob.loadblobfromfile(dest_lob,src_lob,amount,dest_offset,src_offset);
   dbms_lob.fileclose(src_lob);
   dbms_lob.freetemporary(dest_lob);
   dbms_output.put_line('新的偏移位置:'||dest_offset);
end;

--过程LOADCLOBFROMFILE
--用于将BFILE数据装载到CLOB中,当使用该过程装载数据到CLOB中时,可以指定字符集ID号,并进行字符集转换。
--因此,建议在装载BFILE数据到CLOB中时使用该过程
DECLARE
   src_lob bfile;
   dest_lob clob;
   amount int;
   src_offset int:=1;
   dest_offset int:=1;
   csid int:=0;
   lc int:=0;
   waring int;
begin
   src_lob:=bfilename('TESTDIR','1.txt');
   dbms_lob.createtemporary(dest_lob,true);
   dbms_lob.fileopen(src_lob,0);
   amount:=dbms_lob.getlength(src_lob);
   dbms_lob.loadclobfromfile(dest_lob,src_lob,amount,dest_offset,src_offset,csid,lc,waring);
   dbms_lob.fileclose(src_lob);
   dbms_output.put_line(dest_lob);
   dbms_lob.freetemporary(dest_lob);
end;

--过程OPEN
--用于在打开LOB时指定LOB的读写模式:只读(dbms_lob.lob_readonly)、读写(dbms_lob.lob_readwrite)
DECLARE
   src_lob clob;
   v1 varchar2(100):='中华人民共和国';
   amount int;
begin
   amount:=length(v1);
   dbms_lob.createtemporary(src_lob,true);
   dbms_lob.open(src_lob,dbms_lob.lob_readwrite);
   dbms_lob.write(src_lob,amount,1,v1);
   dbms_lob.close(src_lob);
   dbms_output.put_line(src_lob);
   dbms_lob.freetemporary(src_lob);
end;

--过程READ
--用于将LOB数据读取到绊缓冲区中,不仅适用于BLOB和CLOB,也适用于BFILE
DECLARE
   src_lob clob:='伟大的中国';
   amount int;
   buffer varchar2(200);
   offset int:=1;
begin
   amount:=dbms_lob.getlength(src_lob);
   dbms_lob.open(src_lob,dbms_lob.lob_readonly);
   dbms_lob.read(src_lob,amount,offset,buffer);
   dbms_output.put_line(buffer);
   dbms_lob.close(src_lob);
end;

--函数SUBSTR
--用于返回LOB中从指定位置开始的部分内容,不仅适用于BLOB和CLOB,也适用于BFILE
DECLARE
   src_lob clob:='中国,中国,伟大的中国';
   amount int;
   v1 varchar2(200);
   offset int;
begin
   amount:=10;
   offset:=4;
   v1:=dbms_lob.substr(src_lob,amount,offset);
   dbms_output.put_line(v1);
end;

--过程TRIM
--用于截断LOB内容到指定长度,只适用于BLOB和CLOB,不适用于BFILE
DECLARE
   src_lob clob:='中国,中国,伟大的中国';
   amount int;
begin
   amount:=5;
   dbms_lob.trim(src_lob,amount);
   dbms_output.put_line(src_lob);
end;

--过程WRITE
--用于将缓冲区数据写入到LOB中的特定位置,只适用于BLOB和CLOB,而不适用于BFILE
DECLARE
   src_lob clob:='我的祖国';
   amount int;
   offset int;
   buffer varchar2(100):=',伟大的中国';
begin
   offset:=dbms_lob.getlength(src_lob)+1;
   amount:=length(buffer);
   dbms_lob.write(src_lob,amount,offset,buffer);
   dbms_output.put_line(src_lob);
end;

--过程WRITEAPPEND
--用于将缓冲区数据写入到LOB尾部,只适用于BLOB和CLOB,而不适用于BFILE
DECLARE
   src_lob clob:='我的祖国';
   amount int;
   buffer varchar2(100):=',伟大的中国';
begin
   amount:=length(buffer);
   dbms_lob.writeappend(src_lob,amount,buffer);
   dbms_output.put_line(src_lob);
end;


--访问LOB
--访问CLOB
--建立包含CLOB列的表
CREATE TABLE lob_example1(id number(6) primary key,name varchar2(10),resume clob);

--初始化CLOB列
insert into lob_example1 values(1,'王鸣',empty_clob());
insert into lob_example1 values(2,'马丽',empty_clob());
commit;

select * from lob_example1;

--更新CLOB列的数据
DECLARE
  lob_loc CLOB;
  text varchar2(200);
  amount int;
  offset int;
begin
  select resume into lob_loc from lob_example1 where id=&id for update;
  offset:=DBMS_LOB.getlength(lob_loc)+1;
  text:='&resume';
  amount:=length(text);
  dbms_lob.write(lob_loc,amount,offset,text);
  commit;
end;

select * from lob_example1;

--读取CLOB列的内容
--第6个字符开始的所有字符
DECLARE
   lob_loc clob;
   buffer varchar2(200);
   amount int;
   offset int;
BEGIN
     SELECT resume into lob_loc from lob_example1 where id=&id;
     offset:=6;
     amount:=dbms_lob.getlength(lob_loc);
     dbms_lob.read(lob_loc,amount,offset,buffer);
     dbms_output.put_line(buffer);
END;

--将文本文件内容写入到CLOB列
DECLARE
   lobloc CLOB;
   fileloc bfile;
   amount int;
   src_offset int:=1;
   dest_offset int:=1;
   csid int:=0;
   lc int:=0;
   warning int;
BEGIN
   fileloc:=bfilename('TESTDIR','马丽.txt');
   DBMS_LOB.fileopen(fileloc,0);
   amount:=dbms_lob.getlength(fileloc);
   select resume into lobloc from lob_example1 where id=2 for update;
   dbms_lob.loadclobfromfile(lobloc,fileloc,amount,dest_offset,src_offset,csid,lc,warning);
   dbms_lob.fileclose(fileloc);
   commit;
END;

select * from lob_example1;

--将CLOB列内容写入到文本文件
--下面将RESUME列的内容写入到文本文件d:\testDir\a.txt中为例,说明将CLOB列的内容写入到文本文件的方法
DECLARE
   lobloc clob;
   amount int;
   offset int:=1;
   buffer varchar2(2000);
   handle utl_file.file_type;
begin
   select resume into lobloc from lob_example1 where id=&id;
   amount:=dbms_lob.getlength(lobloc);
   dbms_lob.read(lobloc,amount,offset,buffer);
   handle:=utl_file.fopen('TESTDIR','a.txt','w',2000);
   utl_file.put_line(handle,buffer);
   utl_file.fclose(handle);
end;

--访问BLOB
--建立包含BLOB列的表
--当在表中定义存放大批量二进制数据(例如图形/图象数据)的列时,应该选择BLOB类型
CREATE TABLE lob_example2(id number(6) primary key,name varchar2(10),photo blob);

--初始化BLOB列
INSERT INTO lob_example2 values(1,'王鸣',empty_blob());
insert into lob_example2 values(2,'马丽',empty_blob());
commit;

select * from lob_example2;

--将二进制文件内容写入BLOB列
DECLARE
    lobloc blob;
    fileloc bfile;
    amount int;
    src_offset int:=1;
    dest_offset int:=1;
begin
    select photo into lobloc from lob_example2 where id=&id for update;
    fileloc:=bfilename('TESTDIR','&filename');
    dbms_lob.fileopen(fileloc,0);
    amount:=dbms_lob.getlength(fileloc);
    dbms_lob.loadblobfromfile(lobloc,fileloc,amount,dest_offset,src_offset);
    dbms_lob.fileclose(fileloc);
    commit;
end;

--读取BLOB列数据
--因为BLOB列中存放着二进制数据,所以当读取其数据时应该使用RAW变量接收其数据
--读取BLOB列的数据可以使用包DBMS_LOB的过程READ来完成
declare
   lobloc blob;
   buffer raw(20000);
   amount int;
   offset int:=1;
begin
   select photo into lobloc from lob_example2 where id=&id;
   amount:=dbms_lob.getlength(lobloc);
   dbms_output.put_line(amount);
   dbms_lob.read(lobloc,amount,offset,buffer);
end;

select * from lob_example2;

--将BLOB列的内容写入到二进制文件
DECLARE
   lobloc blob;
   amount int;
   offset int:=1;
   buffer raw(2000);
   handle utl_file.file_type;
begin
   select photo into lobloc from lob_example2 where id=&id;
   amount:=dbms_lob.getlength(lobloc);
   dbms_lob.read(lobloc,amount,offset,buffer);
   handle:=utl_file.fopen('TESTDIR','a.bmp','w',1000);
   utl_file.put_raw(handle,buffer);
   utl_file.fclose(handle);
end;

--访问BFILE
--建立包含BFILE列的表
CREATE TABLE lob_example3(id number(6) primary key,name varchar2(10),resume bfile);

--初始化BFILE列
insert into lob_example3 values(1,'王鸣',bfilename('TESTDIR','王鸣.jpg'));
insert into lob_example3 values(2,'马丽',bfilename('TESTDIR','马丽.jpg'));
commit;

select * from lob_example3;

--读取BFILE列的内容
DECLARE
   buffer RAW(2000);
   amount int;
   offset int;
   lobloc bfile;
begin
   select resume into lobloc from lob_example3 where id=&id;
   dbms_lob.fileopen(lobloc,0);
   amount:=dbms_lob.getlength(lobloc);
   offset:=1;
   dbms_lob.read(lobloc,amount,offset,buffer);
   dbms_lob.fileclose(lobloc);
end;

 

你可能感兴趣的:(oracle,数据库,plsql)