我们的产品有一个核心模块和几个可选插件.
可选插件通过1:1关系扩展ticket_type表.该表称为myplugin_ticket_type_extension.
对于myplugin_ticket_type_extension中的每一行,ticket_type中都有一行.这通过ForeignKey强制执行.到目前为止问题:-)
现在困难的部分:如何强制在ticket_type中的每一行myplugin_ticket_type_extension中都有一行?
解决方法
执行此操作的最简单方法是向ticket_type添加第二个外键,该外键引用扩展表.
这种循环依赖的难点在于,在您有机会创建另一条记录之前,INSERT到任一表都会违反外键约束.您可以通过使用延迟约束来避免这种情况,延迟约束会延迟外键检查,直到事务提交为止:
CREATE TABLE ticket_type (id INT PRIMARY KEY); CREATE TABLE myplugin_ticket_type_extension ( id INT PRIMARY KEY,ticket_type_id INT UNIQUE NOT NULL FOREIGN KEY REFERENCES ticket_type (id) DEFERRABLE INITIALLY DEFERRED ); ALTER TABLE ticket_type ADD FOREIGN KEY (id) REFERENCES myplugin_ticket_type_extension (ticket_type_id) DEFERRABLE INITIALLY DEFERRED; BEGIN; INSERT INTO ticket_type VALUES (1); INSERT INTO myplugin_ticket_type_extension VALUES (1,1); COMMIT;
可能值得考虑的另一种方法是使用table inheritance:
CREATE TABLE ticket_type (id INT PRIMARY KEY); CREATE TABLE myplugin_ticket_type_extension (extension_field INT) INHERITS (ticket_type); INSERT INTO myplugin_ticket_type_extension (id,extension_field) VALUES (1,1);
查询ticket_type时,将显示插入扩展表的记录,因此核心模块应不受影响.您可以通过添加触发器来直接阻止插入到ticket_type表中,该触发器可以完全阻止插入(通过引发异常),也可以自动将新记录重定向到扩展表:
CREATE FUNCTION ticket_type_trg() RETURNS TRIGGER AS $$ BEGIN INSERT INTO myplugin_ticket_type_extension (id) VALUES (new.id); RETURN NULL; END $$ LANGUAGE plpgsql; CREATE TRIGGER ticket_type_trg BEFORE INSERT ON ticket_type FOR EACH ROW EXECUTE PROCEDURE ticket_type_trg();
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。