如何在 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 行的某处添加另一个条件(在我上面发布的代码中)。
我有一个 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 行将重复值聚合成一个字符串
- 第 23 - 26 行检查我们在
[编辑]
因为您已经有了 PRINTER_MAPPING_CFG
table,您的代码将以
SQL> with
2 new_value (runouts) as ...
您仍然会像我一样引用 PRINTER_MAPPING_CFG
table。
将在第 18 行的某处添加另一个条件(在我上面发布的代码中)。