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();
私の問題は次のとおりです。トリガーに3つのルールを追加しようとしています(NULL
を返します):
- X、Y、Z の文字で始まる単語は禁止されています
- Z文字で終わる単語は禁止されています
- 3 つの同じ文字が連続する単語は非常にまれであり、次の場合にのみ許可されます。
like '%KLLL%' or like '%MLLL%'
Perl プログラマーとして、私は正規表現をよく知っていますが、私の問題は Pl/PgSQL の部分です。その言語で正規表現マッチングを実行するには、常に or を使用する必要がありますSELECT INTO
かPERFORM
? :=
または、ここで演算子を使用したり、IF
ステートメント内で文字列の一致を実行したりできますか?
アップデート:
Craig の説明の後 (ありがとう!) 、次の 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 エンコーディングの最初の 2 語を使用するべきではありませんが、次のようになります。
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