如何在 Oracle 中搜索逗号分隔的数据库列

How to search a comma separated DB column in Oracle

我有一个 Oracle 数据库 table,其中一列包含逗号分隔值(不是我的设计!)。在 Web 应用程序中,当用户尝试添加一个对象并导致在此 table 中创建一个新条目时,我正在尝试检查重复项。

我知道如何检查单个值(例如尝试添加 "ABC")但不确定如果用户要添加 ABC、DEF、GHI,...

假设 table 被称为 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 已经在 table 中)。

我可以拆分并分别搜索每个,但看起来很浪费,如果有替代方案的话。

是的,不是人们能想象的最好的设计。

看看这是否有帮助:

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 行将重复值聚合成一个字符串

[编辑]

因为您已经有了 PRINTER_MAPPING_CFG table,您的代码将以

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

您仍然会像我一样引用 PRINTER_MAPPING_CFG table。

将在第 18 行的某处添加另一个条件(在我上面发布的代码中)。