如何将 49.000 个字符长的 json 字符串处理成 pl/sql 中的 clob
How to process a 49.000 character-long json-string into a clob in pl/sql
我有一个很长的 json-String,超过 49k 个字符,所以它不适合放在 clob 中。
我有一个将 json-String 作为 clob 输入的过程。在那里我想读出所有值并将它们插入我的 table。如果我将 json-String 变小以测试一切正常。但正如我所说,json-String 的长度超过 49k 个字符。
我的程序的头部是这样的:
PROCEDURE set_FDC_Data(in_json IN CLOB) IS
v_json elmos_opt.json;
v_json_keys elmos_opt.json_list;
v_json_else_obj elmos_opt.json;
v_elseNr VARCHAR(10);
v_pce VARCHAR(10);
v_channel1 elmos_opt.json;
v_protocolCh1 VARCHAR(10);
v_portCh1 NUMBER;
v_deviceIdCh1 NUMBER;
v_t3Ch1 NUMBER;
v_t1Ch1 NUMBER;
v_t2Ch1 NUMBER;
v_t4Ch1 NUMBER;
v_t5Ch1 NUMBER;
v_t6Ch1 NUMBER;
v_t7Ch1 NUMBER;
v_t8Ch1 NUMBER;
v_channel2 elmos_opt.json;
v_remoteHostCh2 VARCHAR(50);
v_protocolCh2 VARCHAR(10);
v_portCh2 NUMBER;
v_deviceIdCh2 NUMBER;
v_t3Ch2 NUMBER;
v_t1Ch2 NUMBER;
v_t2Ch2 NUMBER;
v_t4Ch2 NUMBER;
v_t5Ch2 NUMBER;
v_t6Ch2 NUMBER;
v_t7Ch2 NUMBER;
v_t8Ch2 NUMBER;
v_channel3 elmos_opt.json;
v_deviceIdCh3 NUMBER;
v_t3Ch3 NUMBER;
v_t1Ch3 NUMBER;
v_t2Ch3 NUMBER;
v_t4Ch3 NUMBER;
v_t5Ch3 NUMBER;
v_t6Ch3 NUMBER;
v_t7Ch3 NUMBER;
v_t8Ch3 NUMBER;
v_channel4 elmos_opt.json;
v_deviceIdCh4 NUMBER;
v_t3Ch4 NUMBER;
v_t1Ch4 NUMBER;
v_t2Ch4 NUMBER;
v_t4Ch4 NUMBER;
v_t5Ch4 NUMBER;
v_t6Ch4 NUMBER;
v_t7Ch4 NUMBER;
v_t8Ch4 NUMBER;
v_deviceIdHost NUMBER;
v_deviceIdEqp NUMBER;
v_deviceIdEqpBis NUMBER;
BEGIN
v_json := elmos_opt.json(in_json);
v_json_keys := v_json.get_keys();
FOR i IN 1 .. v_json_keys.count LOOP
v_elseNr := v_json_keys.get(i).get_string;
v_json_else_obj := elmos_opt.json(v_json.get(v_elseNr));
v_pce := v_json_else_obj.get('PCE').get_string;
v_channel1 := elmos_opt.json(v_json_else_obj.get('CHANNEL1'));
v_protocolCh1 := v_channel1.get('PROTOCOL').get_string;
v_portCh1 := v_channel1.get('PORT').get_number;
v_deviceIdCh1 := v_channel1.get('DEVICE_ID').get_number;
v_t3Ch1 := v_channel1.get('T3_TIMEOUT').get_number;
v_t1Ch1 := v_channel1.get('T1_TIMEOUT').get_number;
v_t2Ch1 := v_channel1.get('T2_TIMEOUT').get_number;
v_t4Ch1 := v_channel1.get('T4_TIMEOUT').get_number;
v_t5Ch1 := v_channel1.get('T5_TIMEOUT').get_number;
v_t6Ch1 := v_channel1.get('T6_TIMEOUT').get_number;
v_t7Ch1 := v_channel1.get('T7_TIMEOUT').get_number;
v_t8Ch1 := v_channel1.get('T8_TIMEOUT').get_number;
v_channel2 := elmos_opt.json(v_json_else_obj.get('CHANNEL2'));
v_remoteHostCh2 := v_channel2.get('REMOTE_HOST').get_string;
v_protocolCh2 := v_channel2.get('PROTOCOL').get_string;
v_portCh2 := v_channel2.get('PORT').get_number;
v_deviceIdCh2 := v_channel2.get('DEVICE_ID').get_number;
v_t3Ch2 := v_channel2.get('T3_TIMEOUT').get_number;
v_t1Ch2 := v_channel2.get('T1_TIMEOUT').get_number;
v_t2Ch2 := v_channel2.get('T2_TIMEOUT').get_number;
v_t4Ch2 := v_channel2.get('T4_TIMEOUT').get_number;
v_t5Ch2 := v_channel2.get('T5_TIMEOUT').get_number;
v_t6Ch2 := v_channel2.get('T6_TIMEOUT').get_number;
v_t7Ch2 := v_channel2.get('T7_TIMEOUT').get_number;
v_t8Ch2 := v_channel2.get('T8_TIMEOUT').get_number;
v_channel3 := elmos_opt.json(v_json_else_obj.get('CHANNEL3'));
v_deviceIdCh3 := v_channel3.get('DEVICE_ID').get_number;
v_t3Ch3 := v_channel3.get('T3_TIMEOUT').get_number;
v_t1Ch3 := v_channel3.get('T1_TIMEOUT').get_number;
v_t2Ch3 := v_channel3.get('T2_TIMEOUT').get_number;
v_t4Ch3 := v_channel3.get('T4_TIMEOUT').get_number;
v_t5Ch3 := v_channel3.get('T5_TIMEOUT').get_number;
v_t6Ch3 := v_channel3.get('T6_TIMEOUT').get_number;
v_t7Ch3 := v_channel3.get('T7_TIMEOUT').get_number;
v_t8Ch3 := v_channel3.get('T8_TIMEOUT').get_number;
v_channel4 := elmos_opt.json(v_json_else_obj.get('CHANNEL4'));
v_deviceIdCh4 := v_channel4.get('DEVICE_ID').get_number;
v_t3Ch4 := v_channel4.get('T3_TIMEOUT').get_number;
v_t1Ch4 := v_channel4.get('T1_TIMEOUT').get_number;
v_t2Ch4 := v_channel4.get('T2_TIMEOUT').get_number;
v_t4Ch4 := v_channel4.get('T4_TIMEOUT').get_number;
v_t5Ch4 := v_channel4.get('T5_TIMEOUT').get_number;
v_t6Ch4 := v_channel4.get('T6_TIMEOUT').get_number;
v_t7Ch4 := v_channel4.get('T7_TIMEOUT').get_number;
v_t8Ch4 := v_channel4.get('T8_TIMEOUT').get_number;
v_deviceIdHost := v_json_else_obj.get('DEVICE_ID_HOST').get_number;
v_deviceIdEqp := v_json_else_obj.get('DEVICE_ID_EQP').get_number;
IF v_json_else_obj.exist('DEVICE_ID_EQP_BIS') THEN
v_deviceIdEqpBis := v_json_else_obj.get('DEVICE_ID_EQP_BIS').get_number;
END IF;
END LOOP;
END setFDC_DATA;
有一个 post 建议将 clob 分成块,但是如果 clob 是输入参数怎么办?我该如何在过程中进行?
我得到的错误是:
PLS-00172: string literal too long
此错误是在 运行 我的测试脚本测试我的程序后抛出的:
declare
in_json clob;
begin
-- Call the procedure
in_json := 'very long json String';
EA_JAMIE.set_FDC_Data(in_json => in_json);
end;
如何将我的输入 json 分成块?我从来没有使用过 clobs,也许我为这个错误找到的答案也适用于我的案例,但我不知道如何。 PL/SQL 对我来说也是一个相当新鲜的东西。
您得到的错误是您的文字太长了。文字只能包含 4000 个字符。此处的字面意思是您在调用过程之前设置 in_json 的值。你不能有这个:
in_json := 'some text that is longer than 4000 characters';
请参阅有关文字(和其他字段)最大长度的 Oracle 文档 here。
您可以通过将文字的小块附加到 CLOB 中然后将其传递到您的过程中来作弊。这是一个愚蠢的例子。您可以将 49k 字符 JSON 切成 4k 字符块,可能使用 NP++ 或某些文本编辑器每 4000 个字符插入一个换行符,然后为每个块创建一个变量,然后将它们附加在一起。您甚至可以放弃变量并将文字直接放入 to_clob() 中,但这会使这个 hack 变得更糟(看看)。
DECLARE
v_s1 VARCHAR2(4000) := lpad('x',
4000,
'x');
v_s2 VARCHAR2(4000) := lpad('x',
4000,
'x');
v_s3 VARCHAR2(4000) := lpad('x',
4000,
'x');
v_clob CLOB;
BEGIN
dbms_lob.createtemporary(lob_loc => v_clob,
cache => FALSE);
dbms_lob.append(dest_lob => v_clob,
src_lob => to_clob(v_s1));
dbms_lob.append(dest_lob => v_clob,
src_lob => to_clob(v_s2));
dbms_lob.append(dest_lob => v_clob,
src_lob => to_clob(v_s3));
dbms_output.put_line(dbms_lob.getlength(lob_loc => v_clob));
END;
/
我假设(希望)您将此作为单元测试进行,并且 in_json 最终会来自其他地方。
编辑:您可能还想将 CLOB 作为 IN OUT NOCOPY 传递,而不仅仅是 IN。这将导致(希望)PL/SQL 通过引用传递值,而不是通过值复制数据以节省内存和程序开销。您可以在 Oracle 文档中阅读有关 NOCOPY 的详细信息,因为存在可以忽略的例外情况。
PROCEDURE set_FDC_Data(in_json IN OUT NOCOPY CLOB) IS
我有一个很长的 json-String,超过 49k 个字符,所以它不适合放在 clob 中。 我有一个将 json-String 作为 clob 输入的过程。在那里我想读出所有值并将它们插入我的 table。如果我将 json-String 变小以测试一切正常。但正如我所说,json-String 的长度超过 49k 个字符。
我的程序的头部是这样的:
PROCEDURE set_FDC_Data(in_json IN CLOB) IS
v_json elmos_opt.json;
v_json_keys elmos_opt.json_list;
v_json_else_obj elmos_opt.json;
v_elseNr VARCHAR(10);
v_pce VARCHAR(10);
v_channel1 elmos_opt.json;
v_protocolCh1 VARCHAR(10);
v_portCh1 NUMBER;
v_deviceIdCh1 NUMBER;
v_t3Ch1 NUMBER;
v_t1Ch1 NUMBER;
v_t2Ch1 NUMBER;
v_t4Ch1 NUMBER;
v_t5Ch1 NUMBER;
v_t6Ch1 NUMBER;
v_t7Ch1 NUMBER;
v_t8Ch1 NUMBER;
v_channel2 elmos_opt.json;
v_remoteHostCh2 VARCHAR(50);
v_protocolCh2 VARCHAR(10);
v_portCh2 NUMBER;
v_deviceIdCh2 NUMBER;
v_t3Ch2 NUMBER;
v_t1Ch2 NUMBER;
v_t2Ch2 NUMBER;
v_t4Ch2 NUMBER;
v_t5Ch2 NUMBER;
v_t6Ch2 NUMBER;
v_t7Ch2 NUMBER;
v_t8Ch2 NUMBER;
v_channel3 elmos_opt.json;
v_deviceIdCh3 NUMBER;
v_t3Ch3 NUMBER;
v_t1Ch3 NUMBER;
v_t2Ch3 NUMBER;
v_t4Ch3 NUMBER;
v_t5Ch3 NUMBER;
v_t6Ch3 NUMBER;
v_t7Ch3 NUMBER;
v_t8Ch3 NUMBER;
v_channel4 elmos_opt.json;
v_deviceIdCh4 NUMBER;
v_t3Ch4 NUMBER;
v_t1Ch4 NUMBER;
v_t2Ch4 NUMBER;
v_t4Ch4 NUMBER;
v_t5Ch4 NUMBER;
v_t6Ch4 NUMBER;
v_t7Ch4 NUMBER;
v_t8Ch4 NUMBER;
v_deviceIdHost NUMBER;
v_deviceIdEqp NUMBER;
v_deviceIdEqpBis NUMBER;
BEGIN
v_json := elmos_opt.json(in_json);
v_json_keys := v_json.get_keys();
FOR i IN 1 .. v_json_keys.count LOOP
v_elseNr := v_json_keys.get(i).get_string;
v_json_else_obj := elmos_opt.json(v_json.get(v_elseNr));
v_pce := v_json_else_obj.get('PCE').get_string;
v_channel1 := elmos_opt.json(v_json_else_obj.get('CHANNEL1'));
v_protocolCh1 := v_channel1.get('PROTOCOL').get_string;
v_portCh1 := v_channel1.get('PORT').get_number;
v_deviceIdCh1 := v_channel1.get('DEVICE_ID').get_number;
v_t3Ch1 := v_channel1.get('T3_TIMEOUT').get_number;
v_t1Ch1 := v_channel1.get('T1_TIMEOUT').get_number;
v_t2Ch1 := v_channel1.get('T2_TIMEOUT').get_number;
v_t4Ch1 := v_channel1.get('T4_TIMEOUT').get_number;
v_t5Ch1 := v_channel1.get('T5_TIMEOUT').get_number;
v_t6Ch1 := v_channel1.get('T6_TIMEOUT').get_number;
v_t7Ch1 := v_channel1.get('T7_TIMEOUT').get_number;
v_t8Ch1 := v_channel1.get('T8_TIMEOUT').get_number;
v_channel2 := elmos_opt.json(v_json_else_obj.get('CHANNEL2'));
v_remoteHostCh2 := v_channel2.get('REMOTE_HOST').get_string;
v_protocolCh2 := v_channel2.get('PROTOCOL').get_string;
v_portCh2 := v_channel2.get('PORT').get_number;
v_deviceIdCh2 := v_channel2.get('DEVICE_ID').get_number;
v_t3Ch2 := v_channel2.get('T3_TIMEOUT').get_number;
v_t1Ch2 := v_channel2.get('T1_TIMEOUT').get_number;
v_t2Ch2 := v_channel2.get('T2_TIMEOUT').get_number;
v_t4Ch2 := v_channel2.get('T4_TIMEOUT').get_number;
v_t5Ch2 := v_channel2.get('T5_TIMEOUT').get_number;
v_t6Ch2 := v_channel2.get('T6_TIMEOUT').get_number;
v_t7Ch2 := v_channel2.get('T7_TIMEOUT').get_number;
v_t8Ch2 := v_channel2.get('T8_TIMEOUT').get_number;
v_channel3 := elmos_opt.json(v_json_else_obj.get('CHANNEL3'));
v_deviceIdCh3 := v_channel3.get('DEVICE_ID').get_number;
v_t3Ch3 := v_channel3.get('T3_TIMEOUT').get_number;
v_t1Ch3 := v_channel3.get('T1_TIMEOUT').get_number;
v_t2Ch3 := v_channel3.get('T2_TIMEOUT').get_number;
v_t4Ch3 := v_channel3.get('T4_TIMEOUT').get_number;
v_t5Ch3 := v_channel3.get('T5_TIMEOUT').get_number;
v_t6Ch3 := v_channel3.get('T6_TIMEOUT').get_number;
v_t7Ch3 := v_channel3.get('T7_TIMEOUT').get_number;
v_t8Ch3 := v_channel3.get('T8_TIMEOUT').get_number;
v_channel4 := elmos_opt.json(v_json_else_obj.get('CHANNEL4'));
v_deviceIdCh4 := v_channel4.get('DEVICE_ID').get_number;
v_t3Ch4 := v_channel4.get('T3_TIMEOUT').get_number;
v_t1Ch4 := v_channel4.get('T1_TIMEOUT').get_number;
v_t2Ch4 := v_channel4.get('T2_TIMEOUT').get_number;
v_t4Ch4 := v_channel4.get('T4_TIMEOUT').get_number;
v_t5Ch4 := v_channel4.get('T5_TIMEOUT').get_number;
v_t6Ch4 := v_channel4.get('T6_TIMEOUT').get_number;
v_t7Ch4 := v_channel4.get('T7_TIMEOUT').get_number;
v_t8Ch4 := v_channel4.get('T8_TIMEOUT').get_number;
v_deviceIdHost := v_json_else_obj.get('DEVICE_ID_HOST').get_number;
v_deviceIdEqp := v_json_else_obj.get('DEVICE_ID_EQP').get_number;
IF v_json_else_obj.exist('DEVICE_ID_EQP_BIS') THEN
v_deviceIdEqpBis := v_json_else_obj.get('DEVICE_ID_EQP_BIS').get_number;
END IF;
END LOOP;
END setFDC_DATA;
有一个 post 建议将 clob 分成块,但是如果 clob 是输入参数怎么办?我该如何在过程中进行?
我得到的错误是:
PLS-00172: string literal too long
此错误是在 运行 我的测试脚本测试我的程序后抛出的:
declare
in_json clob;
begin
-- Call the procedure
in_json := 'very long json String';
EA_JAMIE.set_FDC_Data(in_json => in_json);
end;
如何将我的输入 json 分成块?我从来没有使用过 clobs,也许我为这个错误找到的答案也适用于我的案例,但我不知道如何。 PL/SQL 对我来说也是一个相当新鲜的东西。
您得到的错误是您的文字太长了。文字只能包含 4000 个字符。此处的字面意思是您在调用过程之前设置 in_json 的值。你不能有这个:
in_json := 'some text that is longer than 4000 characters';
请参阅有关文字(和其他字段)最大长度的 Oracle 文档 here。
您可以通过将文字的小块附加到 CLOB 中然后将其传递到您的过程中来作弊。这是一个愚蠢的例子。您可以将 49k 字符 JSON 切成 4k 字符块,可能使用 NP++ 或某些文本编辑器每 4000 个字符插入一个换行符,然后为每个块创建一个变量,然后将它们附加在一起。您甚至可以放弃变量并将文字直接放入 to_clob() 中,但这会使这个 hack 变得更糟(看看)。
DECLARE
v_s1 VARCHAR2(4000) := lpad('x',
4000,
'x');
v_s2 VARCHAR2(4000) := lpad('x',
4000,
'x');
v_s3 VARCHAR2(4000) := lpad('x',
4000,
'x');
v_clob CLOB;
BEGIN
dbms_lob.createtemporary(lob_loc => v_clob,
cache => FALSE);
dbms_lob.append(dest_lob => v_clob,
src_lob => to_clob(v_s1));
dbms_lob.append(dest_lob => v_clob,
src_lob => to_clob(v_s2));
dbms_lob.append(dest_lob => v_clob,
src_lob => to_clob(v_s3));
dbms_output.put_line(dbms_lob.getlength(lob_loc => v_clob));
END;
/
我假设(希望)您将此作为单元测试进行,并且 in_json 最终会来自其他地方。
编辑:您可能还想将 CLOB 作为 IN OUT NOCOPY 传递,而不仅仅是 IN。这将导致(希望)PL/SQL 通过引用传递值,而不是通过值复制数据以节省内存和程序开销。您可以在 Oracle 文档中阅读有关 NOCOPY 的详细信息,因为存在可以忽略的例外情况。
PROCEDURE set_FDC_Data(in_json IN OUT NOCOPY CLOB) IS