尝试在Postgres 9.1中创建这个示例表结构:

CREATE TABLE foo (
    name        VARCHAR(256) PRIMARY KEY
);

CREATE TABLE bar (
    pkey        SERIAL PRIMARY KEY,
    foo_fk      VARCHAR(256) NOT NULL REFERENCES foo(name), 
    name        VARCHAR(256) NOT NULL, 
    UNIQUE (foo_fk,name)
);

CREATE TABLE baz(   
    pkey        SERIAL PRIMARY KEY,
    bar_fk      VARCHAR(256) NOT NULL REFERENCES bar(name),
    name        VARCHAR(256)
);

运行上面的代码会产生一个错误,这对我来说没有意义:

NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "foo_pkey" for table "foo" NOTICE: CREATE TABLE will create implicit sequence "bar_pkey_seq" for serial column "bar.pkey" NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "bar_pkey" for table "bar" NOTICE: CREATE TABLE / UNIQUE will create implicit index "bar_foo_fk_name_key" for table "bar" NOTICE: CREATE TABLE will create implicit sequence "baz_pkey_seq" for serial column "baz.pkey" NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "baz_pkey" for table "baz" ERROR: there is no unique constraint matching given keys for referenced table "bar"

********** Error **********

ERROR: there is no unique constraint matching given keys for referenced table "bar"
SQL state: 42830

有人能解释为什么会出现这个错误吗?


当前回答

当你把UNIQUE作为一个表级约束时,你的定义有点像一个复合主键,请看ddl约束,这里是一个提取

这指定所指示列中的值的组合在整个表中是惟一的,尽管任何列都不需要是惟一的(通常也不是惟一的)。

这意味着任何一个字段都可能具有非惟一值,前提是组合是惟一的,并且这与外键约束不匹配。

大多数情况下,您希望约束位于列级。因此,与其将它们定义为表级约束,不如将' UNIQUE '附加到列定义的末尾,如名称VARCHAR(60) NOT NULL UNIQUE或为每个字段指定单独的表级约束。

其他回答

您应该将name列作为唯一的约束。这里有3行代码来改变你的问题

首先通过键入以下代码找出主键约束 \ d table_name 你会在下面这样显示:"some_constraint"主键,btree(列) 删除约束: DROP CONSTRAINT删除约束 用现有的主键列添加一个新的主键列: ALTER TABLE table_name ADD CONSTRAINT (COLUMN_NAME1,COLUMN_NAME2);

这是所有。

当你把UNIQUE作为一个表级约束时,你的定义有点像一个复合主键,请看ddl约束,这里是一个提取

这指定所指示列中的值的组合在整个表中是惟一的,尽管任何列都不需要是惟一的(通常也不是惟一的)。

这意味着任何一个字段都可能具有非惟一值,前提是组合是惟一的,并且这与外键约束不匹配。

大多数情况下,您希望约束位于列级。因此,与其将它们定义为表级约束,不如将' UNIQUE '附加到列定义的末尾,如名称VARCHAR(60) NOT NULL UNIQUE或为每个字段指定单独的表级约束。

这是因为条形表上的名称列没有UNIQUE约束。

想象一下,在bar表中有两行包含名称“ams”,在baz上插入一行,在bar_fk上插入一行“ams”,既然有两行匹配,它将引用bar上的哪一行?

在postgresql中,所有外键都必须引用父表中的唯一键,所以在你的条形表中,你必须有一个唯一的(name)索引。

参见http://www.postgresql.org/docs/9.1/static/ddl-constraints.html#DDL-CONSTRAINTS-FK,具体来说:

最后,我们应该提到外键必须引用列 要么是主键,要么形成唯一约束。

我特别强调。