是什么导致错误:没有唯一的约束条件匹配给定表的键?


154

下面的示例表结构给出了一个错误:没有唯一的约束条件匹配给定表的键,并且盯着它看了好一会儿,现在我不知道为什么在这种情况下会出现此错误。

BEGIN;

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

COMMIT;

运行上面的代码会给出以下错误,对我来说这没有意义,任何人都可以解释为什么会出现此错误。我正在使用postgres 9.1

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

Answers:


188

这是因为表name上的bar列没有UNIQUE约束。

所以,想象一下你对2行bar包含名称表'ams'和你插入一行baz'ams'bar_fk,该行的bar会是指因为有两行相匹配?


1
完美简短,准确易懂的解释!
亚历克斯

79

在postgresql中,所有外键都必须在父表中引用一个唯一键,因此在bar表中必须有一个unique (name)索引。

另请参见http://www.postgresql.org/docs/9.1/static/ddl-constraints.html#DDL-CONSTRAINTS-FK,尤其是:

最后,我们应该提到外键必须引用作为主键或形成唯一约束的列。

强调我的。


21
为什么声明的PK不被视为唯一约束?并不是您可以拥有一个非唯一的PK ...
两栖机器人,2013年

2
它在它“指向”的表上必须是唯一的,因为如果不是,数据库引擎将无法知道您实际指向的行。
Matteo Tassinari

复合键?@amphibient
迷人的机器人

1
我认为有对父表中所引用的列的唯一密钥不仅而且它其他RDBMS太像Oracle,SQL服务器等,在PostgreSQL的要求
Mufachir·侯赛因

2
请注意,答案也适用于复合外键,其中在父表上需要复合唯一约束或主键。
忍者观音

8

当您UNIQUE像完成表级约束一样操作时,定义的内容有点像复合主键,请参见ddl约束,这是摘录

"This specifies that the *combination* of values in the indicated columns is unique across the whole table, though any one of the columns need not be (and ordinarily isn't) unique."

这意味着要么字段可能可能有一个非唯一的值提供的组合是唯一的并且与您的外键约束不匹配。

您最有可能希望约束位于列级别。因此,而不是将它们定义为表级约束,“追加”UNIQUE到列定义的末尾,name VARCHAR(60) NOT NULL UNIQUE或者为每个字段指定单个表级约束。


在我的情况下,列级约束不起作用,我确实应该定义一个复合主键,但是我放弃了它,因为将其映射到JPA有点痛苦:)
2012年

6

您应该将“名称”列作为唯一约束。这是3行代码来更改您的问题

  1. 首先通过键入以下代码找出主键约束

    \d table_name

    您在下方显示为 "some_constraint" PRIMARY KEY, btree (column)

  2. 删除约束:

    ALTER TABLE table_name DROP CONSTRAINT some_constraint
  3. 用现有的添加一个新的主键列:

    ALTER TABLE table_name ADD CONSTRAINT some_constraint PRIMARY KEY(COLUMN_NAME1,COLUMN_NAME2);

就这样。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.