【问题标题】:Foreign key reference with ON UPDATE CASCADE inside arraypostgresql:在数组内更新级联
【发布时间】:2011-11-30 00:49:03
【问题描述】:

我在表 A 上有一个自然主键。

在表 B 中,我想要一个 A 的外键引用数组。

是否可以在数组元素上指定 ON UPDATE CASCADE,这样当表 A 中的主键值发生变化时,B 中的数组也会被修改。 还是我应该将数组规范化到一个单独的表中?

【问题讨论】:

    标签: arrays postgresql database-design foreign-keys


    【解决方案1】:

    规范化这将允许您在外键约束中使用标准ON UPDATE CASCADE。它会快得多,因为系统可以为此使用简单的索引。这应该会给你 3 个表格。需要更多的磁盘空间。但值得每一点:

    • 表一个
    • 表 b
    • 表 a_b -- 实现 n:m 关系

    否则,您将不得不编写一个触发函数来查找 B 中的所有引用并将其替换为主 A 的值。

    【讨论】:

    • 同意——你肯定想这样做。你不想陷入混乱、缓慢的触发器。一点额外的磁盘空间可以为您节省很多麻烦和查询时间。
    • 嗯,虽然我没有提到它,但我正在从现有的 a_b 表中进行非规范化处理。因为我在 a 中有复合/自然主键,所以在这种情况下,额外的磁盘空间是磁盘空间使用量的两倍多,而且意义重大。
    • @EoghanM:在这种情况下,我会求助于代理主键。添加一个序列列作为主(或唯一)键。
    • @Erwin,实际上并没有想到这一点 - 将其视为解决方案,谢谢!
    【解决方案2】:

    是否可以在元素上指定 ON UPDATE CASCADE 数组,这样当表 A 中的主键值发生变化时, B 中的数组被修改。

    只有当

    • 被引用的列和被引用的列都是相同类型的数组,并且
    • 这些值具有相同数量的元素。

    如果您想在一个表中插入数组元素的有效值,并在另一个表中存储这些有效值的数组,则将无法正常工作。

    OTOH,这确实起作用,但只是部分起作用。

    create table a (
      str varchar[2] primary key
    );
    
    create table b (
      -- Room for two values from table a . . .
      str varchar[4] primary key references a (str) on update cascade
    );
    
    insert into a values 
    ('{''A'', ''B''}'),
    ('{''C'', ''D''}'),
    ('{''E'', ''F''}');
    
    insert into b values 
    ('{''A'', ''B''}');
    
    update a set str = '{''A'',''C''}'
    where str = '{''A'',''B''}';
    
    select * from b;
    {'A','C'}
    

    这很有效。但是如果你尝试在表 b 中存储两个数组,你会得到一个错误。

    insert into b values
    ('{{"C", "D"}, {"E", "F"}}');
    ERROR:  insert or update on table "b" violates foreign key constraint "b_str_fkey"
    DETAIL:  Key (str)=({{C,D},{E,F}}) is not present in table "a".
    

    而且,当你斜视和倾斜你的头恰到好处时,这是有道理的。在关系模型中,每一行和每一列的交集只包含一个值。所以你应该不能通过ON UPDATE CASCADE更新半个值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多