加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

PostgreSQL:对可选插件强制执行1:1

发布时间:2020-12-13 16:01:51 所属栏目:百科 来源:网络整理
导读:我们的产品有一个核心模块和几个可选插件. 核心是一个名为ticket_type的数据库表. 可选插件通过1:1关系扩展ticket_type表.该表称为myplugin_ticket_type_extension. 对于myplugin_ticket_type_extension中的每一行,ticket_type中都有一行.这通过ForeignKey
我们的产品有一个核心模块和几个可选插件.

核心是一个名为ticket_type的数据库表.

可选插件通过1:1关系扩展ticket_type表.该表称为myplugin_ticket_type_extension.

对于myplugin_ticket_type_extension中的每一行,ticket_type中都有一行.这通过ForeignKey强制执行.到目前为止问题:-)

现在困难的部分:如何强制在ticket_type中的每一行myplugin_ticket_type_extension中都有一行?

困难的部分:myplugin是一个可选的插件.该产品的核心不应该知道这个插件的任何信息.

解决方法

执行此操作的最简单方法是向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();

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读