Как правильно использовать REGEXP_SUBSTR? - PullRequest
2 голосов
/ 13 января 2020

В настоящее время в моем утверждении select у меня есть id и значение. Значение json выглядит следующим образом:

{"layerId":"nameOfLayer","layerParams":{some unnecessary data}

Я хотел бы иметь в своем идентификаторе выбора и nameOfLayer, поэтому вывод будет, например:

1, layerName
2, layerName2
etc.

json выглядит всегда одинаково, поэтому layerID является первым. Не могли бы вы сказать мне, как я могу правильно использовать REGEXP_SUBSTR в моем запросе выбора, который выглядит следующим образом?

select
  id,
  value
from
  ...
where
  table1.id = table2.bookmark_id
  and ...;

Ответы [ 3 ]

1 голос
/ 13 января 2020

В Oracle 11g вы можете извлечь layerId, используя следующее регулярное выражение, где js - это имя вашего столбца JSON:

regexp_replace(js, '^.*"layerId":"([^"]+).*$', '\1')

Это в основном извлекает строку между двойными кавычками после "layerId":.

В более поздних версиях вы добавили бы проверочное ограничение для таблицы, чтобы убедиться, что документ действителен JSON, а затем использовали точечную нотацию для доступа к атрибуту объекта следующим образом:

create table mytable (
    id int primary key,
    js varchar2(200),
    constraint ensure_js_is_json check (js is json)
);

insert into mytable values (1, '{"layerId":"nameOfLayer","layerParams":{} }');

select id, t.js.layerId from mytable t;

Демонстрация на DB Fiddle :

ID | LAYERID    
-: | :----------
 1 | nameOfLayer
0 голосов
/ 13 января 2020

Я думаю, вы можете использовать regexp_substr вот так:

regexp_substr(str, '[^"]+',1,2) as layer_id,
regexp_substr(str, '[^"]+',1,4) as layername

Db <> fiddle demo

Cheers !!

0 голосов
/ 13 января 2020

Не используйте регулярные выражения; используйте JSON_TABLE или JSON_VALUE для анализа JSON:

Oracle 18 c Настройка :

CREATE TABLE test_data (
  id    INTEGER,
  value VARCHAR2(4000)
);

INSERT INTO test_data ( id, value )
SELECT 1, '{"layerId":"nameOfLayer","layerParams":{"some":"unnecessary data"}}' FROM DUAL UNION ALL
SELECT 2, '{"layerParams":{"layerId":"NOT THIS ONE!"},"layerId":"nameOfLayer"}' FROM DUAL UNION ALL
SELECT 3, '{"layerId":"Name with \"Quotes\"","layerParams":{"layerId":"NOT THIS ONE!"}}' FROM DUAL;

Запрос 1 :

SELECT t.id,
       j.layerId
FROM   test_data t
       CROSS JOIN
       JSON_TABLE(
         t.value,
         '$'
         COLUMNS (
           layerId VARCHAR2(50) PATH '$.layerId'
         )
       ) j

Запрос 2 :

Если вам нужно только одно значение, вы можете использовать JSON_VALUE:

SELECT id,
       JSON_VALUE( value, '$.layerId' ) AS layerId
FROM   test_data

Выход :

Оба выхода:

ID | LAYERID           
-: | :-----------------
 1 | nameOfLayer       
 2 | nameOfLayer       
 3 | Name with "Quotes"

Запрос 3 :

Вы можете попробовать регулярные выражения, но они не всегда работают должным образом:

SELECT id,
       REPLACE(
         REGEXP_SUBSTR( value, '[{,]"layerId":"((\\"|[^"])*)"', 1, 1, NULL, 1 ),
         '\"',
         '"'
       ) AS layerID
FROM   test_data

Вывод :

ID | LAYERID           
-: | :-----------------
 1 | nameOfLayer       
 2 | NOT THIS ONE!     
 3 | Name with "Quotes"

Так что если вы может гарантировать, что никто не собирается помещать данные в базу данных, где JSON находится в другом порядке, чем это может сработать; однако спецификация JSON позволяет парам ключ-значение располагаться в любом порядке, поэтому регулярные выражения не являются общим решением, которое будет анализировать каждую строку JSON. Вы должны использовать правильный JSON синтаксический анализатор, и есть сторонние решения, доступные для Oracle 11g, или вы можете обновить до Oracle 12 c, где есть собственное решение.

дБ <> скрипка здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...