简体   繁体   English

PostgreSQL没有唯一约束错误

[英]postgresql no unique constraint error

I get for this schema this error: 我为这个模式得到这个错误:

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

What I am doing wrong? 我做错了什么? EDIT: now I add a column krankenhaus to the table mitarbeiter and change the alter table command but I get the same error... 编辑:现在我将列krankenhaus添加到表mitarbeiter并更改alter table命令,但是我得到相同的错误...

SCHEMA: 模式:

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;

The primary key of the table Abteilung is (abid, krankenhaus) . Abteilung的主键是(abid, krankenhaus) As a foreign references references exactly one row, you also need to use both columns in the foreign key constraint definition. 由于外部引用仅引用一行,因此您还需要在外键约束定义中同时使用列。

But as you don't have a column krankenhaus in your table Mitarbeiter you can't reference Abteilung . 但是当你没有列krankenhaus在你的表Mitarbeiter你不能引用Abteilung

You either need to reduce the primary key of Abteilung to (abid) (which would be possible as it is a generated, artificial key anyway) or add a column Krankenhaus to your Mitarbeiter table. 您或者需要将Abteilung的主键减小为(abid) (因为无论如何它都是生成的人工键,这都是可能的),或者在Mitarbeiter表中添加一列Krankenhaus

This should work: 这应该工作:

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;

Major points 要点

  • Use a serial column for surrogate PKs: serial列用于替代PK:

  • Don't use varchar(n) with arbitrary limitations for string length, unless you really need to enforce a maximum length and its not going to change. 请勿对字符串长度使用具有任意限制的varchar(n) ,除非您确实需要强制执行最大长度且该长度不会改变。 Details: 细节:

  • Go with just abid as primary key for abteilung . 一起去的只是abid作为主键abteilung There would be a related application for a redundant column included in a FK constraint, but that's not what your model does right now: 是包含在FK约束冗余列相关的应用程序,但是这是你的模型确实现在不是:

  • No need to use an explicit transaction ( BEGIN ... COMMIT ) for part of the code. 无需为部分代码使用显式事务( BEGIN ... COMMIT )。

  • The real difficulty with this kind of circular reference is entering and changing data. 这种循环引用的真正困难在于输入和更改数据。 You probably made your FK constraints DEFERRABLE INITIALLY DEFERRED - which is going to make some queries considerably slower . 您可能使FK约束DEFERRABLE INITIALLY DEFERRED -这将使某些查询变得相当
    You could go with just plain default IMMEDIATE FK constraints, if you wrap INSERT / UPDATE on related rows into data-modifying CTEs : 如果将相关行上的INSERT / UPDATE包装到可修改数据的CTE中 ,则可以使用普通的默认IMMEDIATE FK约束:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM