Как искать разделенный запятыми столбец БД в Oracle - PullRequest
0 голосов
/ 07 января 2020

У меня есть таблица Oracle DB с одним столбцом, который содержит значения, разделенные запятыми (не мой дизайн!). В веб-приложении, когда пользователь пытается добавить объект, который приводит к созданию новой записи в этой таблице, я пытаюсь проверить наличие дубликатов.

Я знаю, как проверить одно значение (например, пытаюсь добавить) AB C "), но не уверен, как это сделать, если пользователь добавляет AB C, DEF, GHI, ...

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

001, 002, 006, 008, 009

Я использую следующее для проверки единственного значения:

SELECT COUNT(*) 
FROM PRINTER_MAPPING_CFG 
WHERE ',' || RUNOUTS || ',' LIKE '%,' || '001' || ',%'

Если пользователь добавляет 003, 004, 006, 007, 008, я я не уверен, как действовать (здесь 006 и 008 уже есть в таблице).

Я могу разделить и искать каждый отдельно, но выглядит расточительно, если есть альтернатива.

1 Ответ

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

Правильно, не самый лучший дизайн, какой только можно себе представить.

Посмотрите, поможет ли это:

SQL> with
  2  printer_mapping_cfg (id, runouts) as
  3    -- this is what you currently have. I included the ID column
  4    -- as you probably don't have just one row in that table, do you?
  5    (select 1, '001, 002, 006, 008, 009' from dual union all
  6     select 2, '005, 006, 007'           from dual
  7    ),
  8  new_value (runouts) as
  9    -- this is what user enters
 10    (select '003, 004, 006, 007, 008' from dual),   --> 006 and 008 exist for ID = 1
 11  split_pmc as                                      --> 006 and 007 exist for ID = 2
 12    (select p.id,
 13            trim(regexp_substr(p.runouts, '[^,]+', 1, column_value)) val
 14     from printer_mapping_cfg p cross join
 15         table(cast(multiset(select level
 16                             from dual
 17                             connect by level <= regexp_count(p.runouts, ',') + 1
 18                            ) as sys.odcinumberlist))
 19    )
 20  select s.id,
 21         listagg(s.val, ', ') within group (order by s.val) duplicates
 22  from split_pmc s
 23  where s.val in (select trim(regexp_substr(n.runouts, '[^,]+', 1, level))
 24                  from new_value n
 25                  connect by level <= regexp_count(n.runouts, ',') + 1
 26                 )
 27  group by s.id
 28  order by s.id;

        ID DUPLICATES
---------- ------------------------------
         1 006, 008
         2 006, 007

SQL>

Что он делает?

  • строки # 1 - 7 представляют данные, которые у вас уже есть
  • строки # 8 - 10 - это строка ввода, та, которую пользователь вводит
  • строки # 11 - 19, используется для разделения существующих значений на строки
  • строки # 20 - 28 представляют окончательный select, где
    • строки # 23 - 26 проверяют, существуют ли значения, которые мы нашли в split_pmc CTE, во вновь добавленных значениях (которые уже разбиты на строки)
    • строка # 21 объединяет повторяющиеся значения в одну строку

[EDIT]

Как у вас уже есть в таблице PRINTER_MAPPING_CFG ваш код будет начинаться с

SQL> with
  2  new_value (runouts) as ...

Вы по-прежнему будете ссылаться на таблицу PRINTER_MAPPING_CFG, как и я.

Еще одно условие будет добавлено куда-то в строке № 18 (в коде, который я разместил выше).

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