PostgreSQL外键不存在,继承问题?
我正在数据库中处理外键,可能与继承有关?PostgreSQL外键不存在,继承问题?,postgresql,inheritance,foreign-keys,Postgresql,Inheritance,Foreign Keys,我正在数据库中处理外键,可能与继承有关? 以下是基本设置: -- table address CREATE TABLE address ( pk_address serial NOT NULL, fk_gadmid_0 integer NOT NULL, -- this table already exists, no problem here street character varying(100), zip character varying(10), city cha
以下是基本设置:
-- table address
CREATE TABLE address
(
pk_address serial NOT NULL,
fk_gadmid_0 integer NOT NULL, -- this table already exists, no problem here
street character varying(100),
zip character varying(10),
city character varying(50),
public boolean,
CONSTRAINT address_primarykey PRIMARY KEY (pk_address),
CONSTRAINT gadmid_0_primarykey FOREIGN KEY (fk_gadmid_0)
REFERENCES adm0 (gadmid_0) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE NO ACTION
)
WITH (
OIDS=FALSE
);
ALTER TABLE address OWNER TO postgres;
-- table stakeholder (parent)
CREATE TABLE stakeholder
(
pk_stakeholder integer DEFAULT nextval('common_stakeholder_seq') NOT NULL,
fk_stakeholder_type integer NOT NULL, -- this table also exists, no problem here
name character varying(255) NOT NULL,
CONSTRAINT stakeholder_primarykey PRIMARY KEY (pk_stakeholder),
CONSTRAINT stakeholder_fk_stakeholder_type FOREIGN KEY (fk_stakeholder_type)
REFERENCES stakeholder_type (pk_stakeholder_type) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE NO ACTION
)
WITH (
OIDS=FALSE
);
ALTER TABLE stakeholder OWNER TO postgres;
-- table individual (child of stakeholder)
CREATE TABLE individual
(
firstname character varying(50),
fk_title integer, -- this table also exists, no problem here
email1 character varying (100),
email2 character varying (100),
phone1 character varying (50),
phone2 character varying (50),
CONSTRAINT individual_primarykey PRIMARY KEY (pk_stakeholder),
CONSTRAINT title_foreignkey FOREIGN KEY (fk_title)
REFERENCES title (pk_title) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE CASCADE
) INHERITS (stakeholder)
WITH (
OIDS=FALSE
);
ALTER TABLE individual OWNER TO postgres;
-- link between stakeholder and address
CREATE TABLE l_stakeholder_address
(
pk_l_stakeholder_address serial NOT NULL,
fk_stakeholder integer NOT NULL REFERENCES stakeholder,
fk_address integer NOT NULL REFERENCES address,
CONSTRAINT l_stakeholder_address_primarykey PRIMARY KEY (pk_l_stakeholder_address),
CONSTRAINT l_stakeholder_address_fk_stakeholder FOREIGN KEY (fk_stakeholder)
REFERENCES stakeholder (pk_stakeholder) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE NO ACTION,
CONSTRAINT l_stakeholder_address_fk_address FOREIGN KEY (fk_address)
REFERENCES address (pk_address) MATCH SIMPLE
ON UPDATE CASCADE ON DELETE NO ACTION
)
WITH (
OIDS=FALSE
);
ALTER TABLE l_stakeholder_address OWNER TO postgres;
到目前为止,没有问题。然后我尝试添加一些值:
INSERT INTO individual (pk_stakeholder, fk_stakeholder_type, name, firstname, fk_title, email1, email2, phone1, phone2)
VALUES (1, 8, 'Lastname', 'Firstname', 1, 'me@you.com', '', '', '');
INSERT INTO address (pk_address, fk_gadmid_0, street, zip, city, public)
VALUES (1, 126, 'Address', '', 'City', FALSE);
INSERT INTO l_stakeholder_address (pk_l_stakeholder_address, fk_stakeholder, fk_address)
VALUES (DEFAULT, 1, 1);
最后,我出现了一个错误(SQL状态23503),表示表“干系人”中不存在键(fk_干系人)=(1)。前2个插入很好,我可以在数据库中看到它们:
stakeholder:
pk_stakeholder | ...
----------------------
1 | ...
address:
pk_address | ...
--------------------
1 | ...
我做错了什么?我必须承认我对PostgreSQL(使用8.4)相当陌生,但我甚至不确定这是否是PG的问题,也许我只是缺乏一些基本的数据库设计理解…不管怎样,到现在为止,我几乎用尽了我所能想到的一切,我也试着让FK像中一样可以推迟,但不知何故,这也不起作用。你的分析完全正确:这是因为继承。检查外键时,不考虑子表 一般来说,继承和外键在PostgreSQL中不能很好地混合。一个主要的问题是,不能跨表使用唯一的约束
您可以使用附加的表
individual\u pks(individual\u pk integer主键)
和来自父级和子级的所有主键来解决此问题,这些主键将使用触发器进行维护(非常简单-插入时插入到个人密码
,删除时删除,更新时更新,如果更改个人密码
)
然后将外键指向这个附加表,而不是子表。这会对性能造成一些小的影响,但只有在添加/删除行时
或者忘记继承,用老方法来做——只需一个表,其中包含一些可为空的列。感谢您的快速回答。我的理解是,子表在这里并不重要,因为它们没有PK(继承的PK除外),FK引用父表(正确存储了PK).但显然我错了(尽管我不知道确切原因).那么有什么方法可以满足我的要求吗?也许可以使用触发器检查链接表中的fk_涉众是否存在于涉众的PK中?这里不关心主键。外键fk_涉众指向表涉众,但其中没有匹配行。表中的行不被考虑。老实说,我仍然不明白。外键指向干系人.pk_干系人,它的存在是因为它被它的子表插入。我想这就是问题所在——但行仍然存在。正如干系人在上面的另一个解决方案中一样。我想我在这个问题上缺乏一些基本的理解。但是vermind,我不想再占用你的时间了,使用Tometzky提出的解决方案似乎是可行的。但无论如何,非常感谢你的帮助!运行
SELECT*FROM ONLY涉众
。FK检查就是这样做的。那里没有行。一个解决方案解决了继承带来的复杂性,尤其是期望要共享继承的ID属性:创建一个触发器,每个子表触发该触发器,以在所有子表中强制执行RI。这类似于单表RI检查,但速度没有那么快。它实现了大多数开发人员在发现继承并基于净收益假设开始使用它时所期望的模式。非常感谢您的支持wer,我成功地用这种方式解决了我的问题。但是,我宁愿使用“干系人”而不是“个人”。因为干系人是父表。所以“干系人”收集“干系人”及其子表的所有主键。谢谢!