暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle 21c对JSON支持功能增强

599

在这篇文章中《Oracle和JSON的结合》介绍了Oracle对JSON的支持,有朋友提了两个问题,

问题1,Oracle有没有字段可以直接存储JSON串并支持检索的?

问题2,试过几次,用来读取和约束还行,但是要用来存并还需要修改,还是不太容易。联想到DB2之前的XmlQuery语法,门槛太高,不小心就出错


(1) 针对问题1

时代在进步,技术同样在发展,Oracle 21c(准确地说,某些功能从20c就已经引入了,由于20c只是预览版,还是主要以21c为准)引入了JSON数据类型,目的就是为了提升检索和DML操作对JSON数据的效率,


https://docs.oracle.com/en/database/oracle/oracle-database/21/nfcon/application-development.html#GUID-47BBA332-62C9-41AD-A1D2-51EE02379171


如下所示,

    SQL> create table tjson(id number, json_data json);
    Table created.


    可以按照常规的字符串类型插入,

      SQL> insert into tjson values(1, '{"name":"Cristiano Ronaldo","goal":30}');
      1 row created.


      还可以使用JSON构造函数插入,

        SQL> insert into tjson values(2, json('{"name":"Leo Messi","goal":25}'));
        1 row created.


        可以直接检索,

          SQL> select * from tjson;
          ID JSON_DATA
          ---------- -------------------------------------------------------
          1 {"name":"Cristiano Ronaldo","goal":30}
                   2 {"name":"Leo Messi","goal":25}


          还可以使用写程序时常用的"."操作符进行检索,

            SQL> select j.json_data.name from tjson j;
            NAME
            --------------------------------------------------------------------------------
            "Cristiano Ronaldo"
            "Leo Messi"


            json_value函数能用特定类型返回节点数据,

              SQL> select j.id, json_value(j.json_data, '$.name') as name,
              2 json_value(j.json_data, '$.goal' returning number) as goal
                3  from tjson j;
              ID NAME GOAL
              ---------- ---------------------- ----------
              1 Cristiano Ronaldo 30
                       2 Leo Messi              25

              https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/JSON_VALUE.html#GUID-C7F19D36-1E75-4CB2-AE67-ADFBAD23CBC2


              json_query函数可以完成相同的操作,

                SQL> select j.id, json_query(j.json_data, '$.name' returning varchar2) as name,
                2 json_query(j.json_data, '$.goal' returning varchar2) as goal
                  3  from tjson j;
                ID NAME GOAL
                ---------- -------------------------- ---------------
                1 "Cristiano Ronaldo" 30
                         2 "Leo Messi"                 25

                https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/JSON_QUERY.html#GUID-6D396EC4-D2AA-43D2-8F5D-08D646A4A2D9


                还可以使用json_table函数,

                  SQL> select j.id, jt.name, jt.goal
                  2 from tjson j,
                  3 json_table(j.json_data, '$' columns(name varchar2(50 char) path '$.name',
                    4                                      goal number path '$.goal')) jt;
                  ID NAME GOAL
                  ---------- -------------------------------------------------- ----------
                  1 Cristiano Ronaldo 30
                           2 Leo Messi                                                  25

                  https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/JSON_TABLE.html#GUID-3C8E63B5-0B94-4E86-A2D3-3D4831B67C62


                  (2) 针对问题2

                  21c引入了json_transform函数,他的作用就是可以通过指定一个或多个操作符改JSON数据或者片段,

                  https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/JSON_TRANSFORM.html#GUID-DD2A821B-C688-4310-81B5-5F45090B9366


                  如下所示,修改id=1的记录中goal这个节点的值,

                    SQL> update tjson set json_data = json_transform(json_data, set '$.goal' = 35) where id = 1;
                    1 row updated.


                    检索进行验证,

                      SQL> select j.id, json_value(j.json_data, '$.name') as name,
                      2 json_value(j.json_data, '$.goal' returning number) as goal
                        3  from tjson j;
                      ID NAME GOAL
                      ---------- -------------------------------------------------- ----------
                      1 Cristiano Ronaldo 35
                               2 Leo Messi                                                  25


                      还支持同时进行多种变更操作,

                        SQL> update tjson set json_data = json_transform(json_data, set '$.name' = 'L.Messi', replace '$.goal' = 30 returning json) where id = 2;
                        1 row updated.


                        支持这些操作,

                          removeOp | insertOp | replaceOp | appendOp | setOp | renameOp | keepOp


                          可以看到更新,

                            SQL> select j.id, json_value(j.json_data, '$.name') as name,
                            2 json_value(j.json_data, '$.goal' returning number) as goal
                              3  from tjson j;
                            ID NAME GOAL
                            ---------- -------------------------- ----------
                            1 Cristiano Ronaldo 35
                                     2 L.Messi                     30


                            至少从肉眼观测效率上和普通数据类型的增删改相差无几,如果比较关注,可以进行一些实际的压测。虽然语法略复杂,至少从操作层面上,还是比较简洁的,对于JSON数据的处理,不再只能通过程序来做了,数据库提供了另外一种方案,尤其是使用存储过程,PL/SQL中同样能用到这些函数和数据类型,会更加便捷。


                            参考资料,

                            https://www.modb.pro/db/110452

                            https://blog.csdn.net/horses/article/details/120369571

                            https://docs.oracle.com/en/database/oracle/oracle-database/21/nfcon/application-development.html#GUID-47BBA332-62C9-41AD-A1D2-51EE02379171

                            https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/JSON_VALUE.html#GUID-C7F19D36-1E75-4CB2-AE67-ADFBAD23CBC2

                            https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/JSON_QUERY.html#GUID-6D396EC4-D2AA-43D2-8F5D-08D646A4A2D9

                            https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/JSON_TABLE.html#GUID-3C8E63B5-0B94-4E86-A2D3-3D4831B67C62

                            https://docs.oracle.com/en/database/oracle/oracle-database/21/sqlrf/JSON_TRANSFORM.html#GUID-DD2A821B-C688-4310-81B5-5F45090B9366


                            如果您认为这篇文章有些帮助,还请不吝点下文章末尾的"点赞"和"在看",或者直接转发pyq,



                            近期更新的文章:

                            翻译专业资格(水平)考试介绍

                            MySQL忘了账号密码,除了跑路,还能补救么?

                            非标准数据块的表空间使用

                            数据库安全的重要性

                            CentOS 7.9安装Oracle 21c历险记


                            近期的热文:

                            "红警"游戏开源代码带给我们的震撼


                            文章分类和索引:

                            公众号1000篇文章分类和索引

                            文章转载自bisal的个人杂货铺,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                            评论