在使用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 trigger,我试图扩展它:
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();
我的问题是:我正在尝试向触发器添加3条规则(返回NULL
):
like '%KLLL%' or like '%MLLL%'
作为Perl程序员,我知道正则表达式,但我的问题是Pl / PgSQL部分 - 如何使用该语言执行正则表达式匹配,我是否总是必须使用SELECT INTO
或PERFORM
?或者我可以在这里使用:=
运算符,甚至可以在IF
语句中执行字符串匹配吗?
更新
克雷格的解释之后(谢谢!)我准备了the following 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
答案 0 :(得分:2)
使用PostgreSQL的~
运算符或regexp_matches
函数。请参阅文档中的pattern matching。
简单的PL / PgSQL示例:
DO
$$
BEGIN
IF 'XABCK' ~ '^[XY]' THEN
RAISE EXCEPTION 'Disallowed character';
END IF;
END;
$$;
如您所见,IF
可以表达。这些表达式可能具有任意复杂性,可能包含子查询CASE
,几乎所有SQL中都是合法的。