Postgresql 是否可以创建始终为小写的char列?

Postgresql 是否可以创建始终为小写的char列?,postgresql,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) ); 问题是,我希

我想创建一个如下表:

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_type
中的所有值都自动变为小写:我不希望对每个可能的查询进行转换,我希望有一个表,无论我对它抛出什么,它都返回小写标记

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

对于那些可能建议我使用enum的类型:类型是动态的,所以我更喜欢这种方法

更新2017.04.17:这个问题的想法不是将控件/转换放在堆栈中的每一个地方:如果数据库可以处理您向它抛出的任何东西,那么您不必1。在前端检查/转换,2。在后端代码中检查/转换,最后是3。在数据库中检查/转换。您只需避免执行1和2,因为您知道数据库将处理您向它抛出的任何内容,并且当您从中选择时,您将获得正确的数据

我很想选择答案,但似乎相同的方法无法用于删除(我尝试使用相同的函数设置和删除触发器,但没有起作用)。

:


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

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();

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

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();

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

引用:

F.8.1。理由

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

SELECT * FROM tab WHERE lower(col) = LOWER(?);
这项工作相当不错,但也有一些缺点:

这会使SQL语句变得冗长,并且您必须始终记住在列和查询值上使用lower

它不会使用索引,除非您使用lower创建函数索引

如果将列声明为
唯一
主键
,则隐式生成的索引区分大小写。因此,它对于不区分大小写的搜索是无用的,并且它不会在不区分大小写的情况下强制唯一性

citext数据类型允许您在SQL查询中消除对lower的调用,并允许主键不区分大小写。citext与文本一样具有区域设置意识,这意味着大写和小写字符的匹配取决于数据库的LC_CTYPE设置规则。同样,此行为与使用lower in查询相同。但是因为它是由数据类型透明地完成的,所以您不必记住在查询中执行任何特殊操作

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

一次:

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)
);

。。。然后,对您的查询不做任何处理。没有任何额外的约束,也没有任何(明显令人害怕的)触发器。

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

引用:

F.8.1。理由

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

SELECT * FROM tab WHERE lower(col) = LOWER(?);
这项工作相当不错,但也有一些缺点:

这会使SQL语句变得冗长,并且您必须始终记住在列和查询值上使用lower

它不会使用索引,除非您使用lower创建函数索引

如果将列声明为
唯一
主键
,则隐式生成的索引区分大小写。因此,它对于不区分大小写的搜索是无用的,并且它不会在不区分大小写的情况下强制唯一性

citext数据类型允许您在SQL查询中消除对lower的调用,并允许主键不区分大小写。citext与文本一样具有区域设置意识,这意味着大写和小写字符的匹配取决于数据库的LC_CTYPE设置规则。同样,此行为与使用lower in查询相同。但是因为它是由数据类型透明地完成的,所以您不必记住在查询中执行任何特殊操作

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

一次:

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)
);

。。。然后,对您的查询不做任何处理。没有任何额外的约束,也没有任何(显然令人害怕的)触发器。

他想要自动更改案例,所以需要触发器或触发器rules@VaoTsun这是答案的一半,因为触发器不太可靠。@ClodoaldoNeto:为什么触发器不可靠?@joanolo,因为程序员不可靠。@joanolo可能是的。但是更改或删除约束是设计更改,但是临时禁用触发器通常不被认为是设计更改(这样做并不罕见)。我并不是说触发器解决方案无效,但在OP的情况下,将此逻辑放在应用程序的存储库层要容易得多。db中的约束可以进行完整性检查。他想要自动改变大小写,所以需要触发器或rules@VaoTsun这是答案的一半,因为触发器不太可靠。@ClodoaldoNeto:为什么触发器不可靠?@joanolo,因为程序员不可靠。@joanolo可能是的。但是改变或删除约束是设计更改,但暂时禁用触发器通常不被视为一个(这样做并不罕见)。我并不是说触发器解决方案无效,但在OP的情况下,将此逻辑放在应用程序的存储库层要容易得多。