【问题标题】:case insensitive Foreign Key PostgreSQL不区分大小写的外键 PostgreSQL
【发布时间】:2014-10-15 17:43:33
【问题描述】:

需要知道我是否可以在 PostgreSQL 中的表中添加不区分大小写的外键约束。我正在将数据库从 MySQL 转换为 PostgreSQL。外键已经在 MySQL 中创建,我没有遇到任何问题,因为 MySQL 不区分大小写。当我将所有数据从 MySQL 加载到 PostgreSQL,然后尝试向表中添加外键时,我在 Postgres 中收到错误消息。例如:

表 A 有 2 列: ID (int) 和 Name(varchar(25))

Entry1: ID = 1 , Name = 'America' Entry2: ID = 2 , Name = 'Canada'

表 B 有 2 列: ID (int) 和 Name(varchar(25))

Entry1: ID(int) = 10 , Name(Varchar(25)) = 'AmeRiCA' Entry1: ID = 1 , Name = 'Canada'

在 MySQL 中,外键是在“名称”列上的表 A 和表 B 之间创建的,但是在 Postgres 中,由于区分大小写的性质,我得到了一个错误。

我没有更改表格并将 Varchar 更改为 citext 的选项。无论如何我可以在PG中定义一个不区分大小写的外键。

有什么建议吗?

谢谢

【问题讨论】:

  • 您的问题很有趣,但我很好奇...为什么您更愿意使用名称作为键(创建 fk)而不是 id?
  • @JorgeCampos -- 当我开始查看这个数据库时,这就是我想到的同一个问题。这个数据库已经创建并交给了我。那么,您认为有什么办法可以完成这项任务吗?
  • 我认为如果没有 citext 选项,您必须在插入/更新/删除之前创建一个触发器,以使用较低或较高的函数检查该行是否存在。我知道,它很丑!

标签: sql postgresql case-sensitive postgresql-9.3


【解决方案1】:

到目前为止,您能做的最好的事情就是更正您的数据。比如这样:

update A set name=initcap(name) where name<>initcap(name);
update B set name=initcap(name) where name<>initcap(name);

如果不可接受,那么您可以在两个表中创建额外的列,例如 name_lower,这将使用触发器自动设置为 lower(name)

create or replace function name_lower_trigger() returns trigger as $$
  begin
    NEW.name_lower=lower(name);
    return NEW;
  end;
$$ language plpgsql;

create trigger a_name_lower_trigger
  before insert or update on a
  for each row execute procedure name_lower_trigger();
create trigger b_name_lower_trigger
  before insert or update on b
  for each row execute procedure name_lower_trigger();

并使用这些列创建外键约束。但它会使数据库非规范化并浪费存储空间,而且很丑陋。更正您的数据会更好。

【讨论】:

  • 这几乎是唯一明智的解决方案。唯一的另一种选择是实现您自己的外键触发器,进行强制小写比较或类似的操作。
猜你喜欢
  • 2014-02-15
  • 1970-01-01
  • 2011-01-14
  • 1970-01-01
  • 2013-04-25
  • 1970-01-01
  • 1970-01-01
  • 2015-04-22
  • 2016-11-15
相关资源
最近更新 更多