Postgres文本列只允许/转换为小写而没有特殊字符,例如:Ñöáè

时间:2016-06-15 23:48:34

标签: postgresql postgresql-9.1 postgresql-9.3 postgresql-9.2 postgresql-9.4

我有一张桌子,我希望这一列只接受小写字符串而且没有特殊字符,例如Ñóáöäë等......

无论如何都要将此约束添加到列中吗?

CREATE TABLE lawyer (
  id SERIAL PRIMARY KEY,
  name VARCHAR NOT NULL,
  url_name VARCHAR NOT NULL,
  gender VARCHAR(1) check (gender in ('m','f')) NOT NULL
);

我要添加约束的列是url_name

2 个答案:

答案 0 :(得分:3)

将所需字符放入此translate()电话的第二个参数中:

CREATE TABLE lawyer (
  id SERIAL PRIMARY KEY,
  name VARCHAR NOT NULL,
  url_name VARCHAR check(translate(url_name, 'abcdefghijklmnopqrstuvwxyz', '') = '') NOT NULL,
  gender VARCHAR(1) check (gender in ('m','f')) NOT NULL
);

insert into lawyer
values (default, 'Adam Smith', 'domain', 'f');

INSERT 0 1

insert into lawyer
values (default, 'Adam Smith', 'dömain', 'f');

ERROR:  new row for relation "lawyer" violates check constraint "lawyer_url_name_check"
DETAIL:  Failing row contains (3, Adam Smith, dömain, f).

或者你可以创建一个触发器,它可以动态修改值:

create or replace function lawyer_before_insert_or_update()
returns trigger language plpgsql as $$
begin
    new.url_name := lower(new.url_name);
    if translate(new.url_name, 'abcdefghijklmnopqrstuvwxyz', '') <> '' then
        raise exception 'Incorrect url name.';
    end if;
    return new;
end $$;

create trigger lawyer_before_insert_or_update
before insert or update on lawyer
for each row execute procedure lawyer_before_insert_or_update();

insert into lawyer
values (default, 'Adam Smith', 'DOMAIN', 'f')
returning *;

 id |    name    | url_name | gender 
----+------------+----------+--------
  4 | Adam Smith | domain   | f
(1 row)

INSERT 0 1

insert into lawyer
values (default, 'Adam Smith', 'dömain', 'f');

ERROR:  Incorrect url name.

答案 1 :(得分:1)

对于转换(例如转换为小写),我同意触发器。但是,对于允许的字符,如果这是一个经常性的要求,我建议使用域名。

类似的东西:

 create domain lower_ascii AS text check VALUE ~ '^[a-z]*$';

域有一些优势,包括它们在所有用途中提供单点管理,如果需求发生变化,您可以全局修改检查约束。