因此,在最近的 Twitch 泄密事件之后,每个人都在讨论他们最喜欢的糟糕代码。突出的一点是 a single monster SQL statement发现“非法术语”。这让我思考如何“正确”地实现这一点。
因此,您有一个要匹配子字符串的字符串表,您如何在 PL/pgSQL 中编写它?我假设任何 SQL 实现都应该具有为此类元编程创建函数/过程的过程功能,基本上创建和执行 SQL 如下所示:
admin@localhost:words> SELECT 'XabcY' LIKE '%abc%' OR 'XabcY' LIKE '%xyz%' as matches;
+-----------+
| matches |
|-----------|
| True |
+-----------+
更具体地说,给定表中的字符串列表disallowed
:
| illegal_string |
|----------------|
| stupid |
| witless |
| moron |
| commie-lover |
如何在 PL/pgSQL 中创建一个动态查询,如果其中任何一个与给定字符串匹配,则在执行时返回 true?它不需要在 Twitch 中使用 ILIKE
来检查给定的单词是否包含子字符串,因此使用 position
也可以,但它应该是高性能/可调整的gin
索引等等。
最佳答案
有两种可能性:
- 您可以使用
LIKE ANY(array)
运算符
postgres=# select 'Ahoj' like any (ARRAY['Ah%', 'Na%']);
┌──────────┐
│ ?column? │
╞══════════╡
│ t │
└──────────┘
(1 row)
postgres=# select 'Nazdar' like any (ARRAY['Ah%', 'Na%']);
┌──────────┐
│ ?column? │
╞══════════╡
│ t │
└──────────┘
(1 row)
- 您可以使用正则表达式:
postgres=# select 'Ahoj' ~ '^(Ah|Na)';
┌──────────┐
│ ?column? │
╞══════════╡
│ t │
└──────────┘
(1 row)
postgres=# select 'Nazdar' ~ '^(Ah|Na)';
┌──────────┐
│ ?column? │
╞══════════╡
│ t │
└──────────┘
(1 row)
所以最终你不需要动态 SQL。
也有 ANSI/SQL 语法:
postgres=# select 'Nazdar' similar to '(Ah|Na)%';
┌──────────┐
│ ?column? │
╞══════════╡
│ t │
└──────────┘
(1 row)
所以你可以这样写:
DECLARE pw text[];
BEGIN
pw := (SELECT array_agg('%' || disallowed || '%'
FROM disallowed);
IF EXISTS(SELECT * FROM foo WHERE c LIKE ANY (pw)) THEN
RAISE NOTICE 'there are some disallowed words';
END IF;
...
我不确定表演。在较大的表上,您需要三元组索引,或者更好的是使用全文而不是子字符串搜索。
关于sql - 将子字符串与存储的字符串列表进行匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69528460/