如何在 Oracle 中为大于 32k(例如 60,000 个字符)的 CLOB 生成 JSON?
How to generate JSON in Oracle for a CLOB that is > 32k (e.g. 60,000 characters)?
1 ) 我必须从 oracle select 查询中创建 json,我可以遵循三种方法。
SELECT JSON_ARRAY(json_object('id' VALUE employee_id,
'data_clob' VALUE data_clob
)) from tablename;
我也尝试过这种方法
2) 如果您无法 patch/work 使用该版本,Lewis Cunningham 和 Jonas Krogsboell 编写了一个优秀的软件包:PL/JSON * http://pljson.sourceforge.net/
这是一个很棒的包(我已经在许多数据库安装中使用过它)。
包含的示例很好,涵盖了大多数场景。
declare
ret json;
begin
ret := json_dyn.executeObject('select * from tab');
ret.print;
end;
/
也在这个答案中提及,但不适用于这么大的 clob。
Return results of a sql query as JSON in oracle 12c
3) 另一种方法是我们可以在 select 查询之后连接字符串。
FOR rec IN (SELECT employee_id, data_clob
FROM tablename) LOOP
IF i <> 1 THEN
v_result := v_result || ',';
END IF;
v_result := v_result || '{"employee_id":' || to_char(rec.employee_id) || ',"data_clob": ' || rec.data_clob || '}';
i := i + 1;
END LOOP;
v_result := v_result || ']}';
3 方法解决了我的问题,但我不想 运行 for loop 。 oracle 中是否有任何解决方案来处理此问题。
我检查了解决方案,但没有 for 循环就无法工作。
url 提供了一些解决方案,我试过了但没有用。同样的问题即将到来。
ORA-22835: Buffer too small for CLOB to CHAR or BLOB to RAW conversion (actual: 57416, maximum: 4000)
你能告诉我怎么做吗?
从 12.2 版本开始你可以做:
select
json_object(
'body' value v_clob
returning clob
)
from dual;
原回答:
在回答这个问题时:
3 approach solve my problem but i don't want to run for loop . Is there is any solution in oracle to handle this .
可以使用 Oracle 的 LISTAGG
函数连接字符串而无需循环:
SELECT '{"employees":[' || LISTAGG('{"employee_id":' || to_char(employee_id)
|| ',"data_clob":"' || data_clob || '"}', ',')
WITHIN GROUP (ORDER BY employee_id) || ']}' AS json
FROM tablename;
但是,正如您在评论中指出的那样,LISTAGG
有 4000 个字符的限制。以下是更多 complex/fiddly 但应该应对超出此限制:
SELECT '{"employees":[' || dbms_xmlgen.convert(
RTRIM(XMLAGG(XMLELEMENT(E,'{"employee_id":' || to_char(employee_id)
|| ',"data_clob":"' || data_clob || '"}',',')
.EXTRACT('//text()') ORDER BY employee_id).GetClobVal(),',')
, 1) || ']}' AS json
FROM tablename;
XMLAGG
处理 CLOB
,但处理 EXTRACT
function has the side-effect of escaping certain characters (e.g. from "
to "
). The query above converts these back (e.g. from "
to "
) using the dbms_xmlgen.convert
function - see this answer 以获取更多详细信息。
SQL Fiddle 演示: http://sqlfiddle.com/#!4/5b295/40
By default the new json_* functions return a varchar2(4000). You can change this in the returning clause.
If you have extended data types enabled, you can change this to a varchar2(32767). But only the *agg functions support clob.
来自 here
SELECT length(JSON_ARRAYAGG(
JSON_OBJECT(
KEY 'object_type' VALUE object_type,
KEY 'object_name' VALUE object_name
)
returning clob)
) array_size
FROM all_objects;
ARRAY_SIZE
5772072
18c 还完全支持 JSON* 函数中的 clobs
在 12.2 中,json_* 函数可以很好地处理 clob。使用子句 Returning clob
create table t( c clob, constraint t_chk check (c is json));
declare
v_clob clob;
begin
for i in 1..10000 loop
v_clob := v_clob || 'asdasdadasdasdasdasdasdasdasd';
end loop;
insert into t(c)
select
json_object
(
'body' value v_clob returning clob
)
from
dual;
end;
1 ) 我必须从 oracle select 查询中创建 json,我可以遵循三种方法。
SELECT JSON_ARRAY(json_object('id' VALUE employee_id,
'data_clob' VALUE data_clob
)) from tablename;
我也尝试过这种方法
2) 如果您无法 patch/work 使用该版本,Lewis Cunningham 和 Jonas Krogsboell 编写了一个优秀的软件包:PL/JSON * http://pljson.sourceforge.net/
这是一个很棒的包(我已经在许多数据库安装中使用过它)。
包含的示例很好,涵盖了大多数场景。
declare
ret json;
begin
ret := json_dyn.executeObject('select * from tab');
ret.print;
end;
/
也在这个答案中提及,但不适用于这么大的 clob。 Return results of a sql query as JSON in oracle 12c
3) 另一种方法是我们可以在 select 查询之后连接字符串。
FOR rec IN (SELECT employee_id, data_clob
FROM tablename) LOOP
IF i <> 1 THEN
v_result := v_result || ',';
END IF;
v_result := v_result || '{"employee_id":' || to_char(rec.employee_id) || ',"data_clob": ' || rec.data_clob || '}';
i := i + 1;
END LOOP;
v_result := v_result || ']}';
3 方法解决了我的问题,但我不想 运行 for loop 。 oracle 中是否有任何解决方案来处理此问题。
我检查了解决方案,但没有 for 循环就无法工作。
url 提供了一些解决方案,我试过了但没有用。同样的问题即将到来。
ORA-22835: Buffer too small for CLOB to CHAR or BLOB to RAW conversion (actual: 57416, maximum: 4000)
你能告诉我怎么做吗?
从 12.2 版本开始你可以做:
select
json_object(
'body' value v_clob
returning clob
)
from dual;
原回答:
在回答这个问题时:
3 approach solve my problem but i don't want to run for loop . Is there is any solution in oracle to handle this .
可以使用 Oracle 的 LISTAGG
函数连接字符串而无需循环:
SELECT '{"employees":[' || LISTAGG('{"employee_id":' || to_char(employee_id)
|| ',"data_clob":"' || data_clob || '"}', ',')
WITHIN GROUP (ORDER BY employee_id) || ']}' AS json
FROM tablename;
但是,正如您在评论中指出的那样,LISTAGG
有 4000 个字符的限制。以下是更多 complex/fiddly 但应该应对超出此限制:
SELECT '{"employees":[' || dbms_xmlgen.convert(
RTRIM(XMLAGG(XMLELEMENT(E,'{"employee_id":' || to_char(employee_id)
|| ',"data_clob":"' || data_clob || '"}',',')
.EXTRACT('//text()') ORDER BY employee_id).GetClobVal(),',')
, 1) || ']}' AS json
FROM tablename;
XMLAGG
处理 CLOB
,但处理 EXTRACT
function has the side-effect of escaping certain characters (e.g. from "
to "
). The query above converts these back (e.g. from "
to "
) using the dbms_xmlgen.convert
function - see this answer 以获取更多详细信息。
SQL Fiddle 演示: http://sqlfiddle.com/#!4/5b295/40
By default the new json_* functions return a varchar2(4000). You can change this in the returning clause.
If you have extended data types enabled, you can change this to a varchar2(32767). But only the *agg functions support clob.
来自 here
SELECT length(JSON_ARRAYAGG(
JSON_OBJECT(
KEY 'object_type' VALUE object_type,
KEY 'object_name' VALUE object_name
)
returning clob)
) array_size
FROM all_objects;
ARRAY_SIZE
5772072
18c 还完全支持 JSON* 函数中的 clobs
在 12.2 中,json_* 函数可以很好地处理 clob。使用子句 Returning clob
create table t( c clob, constraint t_chk check (c is json));
declare
v_clob clob;
begin
for i in 1..10000 loop
v_clob := v_clob || 'asdasdadasdasdasdasdasdasdasd';
end loop;
insert into t(c)
select
json_object
(
'body' value v_clob returning clob
)
from
dual;
end;