Я бы не использовал Regex для этого, так как, например, требования «должны быть уникальными» и «должны быть в порядке возрастания» не могут быть выражены с помощью регулярного выражения (по крайней мере, я не могу придуматьспособ сделать это).
Поскольку вам также необходимо иметь выражение, идентичное в Postgres и Oracle, я бы создал функцию, которая проверяет такой список, а затем скрывает конкретную реализацию СУБД в этой функции.
Для 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, вам, вероятно, понадобитсяиспользовать returns integer
в Postgres, поскольку Oracle по-прежнему не поддерживает логический тип данных в SQL
Функции обработки строк в Oracle менее мощные, чем функции Postgres (например, без string_to_array или unnest), но вывозможно, может реализовать аналогичную логику в PL / SQL (хотя и более сложную)