从 JSON 中提取很长的字符串到 CLOB
Posted
技术标签:
【中文标题】从 JSON 中提取很长的字符串到 CLOB【英文标题】:Extracting very long string from JSON to CLOB 【发布时间】:2017-07-24 09:57:50 【问题描述】:我正在尝试从 json_object_t 将一个很长的字符串提取到 clob 中,并使用 json_object_t.get_clob(key) 方法获得了一些奇怪的数据库行为 (12.2c)。 有一个示例代码比以下:
DECLARE
l_data CLOB := '"text": "very long string about 1M chars"';
l_json json_object_t;
l_text CLOB := EMPTY_CLOB();
BEGIN
l_json := json_object_t.parse(l_data);
l_text := l_json.get_clob('text');
dbms_output.put_line('got ' || dbms_lob.getlength(l_text) || ' chars');
END;
当 'text' 键中的字符串长度小于 32k 字符时,get_clob 方法可以正常工作并显示适当的结果,但是对于较长的字符串,它会产生一个长度为零的空 clob,就像 get_string 一样,但没有 'character string缓冲区太小”异常。
我尝试通过 json_table 查询获取相同的数据,但它根本无法将数据提取到 clob 列,只允许使用 varchar/number。
这是一个错误还是我做错了什么?还有其他方法可以从 JSON 键中提取长字符串吗?
【问题讨论】:
【参考方案1】:我与 Oracle 数据库 JSON 存储组合作,很乐意帮助您解决您面临的这个问题。您能否尝试使用备用 get_Clob 过程而不是此函数并告诉我们行为是什么?
签名:
MEMBER PROCEDURE get_Clob(key VARCHAR2, c IN OUT CLOB)
请试试这个:
DECLARE
content_json CLOB := '"value":"';
content_json_end CLOB := '"';
content_tmp CLOB := 'ab';
l_json json_object_t;
l_text CLOB := EMPTY_CLOB();
tmp clob;
BEGIN
-- 13 gives 16K
-- 14 gives 32K
FOR count IN 1 .. 14
loop
dbms_lob.append(content_tmp, content_tmp); -- a bad append for now
END loop;
dbms_lob.append(content_json, content_tmp);
dbms_lob.append(content_json, content_json_end);
l_json := json_object_t.parse(content_json);
l_json.get_clob('value', l_text); -- !!! TRY THIS PROC get_Clob
--l_text := l_json.get_clob('value');
dbms_output.put_line('Lob size in Kb: ');
dbms_output.put_line(dbms_lob.getLength(l_text) / 1024);
END;
/
期待你的发现..
【讨论】:
您好,只是想与您核实一下。您是否尝试过其他方法?有效果吗? 唉,同样的结果:Lob size in Kb: 0. 此外,get_blob 工作正常 - livesql.oracle.com/apex/livesql/file/… Caine,我是开发 JSON_OBJECT_T 等方法的人。不幸的是,我无法重现您的问题(也尝试了几个早期版本)。请向我提供以下信息:1)您使用什么数据库字符集 SELECT value$ FROM sys.props$ WHERE name = 'NLS_CHARACTERSET' ; 2)您使用什么版本的数据库?从 V$INSTANCE 中选择版本; 现在已经在 ALF32UTF8 字符集的 12.2.0.1 数据库版本上重现了。与此同时,我们已经解决了这个问题。请联系 Oracle 支持以获取您的数据库版本的反向移植。谢谢你。【参考方案2】:这也有效。而不是使用get_clob
方法,而是使用c
:
DECLARE
CURSOR crsrJSON IS
SELECT
json_object( 'employee_id' VALUE employee_id,
'first_name' VALUE first_name,
'last_name' VALUE last_name,
'email' VALUE email,
'phone_number' VALUE phone_number,
'hire_date' VALUE to_char(hire_date,'MM/DD/YYYY'),
'job_id' VALUE job_id,
'salary' VALUE nvl(salary,0),
'commission_pct' VALUE nvl(commission_pct,0),
'manager_id' VALUE NVL(manager_id,0),
'department_id' VALUE NVL(department_id,0),
'department_name' VALUE (select department_name from departments x where x.department_id = hr.department_id),
'job_title' VALUE (select job_title from jobs x where x.job_id = hr.job_id)) emp_data
FROM
employees hr;
js_array JSON_ARRAY_T := new JSON_ARRAY_T;
json_obj JSON_OBJECT_T := JSON_OBJECT_T();
json_clob CLOB := EMPTY_CLOB();
BEGIN
FOR data_rec IN crsrJSON LOOP
js_array.append(JSON_ELEMENT_T.parse(data_rec.emp_data));
END LOOP;
json_obj.put('data',js_array);
IF json_obj.has('data') THEN
json_clob := json_obj.to_clob;
DBMS_OUTPUT.PUT_LINE(json_clob);
ELSE
DBMS_OUTPUT.PUT_LINE('Nope');
END IF;
END;
【讨论】:
如果你想提取一个长键值,这也适用(与我的示例代码相关): (json_elem JSON_ELEMENT_T;) json_elem := json_obj.get('data'); DBMS_OUTPUT.PUT_LINE(json_elem.to_clob);【参考方案3】:with data as
( select
xmlelement(e,regexp_replace('"name":"'||colname||'"', '[[:cntrl:]]', ''),',') col1
from tblname
)
select
rtrim(replace(replace(replace(xmlagg(col1).getclobval(),'&'||'quot;','"'),'<E>',''),'</E>',''),',')
as very_long_json
from data;
【讨论】:
只要执行你就会找到你梦想中的 json :D以上是关于从 JSON 中提取很长的字符串到 CLOB的主要内容,如果未能解决你的问题,请参考以下文章
oracle 10g中怎样执行很长的sql语句呢(最长可能有10万+字符)