Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/81.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 识别冲突的正则表达式_Sql_Ruby On Rails_Ruby_Regex_Postgresql - Fatal编程技术网

Sql 识别冲突的正则表达式

Sql 识别冲突的正则表达式,sql,ruby-on-rails,ruby,regex,postgresql,Sql,Ruby On Rails,Ruby,Regex,Postgresql,我正在用Ruby on Rails framework/PostgreSQL作为DB开发一个小项目,我需要在表中存储一些正则表达式,如下所示: ------------------------ pattern direction ----------------------- 1\d{3} client1 2\d{3} client2 31\d{2} client3 32\d{2} client4 4

我正在用Ruby on Rails framework/PostgreSQL作为DB开发一个小项目,我需要在表中存储一些正则表达式,如下所示:

------------------------
pattern       direction
-----------------------
1\d{3}        client1        
2\d{3}        client2
31\d{2}       client3
32\d{2}       client4
4             client5
-----------------------
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
每个模式都将以一个或多个特定数字开始,并以“未知”数字(从0到255个附加数字)继续

人们将通过GUI向这个表中添加新的对,我希望避免交叉,因此对于我的示例,不允许添加3\d{3},因为它与31\d{2}和32\d{2}相交

在将新表达式添加到DB表之前,是否可以检查现有表达式的交集

此外,在GUI中,用户将看到这些模式,如1xx、2XXX、31XX。我不喜欢给他们看表情。也许我根本不需要使用regexp?但我需要按特定数字搜索最佳匹配模式,例如,编号为3291的查询应返回我的“client4”,查询“4”应返回“client5”


我的最佳做法是什么?

基本上,在以下情况下不允许新条目:

  • 总长度匹配
  • 前缀是条目的子字符串,反之亦然
您可以冗余存储总长度,也可以动态计算总长度。根据问题中显示的模式,我将公式封装在一个简单的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;
然后,在插入时,检查如下:

------------------------
pattern       direction
-----------------------
1\d{3}        client1        
2\d{3}        client2
31\d{2}       client3
32\d{2}       client4
4             client5
-----------------------
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


您也可以在插入之前将逻辑放入触发器

模式中允许有多少个“未知”(最大值)?理想情况下为255,但可以降低到至少30。好的,有了这些,我将坚持您当前的存储方法,并在输入/输出时将
32\d{2}
转换为
32XX
。我对你的问题也有一个想法…是的,我打算在数据库保存/读取时将XXXX模式转换为regexps。。。对用户来说会更舒适。电话号码前缀匹配?嗯。。您的解决方案看起来非常有趣,但我不理解SQL FIDLE上输出的某些时刻。。例如,为什么输入771\d{1}1\d{3}模式被定义为冲突模式?@JC:Oh,我的错。类
模式必须左锚定。我有一个领先的
%
,把聚会搞砸了。现在应该可以工作了。非常感谢,我将在我的沙盒环境中检查所有内容,但我认为您的解决方案可以解决问题。