我正在尝试将逗号分隔的数字字符串与sql查询中的特定模式匹配。过去,我成功地使用正则表达式解决了类似的问题,因此,我也试图使其在这里也能正常工作。问题如下:
(我认为这是一种有序采样而无替换的情况)
坚持1-4的示例,以下条目应匹配:
1
1,2
1,3
1,4
1,2,3
1,2,4
1,3,4
1,2,3,4
2
2,3
2,4
3
3,4
4
而这些不应:
q dawda 323123 a3 a1 1aa,1234 4321 a4,32,1a 1112222334411
1,,2,33,444, 11,12,a 234 2,2,3 33 3,3,3 3,34 34 123 1,4,4,4a 1,444
我目前最好的尝试是:
\b[1-4][\,]?[2-4]?[\,]?[3-4]?[\,]?[4]?\b
这仍然有两个主要缺点:
我使用regexpal进行测试。
旁注:
编辑:澄清了正面示例列表
答案 0 :(得分:2)
我不会为此使用正则表达式,例如要求“必须是唯一的”和“必须以升序”不能真正用正则表达式表示(至少我想不到做到这一点的方法)。
由于您还需要在Postgres和Oracle中具有相同的表达式,因此我将创建一个检查此类列表的函数,然后在该函数中隐藏特定于DBMS的实现。
对于Postgres,我将使用其数组处理功能来实现该功能:
create or replace function is_valid(p_input text)
returns boolean
as
$$
select coalesce(array_agg(x order by x) = string_to_array(p_input, ','), false)
from (
select distinct x
from unnest(string_to_array(p_input,',')) as t(x)
where x ~ '^[0-9]+$' -- only numbers
) t
where x::int between 1 and 4 -- the cast is safe as the inner query only returns valid numbers
$$
language sql;
内部查询以单个数字的形式返回输入列表中的所有(不同的)元素。然后,外部查询聚合返回所需范围和数字顺序的值。如果该结果与输入的结果不同,则该输入无效。
然后显示以下示例数据:
with sample_data (input) as (
values
('1'),
('1,2'),
('1,3'),
('1,4'),
('1,2,3'),
('1,2,4'),
('foo'),
('1aa,1234'),
('1,,2,33,444,')
)
select input, is_valid(input)
from sample_data;
它将返回:
input | is_valid
-------------+---------
1 | true
1,2 | true
1,3 | true
1,4 | true
1,2,3 | true
1,2,4 | true
foo | false
1aa,1234 | false
1,,2,33,444, | false
如果要在Postgres和Oracle中使用相同的功能,则可能需要在Postgres中使用returns integer
,因为Oracle在SQL中仍然不支持布尔数据类型。
Oracle的字符串处理功能不如Postgres的功能强大(例如,没有string_to_array或unnest),但是您也可以在PL / SQL中实现类似的逻辑(尽管更复杂)