12

在 PostgreSQL 中是否可以有条件地添加外键?

就像是:ALTER TABLE table1 ADD FOREIGN KEY (some_id) REFERENCES other_table WHERE some_id NOT IN (0,-1) AND some_id IS NOT NULL;

具体来说,我的参考表具有所有正整数 (1+),但我需要添加外键的表可以包含零 (0)、空和负一 (-1),所有这些都意味着不同的东西。

笔记:

我完全意识到这是糟糕的表格设计,但这是 10 多年前建立的一个聪明的把戏,当时我们可用的功能和资源并不存在。该系统正在运行数百家零售店,因此此时返回并更改方法可能需要几个月的时间,而我们没有。

我不能使用触发器,这必须使用外键来完成

4

5 回答 5

5

简短的回答是否定的,Postgres 没有条件外键。您可能会考虑的一些选项是:

  1. 只是没有 FK 约束。将此逻辑移至数据访问层并在没有参照完整性的情况下生存。
  2. 在列中允许NULL,即使有 FK 约束也是完全有效的。然后,使用另一列存储0and-1的任何含义。
  3. 0在引用表中为和添加一个虚拟行-1。即使它只是有虚假数据,它也会满足 FK 约束。

希望这可以帮助!

于 2012-06-05T16:07:46.827 回答
3

您可以添加另一个“影子”列,table1其中包含已清理的值(即除0and之外的所有内容-1)。使用此列进行参照完整性检查。这个影子列由一个简单的触发器更新/填充,该触发器将table1所有值写入影子列。两者和都可以映射到.0-10-1null

然后你有参考完整性和你不变的原始列。缺点:您还有一些触发器和一些冗余数据。但是,唉,这是遗留模式的命运!

于 2012-06-05T17:42:56.283 回答
2

您的要求等效于此检查约束:

create table t (a float check (a >= -1 and a = floor(a) or a is null));
于 2012-06-05T16:33:11.013 回答
2

您可以使用检查约束和外键来实现这一点。

CREATE TABLE table1 (some_id INT, some_id_fkey INT REFERENCES other_table(other_id), CHECK (some_id IN (0,-1) OR some_id IS NOT DISTINCT FROM some_id_fkey));

(未测试)

于 2017-04-18T00:41:14.430 回答
1

Here's another possibility. Use PG Inheritance to enforce a partition of the table into has +1 in the flag column and otherwise. (Usual rules/triggers for maintaining this.) Then have the FK relationship between only the Has_PLUS_ONE child table and the referenced table.

于 2012-06-08T21:56:19.083 回答