代码之家  ›  专栏  ›  技术社区  ›  Greg Gum

如何使列不为空,但在第一次创建时需要为空

  •  0
  • Greg Gum  · 技术社区  · 7 年前

    我有两张桌子, tableA 和 tableB .

    tableA(id, tableB_id)
    
    tableB(id, tableA_id)
    

    在中创建记录时 表 ,fk值 tableB_id 尚不清楚。所以我别无选择,除了它可以为空。

    但在它创建之后, 塔布莱 是填充的,然后是 表 更新。

    然而,在这之后,我想确保 tableA.tableB_Id 从不为空(为了数据一致性)。

    有什么方法可以确保这一点吗?

    我的第一次尝试是 tableA.tableB _ ID不为空,但这会阻止在中创建记录 表 .

    我唯一能想到的是创建另一个专栏:

    tableA.is_initialized
    

    那么什么时候 tableA.tableB_id 已填充,设置 tableA.is_initialized 成真。

    然后添加一个约束,以便 is_initialized 是真的,那么 tableB_Id 不能为空。

    我走对了吗?

    更具体地说,数据模型:它是表A和表B之间的一对多关系。但是我需要知道哪一个相关的表B记录是 default 一个(当前正在使用的那个),所以我将它存储在表A中。也许在数据库中有一种更好的建模方法,但是到目前为止它工作得很好。

    4 回复  |  直到 7 年前
        1
  •  1
  •   Jonathan Leffler    7 年前

    考虑使用第三个表:

    tableA(id, …other data…)                -- no tableB_id
    tableB(id, tableA_id, …other data…)
    tableA_default_B(tableA_id, tableB_id)
    

    注意没有 … 在的架构中 tableA_default_B . 上的主键(唯一约束) 表A_默认值 是 tableA_id . 它也是 tableA . 这个 tableB_id 列是的外键 tableB . 它也可能对它有一个唯一的约束(因为 塔布莱 与中的两个不同行相关联 表 )

    然后可以插入到对B的无引用约束中。可以将记录插入到对A的引用约束中。最后可以插入到 表A_默认值 有两个已知的身份证。如果在 表A_默认值 对于给定的 tableA.id 在这种情况下,不应该在 塔布莱 在中引用条目 表 ,除了在执行初始插入过程时短暂的。因此,当有一个条目进入 塔布莱 引用中的行 表 没有相应的条目 表A_默认值 ,但一个围绕 INSERT INTO TableB 和 INSERT INTO TableA_Default_B 会解决的。我可能会在 塔布莱 会插入到 表A_默认值 如果该表中没有 塔里亚德 在刚插入的行中使用 塔布莱 .

    使用 is_initialized 标记是危险的、容易出错的,或者在没有触发器的情况下不可行。我建议 不走那条路。

        2
  •  1
  •   Gordon Linoff    7 年前

    这是对阿布拉答案的详细阐述。您的问题是相互需要的外键关系。这是一个很难解决的问题。

    您的想法是让第二列“帮助”空性检查,这是一个好主意。唯一麻烦的是它需要一个触发器才能真正工作——这是第一次 A.tableb_id 如果设置了,则需要设置标志。我喜欢尽可能避免触发。如果使用触发器,则不需要另一列。你可以保证 update 从不将值更改为 NULL .

    保证不- 无效的 值,我们可以沿着Abra的方法做更多的事情,从B中的一个虚拟键开始。 -1 :

    set identity_insert b on;
    
    insert into b (id)   -- you may want to include other columns
        values (-1);
    
    set identity_insert b off;
    

    然后你可以构造 A AS:

    create table A (
        . . . 
        tableB_id int not null default -1 references b(id)
    );
    

    这不能保证该值不能重置为 - 1 在它被设置成其他东西之后。为了保证这一点,您需要如上所述的触发器。

        3
  •  0
  •   Abra BlueJK    7 年前

    只是个建议。使用一个虚拟ID,比如-1(减去一个)。因此,在插入表A之前,请将该值插入表B。然后,每次插入表A时,列table b_id的值将为-1。然后您可以稍后更新。

        4
  •  0
  •   Kars    7 年前

    在表B的insert中使用触发器。当它激发时,它会在表A中输入正确的值。这样,当表B条目存在时,可以确保表A中的引用是正确的。