在使用 UTF8 编码的 PostgreSQL 8.4.13 数据库中,我在此表中保留了一个(非英语)字典:
create table good_words (
word varchar(64) primary key
);
以及以下错误(但经常建议或输入错误)单词的列表:
create table bad_words (
word varchar(64) primary key
);
对于前一个表,我有一个BEFORE INSERT 触发器,我正在尝试扩展它:
create or replace function keep_clean() returns trigger as $body$
begin
new.word := upper(new.word);
perform true
from bad_words
where word = new.word;
if found then
return null;
end if;
-- forbid words with [XYZ] at beginning and Z at the end
-- forbid words with LLL unless it is KLLL or MLLL
return new;
end;
$body$ language plpgsql;
create trigger count_letters
BEFORE INSERT on good_words
for each row execute procedure keep_clean();
我的问题是:我正在尝试NULL
向我的触发器添加 3 条规则(返回):
- 禁止使用以 X、Y 或 Z 字母开头的单词
- 禁止以 Z 字母结尾的单词
- 连续 3 个相同字母的单词非常罕见,只有在出现时才允许使用
like '%KLLL%' or like '%MLLL%'
作为 Perl 程序员,我非常了解正则表达式,但我的问题是 Pl/PgSQL 部分 - 如何在该语言中执行正则表达式匹配,我总是必须使用SELECT INTO
orPERFORM
吗?或者我可以:=
在这里使用运算符,甚至可以在IF
语句中执行字符串匹配?
更新:
经过克雷格的解释(谢谢!)我准备了以下 SQL Fiddle,但它仍然存在2个问题:
create table good_words (
word varchar(64) primary key
);
create or replace function keep_clean() returns trigger as $body$
begin
new.word := upper(new.word);
/* next line does not compile? */
IF new.word !~ '^[\x0410-\x042F]{2,}$' THEN
RAISE EXCEPTION 'Not an uppercased Russian word in UTF8';
END IF;
IF new.word ~ '^[ЪЫЬ]' OR new.word ~ 'Ъ$' THEN
return NULL;
END IF;
/* does not return NULL for 'ошибббка'? */
IF new.word ~ '(.)\1\1' AND new.word NOT LIKE '%ШЕЕЕ%' AND new.word NOT LIKE '%ЗМЕЕЕ%' THEN
return NULL;
END IF;
return new;
end;
$body$ language plpgsql;
它不应该在这里采用 UTF8 编码的第一个两个单词,但它确实:
insert into good_words (word)
values
('abcde'), /* bad word: non-russian */
('ошибббка'), /* bad word: 3 letters in a row */
('длинношеее'),
('проверка')
;
select * from good_words;
更新 2:触发器现在可以工作了,谢谢:http ://sqlfiddle.com/#!11/98403/1