0

PKとして次のフィールドを持つDB上のテーブルがあります:DOC_ID、、、。推測できるように、これは一連のExcelスプレッドシートと呼ばれます。SECTION_IDSET_IDCELL_ID

それらのフィールドに加えて、私はCELL_ROWフィールドとCELL_COLフィールドを持っています。SET_IDunique )を使用すると、代替キーが形成されます。

したがって、少なくとも理論的には、2つのセルの座標を交換する場合は、その制約を解除するか、3番目の一時的な空き位置(たとえば、 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はそれを不可分操作として実行するので、制約は(レコードごとのレコードではなく)操作全体の後でのみチェックされますか?

このような状況でMSSQLServer 2008 r2とPostgresはどのように動作しますか?

4

2 に答える 2

1

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。そのキーワードのcreatetableステートメントを確認してください。

于 2013-02-26T12:53:11.620 に答える
1

一意性制約を延期しない限り、PostgreSQLはエラーをスローします(そして、それを外部キーとして使用することはできません)。SQLServerについてはよくわかりません。

簡単に言うと、おそらくPostgresまたはPostgreSQLと呼びたいでしょう。それをPostgreと呼ぶことは、コミュニティとの接触が少なすぎて修正できないことを示しています。

PostgreSQLの詳細

PostgreSQLは、タプルの更新時にタプルの制約をチェックします。これは、一意性制約に違反しないアトミックな方法でセットが更新された場合でも、一意性制約に違反することを意味します。これにより、セットの整数キーに-1を掛けてから、次の更新でもう一度-1を掛けて、1を追加するなど、いくつかの興味深い回避策があります。

于 2013-02-26T13:04:37.163 に答える