Oracle的clob数据类型
字符串长度
语法:DBMS_LOB.GETLENGTH(field)
作用:获取filed
字段的总长度,和length
函数类似
字符串截取
场景:使用substr
函数有时会无法解决clob数据类型的数据,我们可以使用DBMS_LOB.substr
函数,作用和substr
函数类似。
语法:
-- 从start位置在field截取长度为length的字符串
DBMS_LOB.SUBSTR(field,length,start)
-- 获取field的所有数据
DBMS_LOB.SUBSTR(field)
注意:如果filed的字段很长的话还是会出现"字符串截断"的情况,但是可以根据数据的实际情况调整length
的长度,效果会比substr
函数好点
查询字符串索引位置
语法:
-- 查询field中keyword从startPosition开始第number次出现的索引
dbms_lob.instr(field,keyword,startPosition,number)
-- 查询field中keyword从startPosition开始出现的索引
dbms_lob.instr(field,keyword,startPosition)
-- 从左往右查询field中符合keyword的索引。
dbms_lob.instr(field,keyword)
作用:和instr
类似,不过dbms_lob.instr
可以解决大数据字段的问题
注意:
- 如果
field
中没有找到keyword
,则返回值为0 - 如果
startPosition
的值为0,则返回值为NULL
案例
clob数据类型的数据提取
有的时候我们会在数据库中使用clob
来存储json
的数据,后续需要从clob
中读取对应的数据项。
提取数据,需要分析对应的数据结构,不同的数据结构处理的形式不同。
假设在user
表中的info
字段使用的是clob
数据类型,其中存储如下数据:
{
"employees":[
{"firstName":"Bill","lastName":"Gates","creation_time":"2021-01-01","age":"30"},
{"firstName":"George","lastName":"Bush","creation_time":"2021-06-01","age":"26"},
{"firstName":"Thomas","lastName":"Carter","creation_time":"2020-03-01","age":"23"},
...
]
}
需求:提取出employees
中firstName、lastName、age三个数据项信息,并且数据项的信息是混乱的
思路:使用存储过程,不断的遍历获取所需的数据项,一旦没有找到数据则不再执行。
分析:
-
删除原有临时表的数据,保证临时表记录的数据是最新的
-
使用
dbms_instr
函数来定位关键字的位置,获取关键字对应键的值 -
修改
dbms_instr
函数下一次关键字的起始位置,因为数据量的个数不确定 -
使用
while
来进行死循环,然后当关键字没找到,直接退出死循环,遍历下一行
以下代码在达梦数据库下验证通过
①创建测试数据
create table test001 (
info clob
);
insert into test001 values ('
{
"employees":[
{"firstName":"Bill","lastName":"Gates","creation_time":"2021-01-01","age":"30"},
{"firstName":"George","lastName":"Bush","creation_time":"2021-06-01","age":"26"},
{"firstName":"Thomas","lastName":"Carter","creation_time":"2020-03-01","age":"23"}
]
}
')
②创建临时表存储数据
create table t_employees (
firstname varchar2(20),
lastname varchar2(20),
age number
)
③创建存储过程
create or replace procedure p_employees() is
declare
cursor datas is select info from test001;
-- 定义关键字的位置来获取关键字的信息
firstname_index number;
firstname_start_index number;
firstname_end_index number;
firstname_value varchar2(100);
lastname_index number;
lastname_start_index number;
lastname_end_index number;
lastname_value varchar2(100);
age_index number;
age_start_index number;
age_end_index number;
age_value varchar2(100);
v_sql varchar2(1000);
begin
-- 删除原有的数据,保证临时表存储新的数据
v_sql:= 'delete from t_employees';
execute immediate v_sql;
-- 遍历游标,即遍历每行
for data in datas loop
firstname_start_index:= 1;
lastname_start_index:= 1;
age_start_index:= 1;
while 1>0 loop
-- 根据关键字定位位置,然后获取 firstName": "XXX" 中XX的值
firstname_index:= dbms_lob.instr(data.info,'firstName',firstname_start_index);
if firstname_index=0 then
goto next1;
end if;
firstname_start_index:= firstname_index+length('firstName":"');
firstname_end_index:= dbms_lob.instr(data.info,'"',firstname_start_index);
firstname_value:= dbms_lob.substr(data.info,firstname_end_index-firstname_start_index,firstname_start_index);
lastname_index:= dbms_lob.instr(data.info,'lastName',lastname_start_index);
lastname_start_index:= lastname_index+length('lastName":"');
lastname_end_index:= dbms_lob.instr(data.info,'"',lastname_start_index);
lastname_value:= dbms_lob.substr(data.info,lastname_end_index-lastname_start_index,lastname_start_index);
age_index:= dbms_lob.instr(data.info,'age',age_start_index);
age_start_index:= age_index+length('age":"');
age_end_index:= dbms_lob.instr(data.info,'"',age_start_index);
age_value:= dbms_lob.substr(data.info,age_end_index-age_start_index,age_start_index);
v_sql:= 'insert into t_employees values ('''||firstname_value||''','''||lastname_value||''','||age_value||')';
execute immediate v_sql;
end loop;
<<next1>>
null;
end loop;
end;
④调用存储过程
call p_employees()
⑤查询结果
参考资料
- DBMS_LOB包的使用:http://blog.itpub.net/23065269/viewspace-630417/