【问题标题】:PSQL ON UPDATE interaction with multi-column foreign keyPSQL ON UPDATE 与多列外键的交互
【发布时间】:2021-04-16 19:50:16
【问题描述】:

所以,我的任务是建立一个新的数据库来处理服务器补丁。我仍处于设计阶段,无法找到答案来回答这个问题,所以我正在寻求帮助。

到目前为止:

CREATE TABLE servers (
    name varchar(50) PRIMARY KEY,
    patch_id varchar(10) REFERENCES patch_info(id) NOT NULL,
    env varchar(5),
    ...
)

CREATE TABLE patch_info (
    id varchar(10) PRIMARY KEY,
    patch_time timestamptz NOT NULL,
    reboot_time timestamptz NOT NULL,
)

CREATE TABLE patch_data (
    id big serial PRIMARY KEY,
    name varchar(50),
    patch_id varchar(10),
    env varchar(5),
    FOREIGN KEY (name, patch_id, env) REFERENCES servers (name, patch_id, env) NOT NULL ON UPDATE CASCADE ON DELETE CASCADE
)

我的问题是,如果我更新服务器表中的 patch_id,会有什么行为。 patch_info 表基本上只包含由其他表中的 id 值引用的补丁/重启时间标识符的完整列表。当更新 id 以反映当月的时间/日期时,实际的 patch_info 表本身每月只会更改一次,但是各个服务器会经常每月更改其时间,因此当服务器表中的 patch_id 字段更改时该更改需要向下级联到 patch_data 表。

另一个问题是关于 ON DELETE 选项的。如果实际的 server.name 字段被删除,我希望 patch_data 表级联删除,但如果 patch_id 为 null 或已删除,则不会。这是我的 ON CASCADE ON DELETE 语句的当前行为还是我可以在两个单独的外键中使用 patch_data.name 列?

感谢您的帮助。

【问题讨论】:

    标签: sql database postgresql


    【解决方案1】:

    首先,您需要对 servers (name, patch_id, env) 设置唯一键或主键约束,因为每个外键都必须引用主键或唯一键。

    如果您更新servers 中的patch_idON UPDATE CASCADE 将更新patch_data 中的patch_id 列(表中没有“字段”)。

    如果您从servers 中删除引用的行,ON DELETE CASCADE 将删除patch_data 中的行。

    您不能“删除字段”。也许您的意思是“将列更新为 NULL”。如果servers 上的约束是主键约束,则不能这样做,因为主键列不可为空。如果它是唯一约束,并且您将servers 中的patch_id 更新为NULL,那么patch_data 中的引用行也将patch_id 设置为NULL。这样做的结果是外键关系不再有效,因为外键只对非 NULL 的列强制执行。

    如果这听起来令人困惑,那就对了。因此,请确保所有涉及的列都定义为NOT NULL,这样就不会发生任何奇怪的事情。

    【讨论】:

    • 是的,没有字段,我在发帖寻求帮助或回答时应该注意我的术语,谢谢。所以我需要在由 (name, patch_id, env) 组成的服务器表中创建一个实际的唯一键,以便在另一个表中引用该列集?我认为将名称作为服务器的 PK 是不够的,因为 patch_id 和 env 都可以为不同的服务器有多个条目?
    • 这是一个技术要求:外键必须指向主键或唯一键。我想您只想拥有用于自动更新的外键。为什么要复制列?
    • 审计需要。最初的计划是使用来自服务器的名称和 patch_id 来使用名称、patch_id、env 以及来自 patch_info 的 patch_time 和 reboot_time 填充 patch_data 表。是否可以将服务器 PK 用作单独的唯一约束的一部分?将名称保留为 PK,然后添加 CONSTRAINT my_constraint UNIQUE (name, env, patch_id) 作为要从其他表引用的约束?表 patch_data 将是“公共”的,而其他的都将被锁定,这就是它需要完全依赖于其他表的原因。
    • 是的,您可以添加包含主键的多余唯一约束。我质疑“审计目的”是否需要冗余数据。据我了解,审计是收集数据来回答谁在什么时候做了什么。我看不出保留重复数据如何达到这个目的。我预测,如果您避免出现这种数据重复以及需要同步导致这个问题的数据,那么您在使用数据库时会获得更多乐趣。
    猜你喜欢
    • 2015-12-29
    • 2016-10-29
    • 2018-08-17
    • 2012-08-07
    • 1970-01-01
    • 2011-10-06
    • 1970-01-01
    • 1970-01-01
    • 2018-02-21
    相关资源
    最近更新 更多