我正在开发一个使用Ruby on Rails框架/ PostgreSQL作为DB的小项目,我需要在表中存储一些正则表达式,如下所示:
------------------------
pattern direction
-----------------------
1\d{3} client1
2\d{3} client2
31\d{2} client3
32\d{2} client4
4 client5
-----------------------
每个模式都会以一个或多个某些数字开头,然后由未知的"数字(从0到255个附加数字)。
人们会通过GUI为这个表添加新的对,我想避免交叉,所以对于我的例子3 \ d {3}不应该被允许添加,因为它确实与31 \ d交叉{2}和32 \ d {2}。
在将新的表达式添加到数据库表之前,是否可以检查交集的现有表达式?
此外,在GUI中,用户将看到这些模式,如1XXX,2XXX,31XX。我不想向他们展示表达方式。也许我根本不必使用正则表达式?但我需要按一定的数字搜索最佳匹配模式,例如,使用数字3291的查询应该返回我" client4",query" 4"应该返回" client5"。
在我的案例中,最佳做法是什么?
答案 0 :(得分:2)
基本上,在以下情况下禁止新条目:
您可以冗余地存储总长度或动态计算。我根据问题中显示的模式将公式封装在一个简单的SQL函数中:
CREATE OR REPLACE FUNCTION f_pattern_len(text)
RETURNS int AS
$$
SELECT COALESCE(substring($1, '(\d*)}$')::int, 0) -- digits in prefix
+ length(substring($1, '^\d*')) -- digits in pattern
$$ LANGUAGE SQL IMMUTABLE STRICT;
然后,在INSERT
上,请按以下方式检查:
INSERT INTO tbl (pattern, direction)
SELECT i.input, 'client66'::text
FROM (SELECT '3\d{7}'::text AS input) i
LEFT JOIN tbl t
ON f_pattern_len(t.pattern) = f_pattern_len(i.input)
AND (substring(t.pattern, '^\d*') LIKE (substring(i.input, '^\d*') || '%') OR
substring(i.input, '^\d*') LIKE (substring(t.pattern, '^\d*') || '%'))
WHERE t.pattern IS NULL
您也可以将逻辑放入触发器BEFORE INSERT
...