代码之家  ›  专栏  ›  技术社区  ›  Mathieu

插入几行以满足约束

  •  0
  • Mathieu  · 技术社区  · 15 年前

    我有两张桌子:牌组(ID)和牌组(牌组、颜色、价值)

    甲板有这些限制:

    • CHECK (fifty_two_cards_deck(id))
    • PRIMARY KEY (id)

      创建函数fifty_two_cards_deck(deck integer)返回布尔值 语言SQL稳定严格 作为$ $select count(*)=52,其中deck=1美元$ 美元;

    卡有这些限制:

    • FOREIGN KEY (deck) REFERENCES deck(id)
    • PRIMARY KEY (deck, color, value)

    我如何插入新的面板?

    我试过这个:

    begin transaction;
    INSERT INTO "public"."deck" ("id") VALUES (nextval('deck_id_seq'::regclass));
    INSERT INTO "public"."card" ("deck", "color", "value") VALUES ('1', enum_first(null::Suit), enum_first(null::Symbol));
    
    end transaction
    

    (我编辑了 fifty_two_cards_deck 成为一个 one_card_deck 用于测试) 但我得到了这个错误:

    SQL错误:

    错误:关系“deck”的新行 违反检查约束 “五十张两张扑克牌”

    语句中:开始事务; 插入“public”。“deck”(“id”)。 价值观 (nextval('deck_id_seq':regclass)); 插入“public”.“card”(“deck”, “颜色”,“值”)值(“1”, 枚举优先(空::适合) Enum_First(空::符号));

    期末交易

    如何在不消除约束的情况下解决这个问题?

    编辑:解决方案

    给马格努斯·哈甘德,我让它这样工作(在设置了外置密钥之后,可以延迟):

    begin transaction;
    
    SET CONSTRAINTS ALL DEFERRED;
    
    INSERT INTO "public"."deck-card" ("deck", "position", "color", "value") VALUES (1, 0, enum_first(null::suit), enum_first(null::Symbol));
    INSERT INTO "public"."deck" ("id") VALUES (1);
    
    end transaction
    
    1 回复  |  直到 15 年前
        1
  •  1
  •   Magnus Hagander    15 年前

    如果您将外键设为可延期,然后将其设置为延期,那么它可能会工作。然后插入“卡片”表 第一 然后进入“甲板”。检查约束在插入时执行(因此,在“卡”中的条目存在之前),并且不能延迟到事务结束。

    但这实际上并不能解决这样一个问题:约束被破坏了,应该被删除;)检查约束将只检查进入“deck”的行。但是,一旦在其中插入了行,您仍然可以向“card”表中添加更多行或从中删除行,并且检查约束将不会抱怨-直到下次尝试修改“deck”。