导致错误的原因是:没有唯一约束匹配引用表的给定键?

ams*_*ams 122 sql postgresql

下面的示例表结构给出了一个错误:没有唯一约束匹配引用表的给定键,并且已经盯着它现在我无法弄清楚为什么在这种情况下出现此错误.

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;
Run Code Online (Sandbox Code Playgroud)

运行上面的代码会出现以下错误,这对我来说没有意义,任何人都可以解释为什么会出现这个错误.我正在使用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
Run Code Online (Sandbox Code Playgroud)

Die*_*ego 133

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

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

  • 也许他们两个?这不是一对多关系的工作原理吗? (5认同)

Mat*_*ari 66

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

另见http://www.postgresql.org/docs/9.1/static/ddl-constraints.html#DDL-CONSTRAINTS-FK,具体如下:

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

强调我的.

  • 为什么声明的PK不被认为是一个独特的约束?这不像你可以拥有一个非独特的PK ...... (17认同)
  • 它在它“指向”的表上必须是唯一的,因为如果不是,数据库引擎将无法知道您实际指的是哪一行。 (2认同)
  • 请注意,对于复合外键也是如此,其中父表上需要复合唯一约束或主键。 (2认同)

Har*_*thi 12

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

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

    \d table_name
    
    Run Code Online (Sandbox Code Playgroud)

    你在底部是这样显示的 "some_constraint" PRIMARY KEY, btree (column)

  2. 删除约束:

    ALTER TABLE table_name DROP CONSTRAINT some_constraint
    
    Run Code Online (Sandbox Code Playgroud)
  3. 使用现有的主键列添加一个新的主键列:

    ALTER TABLE table_name ADD CONSTRAINT some_constraint PRIMARY KEY(COLUMN_NAME1,COLUMN_NAME2);
    
    Run Code Online (Sandbox Code Playgroud)

就这样。


T I*_*T I 5

当您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."
Run Code Online (Sandbox Code Playgroud)

这意味着,如果组合是唯一的,并且与外键约束不匹配,则两个字段都可能具有非唯一值。

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