可以立即执行与 JSON_TABLE 一起使用
Can execute immediate be used with JSON_TABLE
我需要将 JSON 转换为 Oracle 12c v12.1.0.2
中的数据 table(键值列)
所以例如有一个 JSON 字符串像
{"ID": 10, "Description": "TestJSON", "status":"New"}
我需要将其转换为:
Column1 Column2
------------------------------------
ID 10
Description TestJSON
status New
现在我的 JSON 字符串可以更改属性的数量,因此我需要保持转换动态。
我尝试使用立即执行:
set serveroutput on;
declare
sqlsmt VARCHAR2(200);
t3 varchar2(50);
begin
sqlsmt := 'SELECT * '||
'FROM json_table( ( select jsonstr from mytable where ID= 10) , ''$[*]'' '||
'COLUMNS ( :t1 PATH ''$.''|| '':t2'' ))';
execute immediate sqlsmt into t3 using 'desc' , '$.Description' ;
DBMS_OUTPUT.PUT_LINE( 'Output Variable: ' || t3);
END;
但是,我收到以下错误:
ORA-00904: : invalid identifier
ORA-06512: at line 8
00904. 00000 - "%s: invalid identifier"
请帮忙。我有 Oracle 12c V1。但我真的需要从 JSON.
动态拉取列
有几件事可以帮助动态 SQL(假设您确实需要使用它)。第一种是在尝试执行之前使用 dbms_output
显示生成的语句;所以在你的情况下:
...
dbms_output.put_line(sqlsmt);
execute immediate sqlsmt into t3;
--using 'descr' , '$.Description' ;
DBMS_OUTPUT.PUT_LINE( 'Output Variable: ' || t3);
END;
/
您的代码显示:
SELECT * FROM json_table( ( select jsonstr from mytable where ID= 10) , '$[*]' COLUMNS ( :t1 PATH '$.'|| ':t2' ))
最明显的问题出现在 '$.'|| ':t2'
中,其中 :t2
不应包含在引号中;这不会导致错误,但会阻止它像您期望的那样绑定到您的变量,因为它是一个文字值。您在那个位和您的变量值中也有 $.
部分,但同样没有那么远。
与所有动态 SQL 一样,您只能为 using
子句中的变量提供值。您试图将列名作为绑定变量传递,这是不允许的;所以它试图使用 :t1
作为输出列名,而不是 desc
; :t1
不是有效名称。 (desc
也不是,因为那是一个保留字 - 但要么得到相同的错误。)因此,您必须连接列名而不是绑定它。
看起来您可以使用 :t2
作为路径;但是你也不能那样做,不是作为动态 SQL 限制,而是作为 SQL/JSON 限制 - 如果你做到这一点,使用有效的变量值,你仍然会得到 "ORA-40454: path expression not a literal".您也必须将路径连接到语句中。
最后 $[*]
不允许您匹配 Description
... 这导致了关于动态 SQL 的第二个提示;首先让静态查询正常工作,然后使其动态化。
所以把它们放在一起,你可以这样做:
declare
sqlsmt varchar2(200);
t1 varchar2(30) := 'descr';
t2 varchar2(30) := 'Description';
t3 varchar2(50);
begin
sqlsmt := 'SELECT * '||
'FROM json_table( ( select jsonstr from mytable where ID= 10) , ''$'' '||
'COLUMNS ( ' || t1 || ' PATH ''$.' || t2 || '''))';
dbms_output.put_line(sqlsmt);
execute immediate sqlsmt into t3;
dbms_output.put_line( 'Output Variable: ' || t3);
end;
/
您的示例数据输出:
SELECT * FROM json_table( ( select jsonstr from mytable where ID= 10) , '$' COLUMNS ( descr PATH '$.Description'))
Output Variable: TestJSON
唯一允许作为变量传递的东西 10 是硬编码的,这有点奇怪。但我知道这是一个实验。
您也可以将语句写成:
select j.*
from mytable t
cross join json_table ( t.jsonstr, '$' columns ( descr path '$.Description' )) j
where t.id = 10;
你可以动态地做:
declare
sqlsmt varchar2(200);
id number := 10;
t1 varchar2(30) := 'descr';
t2 varchar2(30) := 'Description';
t3 varchar2(50);
begin
sqlsmt := 'select j.*'
|| ' from mytable t'
|| q'^ cross join json_table ( t.jsonstr, '$' columns ( ^'
|| t1
|| q'^ path '$.^'
|| t2
|| q'^' )) j^'
|| ' where t.id = :id';
dbms_output.put_line(sqlsmt);
execute immediate sqlsmt into t3 using id;
dbms_output.put_line( 'Output Variable: ' || t3);
end;
/
我已经使用 the alternative quoting mechanism 来避免在语句中将引号加倍,但这是可选的。使用相同的数据输出:
select j.* from mytable t cross join json_table ( t.jsonstr, '$' columns ( descr path '$.Description' )) j where t.id = :id
Output Variable: TestJSON
我需要将 JSON 转换为 Oracle 12c v12.1.0.2
中的数据 table(键值列)所以例如有一个 JSON 字符串像
{"ID": 10, "Description": "TestJSON", "status":"New"}
我需要将其转换为:
Column1 Column2
------------------------------------
ID 10
Description TestJSON
status New
现在我的 JSON 字符串可以更改属性的数量,因此我需要保持转换动态。
我尝试使用立即执行:
set serveroutput on;
declare
sqlsmt VARCHAR2(200);
t3 varchar2(50);
begin
sqlsmt := 'SELECT * '||
'FROM json_table( ( select jsonstr from mytable where ID= 10) , ''$[*]'' '||
'COLUMNS ( :t1 PATH ''$.''|| '':t2'' ))';
execute immediate sqlsmt into t3 using 'desc' , '$.Description' ;
DBMS_OUTPUT.PUT_LINE( 'Output Variable: ' || t3);
END;
但是,我收到以下错误:
ORA-00904: : invalid identifier
ORA-06512: at line 8
00904. 00000 - "%s: invalid identifier"
请帮忙。我有 Oracle 12c V1。但我真的需要从 JSON.
动态拉取列有几件事可以帮助动态 SQL(假设您确实需要使用它)。第一种是在尝试执行之前使用 dbms_output
显示生成的语句;所以在你的情况下:
...
dbms_output.put_line(sqlsmt);
execute immediate sqlsmt into t3;
--using 'descr' , '$.Description' ;
DBMS_OUTPUT.PUT_LINE( 'Output Variable: ' || t3);
END;
/
您的代码显示:
SELECT * FROM json_table( ( select jsonstr from mytable where ID= 10) , '$[*]' COLUMNS ( :t1 PATH '$.'|| ':t2' ))
最明显的问题出现在 '$.'|| ':t2'
中,其中 :t2
不应包含在引号中;这不会导致错误,但会阻止它像您期望的那样绑定到您的变量,因为它是一个文字值。您在那个位和您的变量值中也有 $.
部分,但同样没有那么远。
与所有动态 SQL 一样,您只能为 using
子句中的变量提供值。您试图将列名作为绑定变量传递,这是不允许的;所以它试图使用 :t1
作为输出列名,而不是 desc
; :t1
不是有效名称。 (desc
也不是,因为那是一个保留字 - 但要么得到相同的错误。)因此,您必须连接列名而不是绑定它。
看起来您可以使用 :t2
作为路径;但是你也不能那样做,不是作为动态 SQL 限制,而是作为 SQL/JSON 限制 - 如果你做到这一点,使用有效的变量值,你仍然会得到 "ORA-40454: path expression not a literal".您也必须将路径连接到语句中。
最后 $[*]
不允许您匹配 Description
... 这导致了关于动态 SQL 的第二个提示;首先让静态查询正常工作,然后使其动态化。
所以把它们放在一起,你可以这样做:
declare
sqlsmt varchar2(200);
t1 varchar2(30) := 'descr';
t2 varchar2(30) := 'Description';
t3 varchar2(50);
begin
sqlsmt := 'SELECT * '||
'FROM json_table( ( select jsonstr from mytable where ID= 10) , ''$'' '||
'COLUMNS ( ' || t1 || ' PATH ''$.' || t2 || '''))';
dbms_output.put_line(sqlsmt);
execute immediate sqlsmt into t3;
dbms_output.put_line( 'Output Variable: ' || t3);
end;
/
您的示例数据输出:
SELECT * FROM json_table( ( select jsonstr from mytable where ID= 10) , '$' COLUMNS ( descr PATH '$.Description'))
Output Variable: TestJSON
唯一允许作为变量传递的东西 10 是硬编码的,这有点奇怪。但我知道这是一个实验。
您也可以将语句写成:
select j.*
from mytable t
cross join json_table ( t.jsonstr, '$' columns ( descr path '$.Description' )) j
where t.id = 10;
你可以动态地做:
declare
sqlsmt varchar2(200);
id number := 10;
t1 varchar2(30) := 'descr';
t2 varchar2(30) := 'Description';
t3 varchar2(50);
begin
sqlsmt := 'select j.*'
|| ' from mytable t'
|| q'^ cross join json_table ( t.jsonstr, '$' columns ( ^'
|| t1
|| q'^ path '$.^'
|| t2
|| q'^' )) j^'
|| ' where t.id = :id';
dbms_output.put_line(sqlsmt);
execute immediate sqlsmt into t3 using id;
dbms_output.put_line( 'Output Variable: ' || t3);
end;
/
我已经使用 the alternative quoting mechanism 来避免在语句中将引号加倍,但这是可选的。使用相同的数据输出:
select j.* from mytable t cross join json_table ( t.jsonstr, '$' columns ( descr path '$.Description' )) j where t.id = :id
Output Variable: TestJSON