Каков наилучший способ отделить и сохранить адреса из строки в PL / SQL? - PullRequest
0 голосов
/ 25 января 2019

В нашей базе данных есть таблицы с адресами компаний. Некоторые компании имеют более 1 адреса. В этом случае мы использовали для сохранения адресов в столбце, как это:

'119021, г Москва, ул Льва Толстого, д 16; 117312, г Москва, ул Вавилова, д 19' 

Итак, точка с запятой и пробел между адресами.

Теперь мне нужно создать другую таблицу, в которой каждый адрес имеет свою строку, копируя данные из существующей таблицы.

Какие инструменты мне следует использовать в моей процедуре,

  • определяет, есть ли в столбце один или несколько адресов
  • отдельные адреса, если их больше 1

Должен ли я использовать REGEXP? Если да, то как?

Ответы [ 2 ]

0 голосов
/ 07 февраля 2019

Во-первых, было бы упущением, если бы я не указал будущим поисковикам, что хранение более одного фрагмента информации в одном столбце нарушает первую нормальную форму проектирования базы данных и не доставит вам ничего, кроме неприятностей в будущем. Поскольку вы исправляете это, я приветствую вас!

Во-вторых, использование шаблона регулярного выражения в форме '[^;]+' для анализа строк с разделителями завершается неудачно, когда в списке есть нулевые элементы. Смотрите здесь для получения дополнительной информации о том, почему это плохая идея: https://stackoverflow.com/a/31464699/2543416

Теперь я не весь мрак и мрак! Я не знаю, какой набор символов вы используете, но вы поймете. В этом примере используется форма регулярного выражения, которая допускает элементы списка NULL и 1 или более точек с запятой, за которыми следует пробел ИЛИ конец строки.

with tbl(id, str) as (
  select 1, '119021-1, г Москва, ул Льва Толстого, д 16; 117312-1, г Москва, ул Вавилова, д 19' from dual union all
  select 2, '119021-2, г Москва, ул Льва Толстого, д 16;;; 117312-2, г Москва, ул Вавилова, д 19' from dual
)
select id, regexp_substr(str, '(.*?)(;+ |$)', 1, level, NULL, 1) addr_fixed
from tbl
connect by regexp_substr(str, '(.*?)(;+ |$)', 1, level, NULL, 1) is not null
  and prior id = id
  and prior sys_guid() is not null;


        ID ADDR_FIXED                                   
---------- ---------------------------------------------
         1 119021-1, ¿ ¿¿¿¿¿¿, ¿¿ ¿¿¿¿ ¿¿¿¿¿¿¿¿, ¿ 16   
         1 117312-1, ¿ ¿¿¿¿¿¿, ¿¿ ¿¿¿¿¿¿¿¿, ¿ 19        
         2 119021-2, ¿ ¿¿¿¿¿¿, ¿¿ ¿¿¿¿ ¿¿¿¿¿¿¿¿, ¿ 16   
         2 117312-2, ¿ ¿¿¿¿¿¿, ¿¿ ¿¿¿¿¿¿¿¿, ¿ 19        

4 rows selected.
0 голосов
/ 25 января 2019

определяет, есть ли в столбце один или более 1 адресов

. Вы можете использовать REGEXP_COUNT, чтобы подсчитать, сколько раз символ точки с запятойпоявится в поле: добавив 1 к этому, вы получите количество адресов:

SELECT t.*, regexp_count(t.address, ';') + 1 FROM mytable t;

отдельных адресов, если их больше 1

Разделить строкув новые строки, как прокомментировал О. Джонс, подход состоит в том, чтобы использовать функции регулярных выражений в сочетании с рекурсивным запросом, например:

SELECT TRIM(regexp_substr( t.address, '[^;]+', 1,  LEVEL )) regexp_substr
FROM mytable t
CONNECT BY LEVEL <= regexp_count( t.address,  ';' ) + 1;

Этот тип оператора может быть встроен в INSERT ... AS SELECT или CREATE ... AS SELECT заказ, например:

CREATE TABLE newtable as
SELECT t.name, TRIM(regexp_substr( t.address, '[^;]+', 1,  LEVEL )) regexp_substr
FROM mytable t
CONNECT BY LEVEL <= regexp_count( t.address,  ';' ) + 1;

Демонстрация на Oracle 11gR2

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