如何在 Oracle (12.1) 存储过程中将 clob 的 json 数组转换为对象类型
How to convert a json array of clob into a object type in Oracle (12.1) stored procedure
我正在尝试将 json 数组转换为 json clob 并将其转换为 Oracle 存储过程中的对象类型。
下面是我在 Oracle 中的对象类型。
create or replace TYPE REPORT_OBJ FORCE as OBJECT (
id NUMBER,
name NUMBER,
createDt Date,
value NUMBER(10,2)
);
create or replace TYPE REPORT_OBJ_LIST as TABLE OF REPORT_OBJ;
这是我的 json 数组:
[{"id":1,"name":"john",:"createDt":"01-jan-2020","value":10},
{"id":2,"name":"crystal","createDt":"01-feb-2020","value":20},
{"id":3,"name":"bob","createDt":"01-mar-2020","value":30}]
这是我的存储过程,它以 report_obj_list 作为输入参数
create or replace PROCEDURE SaveUpdate_ReportsData(reportList IN REPORT_OBJ_LIST)
AS v_count number;
v_column REPORTS_DATA.id%TYPE;
updatedRecs Number;
recsCount Number;
dbid REPORTS_DATA.Id%TYPE;
dbname REPORTS_DATA.name%TYPE;
dbcreateDt REPORTS_DATA.createDt%TYPE;
dbvalue REPORTS_DATA.value%TYPE;
BEGIN
recsCount := 0;
updatedRecs := 0;
for i in reportList.first..reportList.last loop
v_column := 0;
dbid := 0;
dbname := 0;
dbcreateDt := sysdate;
dbvalue := 0;
BEGIN
SELECT DISTINCT NVL(b.repId,0) into v_column from (
(SELECT 'TEMP' as temp from REPORTS_DATA) a left join (
SELECT DISTINCT 'TEMP' AS temp, NVL(id,0) as repId FROM REPORTS_DATA
where createDt = reportList(i).createDt ) b on a.temp = b.temp);
if(v_column <= 0 ) then
INSERT INTO REPORTS_DATA (Id,name,createDt,value)
VALUES (reportList(i).Id,reportList(i).name, reportList(i).createDt,
reportList(i).value);
updatedRecs := updatedRecs+1;
else
updatedRecs := updatedRecs+1;
SELECT id,name,createDt,value INTO
dbid,dbname,dbcreateDt,dbvalue
FROM REPORTS_DATA
where createDt = reportList(i).createDt;
update REPORTS_DATA set id = NVL(reportList(i).id,dbid),
name = NVL(reportList(i).name,dbname) ,
createDt = NVL(reportList(i).createDt,dbcreateDt),
value = NVL(reportList(i).value, dbvalue);
end if;
EXCEPTION
WHEN NO_DATA_FOUND THEN
v_column := null;
DBMS_OUTPUT.PUT_LINE('hello' || v_column);
END;
end loop;
Commit;
recsCount:= updatedRecs ;
DBMS_OUTPUT.PUT_LINE('HELOOwq ' || recsCount);
end SaveUpdate_ReportsData ;
below is the oracle table
create table REPORTS_DATA(
id number,
name varchar(200),
createdt date,
value number(10,2)
);
从 java 开始,我必须将 jsonarray 转换为 clob(以便它可以接受大量数据作为存储过程的输入),并且存储过程应该接受 json clob 数组并将其转换为 'Report_obj_list',现有的存储过程将从那里正常工作。我已经编写了接受对象的存储过程,但我需要进行更改,以便它接受 clob json 数组并将其转换为存储过程中的对象。
更新存储过程
create or replace PROCEDURE SaveUpdate_ReportsData(intnum in Number)
AS v_count number;
jstr clob;
reportList report_obj_list;
v_column REPORTS_DATA.id%TYPE;
dbid REPORTS_DATA.Id%TYPE;
dbname REPORTS_DATA.name%TYPE;
dbcreateDt REPORTS_DATA.createDt%TYPE;
dbvalue REPORTS_DATA.value%TYPE;
BEGIN
jstr := to_clob('[{"id":1,"name":"john","createDt":"01-jan-2020","value":10},
{"id":2,"name":"crystal","createDt":"01-feb-2020","value":20},
{"id":3,"name":"bob","createDt":"01-mar-2020","value":30}]');
select report_obj(id, name, to_date(createdt, 'dd-mon-yyyy'), value)
bulk collect into reportList
from json_table(jstr, '$[*]'
columns( id number path '$.id',
name varchar2(20) path '$.name',
createdt varchar2(11) path '$.createDt',
value number(10, 2) path '$.value'
)
);
for i in reportList.first..reportList.last loop
DBMS_OUTPUT.PUT_LINE('name_ ' || reportList(i).name);
v_column := 0;
dbid := 0;
dbname := 0;
dbcreateDt := sysdate;
dbvalue := 0;
BEGIN
SELECT DISTINCT NVL(b.repId,0) into v_column from (
(SELECT 'TEMP' as temp from REPORTS_DATA) a left join (
SELECT DISTINCT 'TEMP' AS temp, NVL(id,0) as repId FROM REPORTS_DATA
where createDt = reportList(i).createDt ) b on a.temp = b.temp);
if(v_column <= 0 ) then
INSERT INTO REPORTS_DATA (Id,name,createDt,value)
VALUES (reportList(i).Id,reportList(i).name, reportList(i).createDt,
reportList(i).value);
else
SELECT id,name,createDt,value INTO
dbid,dbname,dbcreateDt,dbvalue
FROM REPORTS_DATA
where createDt = reportList(i).createDt;
update REPORTS_DATA set id = NVL(reportList(i).id,dbid),
name = NVL(reportList(i).name,dbname) ,
createDt = NVL(reportList(i).createDt,dbcreateDt),
value = NVL(reportList(i).value, dbvalue);
end if;
EXCEPTION
WHEN NO_DATA_FOUND THEN
v_column := null;
END;
end loop;
Commit;
end SaveUpdate_ReportsData ;
我调用存储过程如下:
DECLARE
BEGIN
SaveUpdate_ReportsData(
12
);
END;
/
它没有抛出任何类型的错误,但同时它没有将数据插入 REPORTS_DATA table 甚至没有打印名称。
帮我解决问题
提前致谢。
以下是如何从 JSON(CLOB 数据类型)中提取数据并将其传递给用户定义类型的对象集合(嵌套 table),就像您一样有。 PL/SQL 代码用于接受 CLOB(假设有效 JSON)和 return 对象的嵌套 table 的函数。 (然后我展示了一个调用SQL中的函数的例子,看看里面保存了什么。)
不确定将 JSON 数组转换为 CLOB 是什么意思。就Oracle而言,JSON是一个CLOB。
无论如何 - 这是函数:
create or replace type report_obj force as object (
id number,
name_ varchar2(20),
createdt date,
value_ number(10,2)
);
/
create or replace type report_obj_list as table of report_obj;
/
create or replace function json_to_obj_list (jstr clob)
return report_obj_list
as
lst report_obj_list;
begin
select report_obj(id, name_, to_date(createdt, 'dd-mon-yyyy'), value_)
bulk collect into lst
from json_table(jstr, '$[*]'
columns( id number path '$.id',
name_ varchar2(20) path '$.name',
createdt varchar2(11) path '$.createDt',
value_ number(10, 2) path '$.value'
)
);
return lst;
end;
/
(如您所见,我更改了您的对象类型定义 - 我将属性名称 name
和 value
更改为 name_
和 value_
,因为 name
和 value
是 Oracle 关键字,因此不应将它们用作标识符。)
这是它的工作原理。请注意,我将显式 CLOB 传递给函数。更有可能的是,您希望将 CLOB 存储在某处(table?)并从那里传递它们。那部分比较琐碎。
select * from json_to_obj_list(
to_clob(
'[{"id":1,"name":"john","createDt":"01-jan-2020","value":10},
{"id":2,"name":"crystal","createDt":"01-feb-2020","value":20},
{"id":3,"name":"bob","createDt":"01-mar-2020","value":30}]')
);
ID NAME_ CREATEDT VALUE_
---------- -------------------- ----------- ----------
1 john 01-jan-2020 10
2 crystal 01-feb-2020 20
3 bob 01-mar-2020 30
注意createdt
实际上是date
数据类型;在输出中它看起来像你的输入只是因为我故意设置我的 nls_date_format
来匹配它。否则,您的查询将 return 该列中的日期采用会话的默认格式。
我正在尝试将 json 数组转换为 json clob 并将其转换为 Oracle 存储过程中的对象类型。
下面是我在 Oracle 中的对象类型。
create or replace TYPE REPORT_OBJ FORCE as OBJECT (
id NUMBER,
name NUMBER,
createDt Date,
value NUMBER(10,2)
);
create or replace TYPE REPORT_OBJ_LIST as TABLE OF REPORT_OBJ;
这是我的 json 数组:
[{"id":1,"name":"john",:"createDt":"01-jan-2020","value":10},
{"id":2,"name":"crystal","createDt":"01-feb-2020","value":20},
{"id":3,"name":"bob","createDt":"01-mar-2020","value":30}]
这是我的存储过程,它以 report_obj_list 作为输入参数
create or replace PROCEDURE SaveUpdate_ReportsData(reportList IN REPORT_OBJ_LIST)
AS v_count number;
v_column REPORTS_DATA.id%TYPE;
updatedRecs Number;
recsCount Number;
dbid REPORTS_DATA.Id%TYPE;
dbname REPORTS_DATA.name%TYPE;
dbcreateDt REPORTS_DATA.createDt%TYPE;
dbvalue REPORTS_DATA.value%TYPE;
BEGIN
recsCount := 0;
updatedRecs := 0;
for i in reportList.first..reportList.last loop
v_column := 0;
dbid := 0;
dbname := 0;
dbcreateDt := sysdate;
dbvalue := 0;
BEGIN
SELECT DISTINCT NVL(b.repId,0) into v_column from (
(SELECT 'TEMP' as temp from REPORTS_DATA) a left join (
SELECT DISTINCT 'TEMP' AS temp, NVL(id,0) as repId FROM REPORTS_DATA
where createDt = reportList(i).createDt ) b on a.temp = b.temp);
if(v_column <= 0 ) then
INSERT INTO REPORTS_DATA (Id,name,createDt,value)
VALUES (reportList(i).Id,reportList(i).name, reportList(i).createDt,
reportList(i).value);
updatedRecs := updatedRecs+1;
else
updatedRecs := updatedRecs+1;
SELECT id,name,createDt,value INTO
dbid,dbname,dbcreateDt,dbvalue
FROM REPORTS_DATA
where createDt = reportList(i).createDt;
update REPORTS_DATA set id = NVL(reportList(i).id,dbid),
name = NVL(reportList(i).name,dbname) ,
createDt = NVL(reportList(i).createDt,dbcreateDt),
value = NVL(reportList(i).value, dbvalue);
end if;
EXCEPTION
WHEN NO_DATA_FOUND THEN
v_column := null;
DBMS_OUTPUT.PUT_LINE('hello' || v_column);
END;
end loop;
Commit;
recsCount:= updatedRecs ;
DBMS_OUTPUT.PUT_LINE('HELOOwq ' || recsCount);
end SaveUpdate_ReportsData ;
below is the oracle table
create table REPORTS_DATA(
id number,
name varchar(200),
createdt date,
value number(10,2)
);
从 java 开始,我必须将 jsonarray 转换为 clob(以便它可以接受大量数据作为存储过程的输入),并且存储过程应该接受 json clob 数组并将其转换为 'Report_obj_list',现有的存储过程将从那里正常工作。我已经编写了接受对象的存储过程,但我需要进行更改,以便它接受 clob json 数组并将其转换为存储过程中的对象。
更新存储过程
create or replace PROCEDURE SaveUpdate_ReportsData(intnum in Number)
AS v_count number;
jstr clob;
reportList report_obj_list;
v_column REPORTS_DATA.id%TYPE;
dbid REPORTS_DATA.Id%TYPE;
dbname REPORTS_DATA.name%TYPE;
dbcreateDt REPORTS_DATA.createDt%TYPE;
dbvalue REPORTS_DATA.value%TYPE;
BEGIN
jstr := to_clob('[{"id":1,"name":"john","createDt":"01-jan-2020","value":10},
{"id":2,"name":"crystal","createDt":"01-feb-2020","value":20},
{"id":3,"name":"bob","createDt":"01-mar-2020","value":30}]');
select report_obj(id, name, to_date(createdt, 'dd-mon-yyyy'), value)
bulk collect into reportList
from json_table(jstr, '$[*]'
columns( id number path '$.id',
name varchar2(20) path '$.name',
createdt varchar2(11) path '$.createDt',
value number(10, 2) path '$.value'
)
);
for i in reportList.first..reportList.last loop
DBMS_OUTPUT.PUT_LINE('name_ ' || reportList(i).name);
v_column := 0;
dbid := 0;
dbname := 0;
dbcreateDt := sysdate;
dbvalue := 0;
BEGIN
SELECT DISTINCT NVL(b.repId,0) into v_column from (
(SELECT 'TEMP' as temp from REPORTS_DATA) a left join (
SELECT DISTINCT 'TEMP' AS temp, NVL(id,0) as repId FROM REPORTS_DATA
where createDt = reportList(i).createDt ) b on a.temp = b.temp);
if(v_column <= 0 ) then
INSERT INTO REPORTS_DATA (Id,name,createDt,value)
VALUES (reportList(i).Id,reportList(i).name, reportList(i).createDt,
reportList(i).value);
else
SELECT id,name,createDt,value INTO
dbid,dbname,dbcreateDt,dbvalue
FROM REPORTS_DATA
where createDt = reportList(i).createDt;
update REPORTS_DATA set id = NVL(reportList(i).id,dbid),
name = NVL(reportList(i).name,dbname) ,
createDt = NVL(reportList(i).createDt,dbcreateDt),
value = NVL(reportList(i).value, dbvalue);
end if;
EXCEPTION
WHEN NO_DATA_FOUND THEN
v_column := null;
END;
end loop;
Commit;
end SaveUpdate_ReportsData ;
我调用存储过程如下:
DECLARE
BEGIN
SaveUpdate_ReportsData(
12
);
END;
/
它没有抛出任何类型的错误,但同时它没有将数据插入 REPORTS_DATA table 甚至没有打印名称。
帮我解决问题
提前致谢。
以下是如何从 JSON(CLOB 数据类型)中提取数据并将其传递给用户定义类型的对象集合(嵌套 table),就像您一样有。 PL/SQL 代码用于接受 CLOB(假设有效 JSON)和 return 对象的嵌套 table 的函数。 (然后我展示了一个调用SQL中的函数的例子,看看里面保存了什么。)
不确定将 JSON 数组转换为 CLOB 是什么意思。就Oracle而言,JSON是一个CLOB。
无论如何 - 这是函数:
create or replace type report_obj force as object (
id number,
name_ varchar2(20),
createdt date,
value_ number(10,2)
);
/
create or replace type report_obj_list as table of report_obj;
/
create or replace function json_to_obj_list (jstr clob)
return report_obj_list
as
lst report_obj_list;
begin
select report_obj(id, name_, to_date(createdt, 'dd-mon-yyyy'), value_)
bulk collect into lst
from json_table(jstr, '$[*]'
columns( id number path '$.id',
name_ varchar2(20) path '$.name',
createdt varchar2(11) path '$.createDt',
value_ number(10, 2) path '$.value'
)
);
return lst;
end;
/
(如您所见,我更改了您的对象类型定义 - 我将属性名称 name
和 value
更改为 name_
和 value_
,因为 name
和 value
是 Oracle 关键字,因此不应将它们用作标识符。)
这是它的工作原理。请注意,我将显式 CLOB 传递给函数。更有可能的是,您希望将 CLOB 存储在某处(table?)并从那里传递它们。那部分比较琐碎。
select * from json_to_obj_list(
to_clob(
'[{"id":1,"name":"john","createDt":"01-jan-2020","value":10},
{"id":2,"name":"crystal","createDt":"01-feb-2020","value":20},
{"id":3,"name":"bob","createDt":"01-mar-2020","value":30}]')
);
ID NAME_ CREATEDT VALUE_
---------- -------------------- ----------- ----------
1 john 01-jan-2020 10
2 crystal 01-feb-2020 20
3 bob 01-mar-2020 30
注意createdt
实际上是date
数据类型;在输出中它看起来像你的输入只是因为我故意设置我的 nls_date_format
来匹配它。否则,您的查询将 return 该列中的日期采用会话的默认格式。