Обновите значение идентификатора в формате XXXXXXXX-X с использованием оракула SQL - PullRequest
1 голос
/ 24 июня 2019

Название таблицы: ТЕСТ Название столбца: ID [VARCHAR (200)]

Формат идентификатора: ‘XXXXXXXX-X’, где ‘X’ - это число от 0 до 9. Дополнительные операции в случае, если вышеуказанный формат не выполняется:

  1. если идентификатор состоит из 9 цифр и между восьмой и девятой цифрой двойная черта, лишняя черта удаляется (например, 08452142--6 -> 08452142-6)

  2. , если идентификатор состоит из 9 цифр, и между восьмой и девятой цифрой и / или нецифровыми и / или небуквенными символами (символами) есть пробел (ы), а затем заменить их на тире (например, 08452142 -. 3 -> 08452142-3)

  3. , если идентификатор состоит из 9 цифр и начинается / заканчивается нецифровыми и / или небуквенными символами, а затем удаляет эти символы до цифр (например, 08452142-2 .. -> 08452142 -2)

  4. , если идентификатор содержит только 9 цифр, тогда перед последней цифрой ставится тире (например, 123456789 -> 12345678-9)

Я достиг необходимого формата с помощью приведенного ниже фрагмента.

UPDATE TEST
  SET ID = (SELECT REGEXP_REPLACE(ID,'^\d{8}-\d{1}$','') AS "ID" 
            from TEST 
            WHERE PK = 11;
)

Каковы возможные способы добавления преобразований, упомянутых в пунктах [1-4] выше, в одном запросе?

Используя REGEXP_REPLACE, я могу получить ID в вышеуказанном формате. Но если формат неправильный, и ID необходимо преобразовать [например, удалить лишнюю черту или добавить черту в случае получения 9 цифр], чтобы получить удовлетворительный формат, как этого можно достичь в одном запросе UPDATE?

Ответы [ 4 ]

0 голосов
/ 25 июня 2019

Я попробовал подход, основанный на предложении @ BarbarosÖzhan:

with source as (
    select  '02426467--6' id from dual union all
    select  '02426467-6' id from dual union all
    select  '02597718 -- .   3' id from dual union all
    select  '02597718 --dF5 .   3' id from dual union all
    select  '00120792-2..' id from dual union all
    select  '..00120792-2..' id from dual union all
    select  '123456789' id from dual union all
    select  '1234567890' id from dual
)
select
    case
        when regexp_like(id, '\d{8}-\d{1}')
            then id
        else
            case
        when regexp_like(id, '\d{8}-\d{1}')
            then id
        else
            case
                when regexp_count(id, '\d') = 9
                    then
                        case
                            when
                                regexp_like(
                                    regexp_replace(
                                        regexp_replace(
                                            id, '(\d{8}-)(-)(\d{1})', '\1\3' 
                                        ), '(\d{8})([^A-Za-z1-9])(\d{1})', '\1-\3' 
                                    )
                                , '\d{8}-\d{1}')
                                then
                                    regexp_replace(
                                        regexp_replace(
                                            id, '(\d{8}-)(-)(\d{1})', '\1\3' 
                                        ), '(\d{8})([^A-Za-z1-9])(\d{1})', '\1-\3' 
                                    )
                            else id
                        end
                else id
            end
    end id_tr
    from source

Однако в случаях 3 и 4 я не могу избавиться от пробела, точки и алфавитов.Я думаю, что что-то не так с логикой в ​​случае, если длина больше, чем 9. Я заканчиваю "id", так что результат такой же, без каких-либо изменений.Любые предложения, чтобы улучшить это?

0 голосов
/ 24 июня 2019

Я думаю, вам нужны первые 8 цифр, затем дефис, затем 9-я цифра:

select ( substr(regexp_replace(id, '[^0-9]', ''), 1, 8) ||
         '-' ||
         substr(regexp_replace(id, '[^0-9]', ''), 9, 1)
       )
0 голосов
/ 24 июня 2019

В любом случае вам нужно извлечь 9 цифр из вашей строки на первом шаге.А затем добавьте дефис перед последним символом.Для обоих шагов используйте regexp_replace() function

with test(id) as
(
 select '08452142--6'    from dual union all
 select '08452142 - . 3' from dual union all
 select '08452142-2..'   from dual union all
 select '123456789'      from dual union all
 select '1234567890'     from dual
)
select case when length(regexp_replace(id,'(\D)'))=9 then
            regexp_replace(regexp_replace(id,'(\D)'),
                                     '(^[[:digit:]]{8})(.*)([[:digit:]]{1}$)','\1-\3')
       end as id
  from test;

ID
----------
08452142-6
08452142-3
08452142-2
12345678-9
<null>

Demo

0 голосов
/ 24 июня 2019

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

UPDATE TEST
   SET ID = REGEXP_REPLACE(ID,'^\D*(\d{8})\D*(\d)\D*$','\1-\2')
 WHERE REGEXP_LIKE(ID,'^\D*(\d{8})\D*(\d)\D*$')

Таким образом, вы игнорируете все нецифровые символы и ищете 8-значный номер, а затем 1-значный номер. Возьмите эти 2 цифры и поставьте между ними один «-».

Это немного более щедро, чем вам может понадобиться, но должно работать со всеми предоставленными вами примерами.

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