【问题标题】:Update multiple records, with temporary key overlap更新多条记录,临时键重叠
【发布时间】:2013-02-26 12:12:05
【问题描述】:

我在 DB 上有一个表,其中包含以下字段作为 PK:DOC_IDSECTION_IDSET_IDCELL_ID。正如您所推断的,这指的是一组 Excel 电子表格。

除了这些字段之外,我还有一个CELL_ROW 字段和CELL_COL 字段。 使用SET_ID唯一),它们形成了一个替代键。

因此,至少在理论上,如果我想交换两个单元格的坐标,我需要释放该约束,或者使用第三个临时空闲位置(例如 A100000)。

假设我有以下单元格:

 DOC_ID | SECTION_ID | SET_ID | CELL_ID | CELL_ROW | CELL_COL
--------|------------|--------|---------|----------|----------
   5    |     456    |  8778  |  15045  |    5     |    4
   5    |     456    |  8778  |  15048  |    5     |    5 

假设我有以下临时表,我从中对主表执行UPDATE

 DOC_ID | SECTION_ID | SET_ID | CELL_ID | CELL_ROW | CELL_COL
--------|------------|--------|---------|----------|----------
   5    |     456    |  8778  |  15045  |    5     |    5
   5    |     456    |  8778  |  15048  |    5     |    4

理论上,UPDATE 应该引发异常...

不过刚刚试了一下,效果很好!

你能解释一下为什么吗? Oracle 是否将其作为原子操作执行,因此仅在整个操作之后检查约束(而不是每个记录的记录)?

MS SQL Server 2008 r2 和 Postgres 在这种情况下的表现如何?

【问题讨论】:

    标签: sql-server-2008 postgresql oracle10g sql-update unique-constraint


    【解决方案1】:

    PostgreSQL 会抛出一个错误,除非你推迟唯一约束(然后你不能将它用作外键)。我不确定 SQL Server。

    简而言之,您可能希望将其称为 Postgres 或 PostgreSQL。将其称为 Postgre 表明您与社区的联系太少而无法纠正。

    有关 PostgreSQL 的更多信息

    PostgreSQL 在元组更新时检查元组约束。这意味着即使在以不违反唯一约束的原子方式更新集合的情况下,也会违反唯一约束。这导致了一些有趣的解决方法,例如将整数键乘以 -1 为集合,然后在下一次更新中再次乘以 -1 并加一。

    【讨论】:

    • 感谢您的回答!实际上,我与 Postgres 社区没有任何联系。在我的公司中,我们为上述 DBMS 提供全面支持,但自从一年前我被聘用以来,我从未在 Postgres 上工作过。
    • 我在 SQL Server 上尝试过,它似乎可以正常工作。现在,对于 PG,有没有办法改变约束并即时设置它DEFERRABLE?或者这个属性只能在创建表时设置?请注意,约束不是 FK。
    • 决定在创建数据库时将其设置为 DEFERRABLE 以解决问题。
    【解决方案2】:

    我在 Postgresql 中尝试过,果然出现了重复键错误:

    create table t (
        doc_id integer,
        section_id integer,
        set_id integer,
        cell_id integer,
        cell_row integer,
        cell_col integer,
        primary key (doc_id, section_id, set_id, cell_id),
        unique (set_id, cell_row, cell_col)
    );
    
    insert into t (doc_id, section_id, set_id, cell_id, cell_row, cell_col)
    values
    (5, 456, 8778, 15045, 5, 4),
    (5, 456, 8778, 15048, 5, 5);
    
    create temporary table t_temp (
        doc_id integer,
        section_id integer,
        set_id integer,
        cell_id integer,
        cell_row integer,
        cell_col integer
    );
    
    insert into t_temp (doc_id, section_id, set_id, cell_id, cell_row, cell_col)
    values
    (5, 456, 8778, 15045, 5, 5),
    (5, 456, 8778, 15048, 5, 4);
    
    update t
    set
        cell_col = t_temp.cell_col
    from t_temp
    where
        t.doc_id = t_temp.doc_id
        and t.section_id = t_temp.section_id
        and t.set_id = t_temp.set_id
        and t.cell_id = t_temp.cell_id
    ;
    ERROR:  duplicate key value violates unique constraint "t_set_id_cell_row_cell_col_key"
    DETAIL:  Key (set_id, cell_row, cell_col)=(8778, 5, 5) already exists.
    

    如果约束设置为deferrable,我可以这样做。检查该关键字的 create table 语句。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-02-18
      • 2016-05-01
      • 2013-05-02
      • 2014-03-04
      • 1970-01-01
      • 1970-01-01
      • 2015-07-22
      相关资源
      最近更新 更多