是否可以创建一个始终小写的char列?

时间:2017-04-04 19:18:26

标签: postgresql

我想创建一个像:

的表
create table project_types (
  id char(20) not null unique default 'xxx'
};

从其他表中使用它:

create table other_table (
  ...
  fk_ptype char(20),
  fk_ptype_on_other_table" foreign key (fk_ptype) references project_type(id)
);

问题是,我希望插入project_types的所有值都自动变为小写:我不想对每个可能的查询进行转换,我想要一张表,无论如何我扔了它,它返回小写标记。

我正在考虑在插入更新时触发,但我想知道是否有更好的方法来施加此类限制。此外,这个解决方案意味着我必须对删除进行转换。

对于那些可能暗示我使用枚举执行此操作的内容:类型是动态的,所以我更喜欢这种方法。

更新2017.04.17:这个问题的想法不是在堆栈中的任何地方放置控件/转换:如果数据库可以处理你扔的任何东西,那么你就没有 1。检查/转换前端, 2。检查/转换后端代码,最后 3。检查/在数据库中转换。你只需要避免做1和2,因为你知道数据库会处理你扔的任何东西,并且当你select时它会有正确的数据。

我很想选择@herbert-pimentel回答,但似乎同样的方法不能用于delete(我尝试使用相同的功能设置和开启删除触发器,但它没有#&# 39;工作)。

3 个答案:

答案 0 :(得分:3)

在插入或更新之前触发器如何确保/转换数据小写;

CREATE OR REPLACE FUNCTION public.fun_trg_lowercase()
  RETURNS trigger AS
$BODY$
begin 
  NEW.my_char_field = lowercase(NEW.my_char_field);  
  RETURN NEW;
end;
$BODY$
  LANGUAGE plpgsql VOLATILE;

CREATE TRIGGER biu_lowercase_field
  BEFORE INSERT OR UPDATE
  ON mytable
  FOR EACH ROW
  EXECUTE PROCEDURE fun_trg_lowercase();

答案 1 :(得分:2)

Check constraint

create table project_types (
    id char(20) not null unique default 'xxx'
    check (id = lower(id))
);

答案 2 :(得分:1)

您可以为此目的使用特殊类型的数据,称为CITEXT(=不区分大小写的文本)。它是PostgreSQL中另外提供的模块标准。

引用PostgreSQL documentation on CITEXT

  

F.8.1。理

     

在PostgreSQL中进行不区分大小写的匹配的标准方法是在比较值时使用lower函数,例如

SELECT * FROM tab WHERE lower(col) = LOWER(?);
     

这种方法运作得相当好,但有许多缺点:

     

它使您的SQL语句冗长,并且您始终必须记住在列和查询值上使用lower。

     

它不会使用索引,除非您使用lower。

创建功能索引      

如果将列声明为UNIQUEPRIMARY KEY,则隐式生成的索引区分大小写。因此,对于不区分大小写的搜索没有用处,并且它不会不区分大小写地强制执行唯一性。

     

citext数据类型允许您消除SQL查询中较低的调用,并允许主键不区分大小写。 citext是语言环境感知的,就像文本一样,这意味着大写和小写字符的匹配取决于数据库LC_CTYPE设置的规则。同样,此行为与查询中较低的使用相同。但由于数据类型透明地完成了这项工作,因此您不必记住在查询中做任何特别的事情。

因此,在您的具体情况下,您只需要这样做:

一次:

CREATE EXTENSION citext ;

CREATE TABLE project_types 
(
    id citext PRIMARY KEY default 'xxx'
);

CREATE TABLE other_table 
(
     /* ... */
   fk_ptype citext,
   fk_ptype_on_other_table foreign key (fk_ptype) references project_type(id)
);

...然后,对您的查询执行 nothing 。没有任何额外的限制,也没有任何(显然是可怕的)触发器。