【问题标题】:ERROR: there is no unique constraint matching given keys for referenced table "abteilung"错误:没有唯一约束匹配引用表“abteilung”的给定键
【发布时间】:2014-12-23 04:51:41
【问题描述】:

我收到此错误:

ERROR:  there is no unique constraint matching given keys for referenced table "abteilung"

对于这个架构:

CREATE TABLE Person (
    svnr VARCHAR(40) PRIMARY KEY,
    anschrift VARCHAR(40) NOT NULL,
    name VARCHAR(20) NOT NULL
);

BEGIN;

CREATE TABLE Mitarbeiter (
    svnr VARCHAR(40) PRIMARY KEY REFERENCES Person(svnr),
    beschaeftigt_seit DATE NOT NULL,
    gehalt NUMERIC(5,2),
    CHECK(gehalt > 0),
    abteilung INTEGER NOT NULL,
    krankenhaus INTEGER NOT NULL
);

CREATE TABLE Krankenhaus (
    kid INTEGER PRIMARY KEY DEFAULT nextval('seq_krankenhaus'),
    anschrift VARCHAR(40) NOT NULL,
    name VARCHAR(20) NOT NULL,
    geleitet_von VARCHAR(40) REFERENCES Mitarbeiter(svnr) DEFERRABLE INITIALLY DEFERRED
);

CREATE TABLE Abteilung (
    abid INTEGER DEFAULT nextval('seq_abteilung'),
    name VARCHAR(40) NOT NULL,
    anschrift VARCHAR(40) NOT NULL,
    koordiniert VARCHAR(40) REFERENCES Mitarbeiter(svnr) DEFERRABLE INITIALLY DEFERRED,
    krankenhaus INTEGER REFERENCES Krankenhaus(kid),
    PRIMARY KEY (abid, krankenhaus)
);

ALTER TABLE Mitarbeiter ADD CONSTRAINT fk_abteilung FOREIGN KEY (abteilung, krankenhaus) REFERENCES Abteilung(abid, krankenhaus) DEFERRABLE INITIALLY DEFERRED;

COMMIT;

我做错了什么?

在将列krankenhaus 添加到表mitarbeiter 并更改alter table 命令后,我仍然收到相同的错误...

【问题讨论】:

  • 在您应用@a_horse 的建议后,错误消息与您的代码相矛盾。它应该工作。不过,您确实选择了较差的选项。您最好删除多余的mitarbeiter.krankenhaus,只使用abid 进行PK 和FK。

标签: postgresql database-design foreign-keys


【解决方案1】:

Abteilung 的主键是(abid, krankenhaus)。由于外部引用仅引用一行,因此您还需要在外键约束定义中使用 both 列。

但由于您的表 Mitarbeiter 中没有列 krankenhaus,因此您无法引用 Abteilung

您要么需要将Abteilung 的主键减少到(abid)(这是可能的,因为它是生成的人工键),或者将Krankenhaus 列添加到Mitarbeiter 表中。

【讨论】:

  • 哦,是的,谢谢!但现在我按照你说的做了修改(见代码),但我得到了同样的错误
【解决方案2】:

这应该可行:

CREATE TABLE person (
   svnr text PRIMARY KEY
 , anschrift text NOT NULL
 , name text NOT NULL
);

CREATE TABLE mitarbeiter (
   svnr text PRIMARY KEY REFERENCES person
 , beschaeftigt_seit date NOT NULL
 , gehalt numeric(5,2)
 , abid int NOT NULL
 , CHECK(gehalt > 0)
);

CREATE TABLE krankenhaus (
   kid serial PRIMARY KEY
 , anschrift text NOT NULL
 , name text NOT NULL
 , geleitet_von text REFERENCES mitarbeiter(svnr) DEFERRABLE INITIALLY DEFERRED
);

CREATE TABLE abteilung (
   abid serial PRIMARY KEY
 , kid INTEGER REFERENCES krankenhaus(kid)
 , koordiniert text REFERENCES mitarbeiter(svnr) DEFERRABLE INITIALLY DEFERRED
 , name text NOT NULL
 , anschrift text NOT NULL
);

ALTER TABLE mitarbeiter
   ADD CONSTRAINT fk_abteilung FOREIGN KEY (abid)
   REFERENCES abteilung(abid) DEFERRABLE INITIALLY DEFERRED;

为代理 PK 使用 serial 列:

不要使用varchar(n) 对字符串长度进行任意限制,除非您确实需要 强制规定最大长度并且它不会改变。见:

只使用abid 作为abteilung 的主键。对于 FK 约束中包含的冗余列,会有一个相关的应用程序,但这不是您的模型现在所做的:

部分代码无需使用显式事务 (BEGIN ... COMMIT)。

这些循环引用的真正困难在于输入和更改数据。您可能设置了 FK 约束 DEFERRABLE INITIALLY DEFERRED - 这将使一些查询大大变慢
可以使用简单的默认 IMMEDIATE FK 约束,如果您将相关行上的 INSERT / UPDATE 包装到 数据修改 CTE 中。见:

【讨论】:

  • 谢谢!但我需要 abteilung 和 mitarbeiter 中的 krankenhaus 列,因为 abteilung 是 krankenhaus 的弱实体
  • @prodi22:weaky entity 是什么?无论哪种方式,abteilung.kid 都应该是您所需要的。
猜你喜欢
  • 1970-01-01
  • 2016-08-13
  • 2012-08-11
  • 2021-06-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多