Postgres:select 使用列作为正则表达式,当只有一些行是有效的正则表达式时
Postgres: select using column as regex, when only some rows are valid regexes
TLDR
如何使用列值 ('input' ~ t.somecolumn
) 执行正则表达式匹配查询,其中只有行的已知子集在该列中具有有效的正则表达式?
完整示例
- 有一个
blocked_items
table 包括两个 varchar 列:type
和 value
,
- 其中一个类型是
DOMAIN_REGEX
,然后 value
总是包含正确的正则表达式,
- 但是:对于其他类型
value
不需要是正则表达式,当作为正则表达式处理时可能会导致错误。
要检查域是否被阻止,我调用此查询并将有问题的 URL 作为 </code> 参数传递:</p>
<pre><code>SELECT 1 FROM blocked_items WHERE type = 'DOMAIN_REGEX' AND ~ value LIMIT 1
问题:在某些数据库实例上 如果具有另一个 type
的行 value
不是有效的正则表达式,则查询失败。在一个数据库上,此查询正确运行,而在另一个实例上,无论输入如何,都会抛出:invalid regular expression: quantifier operand invalid
.
示例测试数据:
| type | value |
|--------------+---------------------|
| EMAIL | test+++1@test.com |
| DOMAIN_REGEX | test\d\.com |
问题
我知道我的错误的原因是数据库引擎可以选择首先检查第二个条件 ( ~ value
) -- 我已经为我的查询检查了 EXPLAIN
,确实是这两个数据库实例不同。
有什么办法吗
- 强制数据库首先检查
type
列,以便正则表达式过滤器始终有效?
- 以不同的方式形成查询以忽略非正则表达式
value
条目的错误?或者先检查它是否是一个有效的正则表达式?
- 用其他方法解决这个问题?
// 我知道更改架构或使用 LIKE
可能就足够了,但既然我偶然发现了这一点,我很好奇是否有使用像这样的正则表达式的解决方案:)
你是对的,架构不是很好。如果您仍然确实必须保留架构,您可以尝试CASE/WHEN、https://www.postgresqltutorial.com/postgresql-case/
您应该能够使用 case
:
强制执行操作顺序
SELECT 1
FROM blocked_items
WHERE (CASE WHEN type <> 'DOMAIN_REGEX' THEN false
ELSE ~ value
END)
LIMIT 1;
一般来说,SQL(和 Postgres)对表达式求值的顺序提供很少的控制。但是,CASE
在许多情况下应该提供这种控制。
TLDR
如何使用列值 ('input' ~ t.somecolumn
) 执行正则表达式匹配查询,其中只有行的已知子集在该列中具有有效的正则表达式?
完整示例
- 有一个
blocked_items
table 包括两个 varchar 列:type
和value
, - 其中一个类型是
DOMAIN_REGEX
,然后value
总是包含正确的正则表达式, - 但是:对于其他类型
value
不需要是正则表达式,当作为正则表达式处理时可能会导致错误。
要检查域是否被阻止,我调用此查询并将有问题的 URL 作为 </code> 参数传递:</p>
<pre><code>SELECT 1 FROM blocked_items WHERE type = 'DOMAIN_REGEX' AND ~ value LIMIT 1
问题:在某些数据库实例上 如果具有另一个 type
的行 value
不是有效的正则表达式,则查询失败。在一个数据库上,此查询正确运行,而在另一个实例上,无论输入如何,都会抛出:invalid regular expression: quantifier operand invalid
.
示例测试数据:
| type | value |
|--------------+---------------------|
| EMAIL | test+++1@test.com |
| DOMAIN_REGEX | test\d\.com |
问题
我知道我的错误的原因是数据库引擎可以选择首先检查第二个条件 ( ~ value
) -- 我已经为我的查询检查了 EXPLAIN
,确实是这两个数据库实例不同。
有什么办法吗
- 强制数据库首先检查
type
列,以便正则表达式过滤器始终有效? - 以不同的方式形成查询以忽略非正则表达式
value
条目的错误?或者先检查它是否是一个有效的正则表达式? - 用其他方法解决这个问题?
// 我知道更改架构或使用 LIKE
可能就足够了,但既然我偶然发现了这一点,我很好奇是否有使用像这样的正则表达式的解决方案:)
你是对的,架构不是很好。如果您仍然确实必须保留架构,您可以尝试CASE/WHEN、https://www.postgresqltutorial.com/postgresql-case/
您应该能够使用 case
:
SELECT 1
FROM blocked_items
WHERE (CASE WHEN type <> 'DOMAIN_REGEX' THEN false
ELSE ~ value
END)
LIMIT 1;
一般来说,SQL(和 Postgres)对表达式求值的顺序提供很少的控制。但是,CASE
在许多情况下应该提供这种控制。