我正在尝试构建我的第一个涉及继承的Postgres数据库模式。我知道PostgreSQL foreign key not existing, issue of inheritance?中讨论的外键问题。但是,这个问题的答案并没有真正为解决方案提供一个例子,所以我提出了自己的想法(灵感来自http://people.planetpostgresql.org/dfetter/index.php?/archives/51-Partitioning-Is-Such-Sweet-Sorrow.html):
CREATE TABLE a (
id SERIAL PRIMARY KEY INITIALLY DEFERRED,
foo TEXT
);
CREATE TABLE b (
PRIMARY KEY(id),
a_number REAL
) inherits(a);
CREATE TABLE c (
PRIMARY KEY(id),
a_number INTEGER
) inherits(a);
-- SELECT * FROM ONLY a; will always return an empty record.
CREATE TABLE x (
a_id INTEGER NOT NULL,
bar TEXT
);
CREATE TABLE xb (
FOREIGN KEY( a_id ) REFERENCES b INITIALLY DEFERRED
) inherits(x);
CREATE TABLE xc (
FOREIGN KEY( a_id ) REFERENCES c INITIALLY DEFERRED
) inherits(x);
为了执行工作INSERT INTO x
,我定义了以下触发器:
CREATE FUNCTION marshal_x()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
DECLARE
ref_table varchar;
BEGIN
SELECT INTO ref_table p.relname FROM a, pg_class p WHERE a.id = NEW.a_id AND a.tableoid = p.oid;
IF ref_table = 'b'
THEN INSERT INTO xb ( a_id, bar ) VALUES ( NEW.a_id, NEW.bar );
ELSIF ref_table = 'c'
THEN INSERT INTO xc ( a_id, bar ) VALUES ( NEW.a_id, NEW.bar );
END IF;
RETURN NULL;
END;
$$;
CREATE TRIGGER insert_x_trg
BEFORE INSERT ON x
FOR EACH ROW
EXECUTE PROCEDURE marshal_x();
编辑:有没有人看到这个定义有问题,这对我未经训练的眼睛来说并不明显?
假设表c
为空。会表现
SELECT * FROM a JOIN x ON a.id= x.a_id;
与
相同SELECT * FROM b JOIN x ON b.id= x.a_id;
?非常感谢提前。
ISAM
答案 0 :(得分:2)
无论如何使用继承的目的是什么?如果您只想根据行类型使用不同的列,例如在OOP中,最好使用单个表并在不适用的列中放置NULL。或者将其他列拆分为另一个表,您将其加入到原始表中。
PostgreSQL中继承的主要用途是表分区,并且有许多带有继承的警告。 PostgreSQL 9.1引入了一个“Merge Append”优化,它有所帮助,但它仍然不是最理想的。
SELECT * FROM JOIN x ON a.id = x.a_id;
将两个大型继承的表连接在一起听起来好像不能很好地扩展,特别是当你增加子表的数量时。 PostgreSQL不够聪明,不能遵循这里的xb和xc外键约束,它会尝试将整个表 a 连接到整个 x 。
但话又说回来,它可能会成为一个问题,这一切都取决于你的疑问和业绩预期。