0

テーブルの外部キーを新しい挿入からの値に更新したいのですが、そのキーは現在nullです。ここでの注意点は、INSERT の情報がテーブルに関連していることです。

例を考えてみましょう:

  1. 車には car_part があります
  2. car と car_part の両方に version_control への関連付けがあります (version_control には from_version,to_version,active という ID があります)
  3. 一部の車には現在、null version_control があります。
  4. 車には version_control を持つ car_part があるため、基本的には車の新しい version_control を作成し、car_part の version_control と同じ情報を入力する必要があります。

例えば:

CAR
|id|car_part_id|version_control_id|
|1 |10         |                  |

CAR_PART
|id|version_control_id|
|10|100               |

VERSION_CONTROL
|id |from    |to         |
|100|1990    |2012       |

上記の例では、次のことを行います。

  1. 更新車 1、
  2. version_control #100 と同じ情報を持つ新しい version_control を追加します

実際の例では、数百台の車があり、その数十台の version_control_id が null であるため、これを 1 回のクエリで実行する必要があります。

以下の PSEUDO コードを、この問題を解決する有効な SQL に変更するにはどうすればよいですか?

UPDATE car
WITH inserted_version as (
    INSERT INTO version_control(
            id, active, from_version_id, to_version_id)
    WITH vc_to_create as (
        select c.id as car_id,vc.* from car c
        inner join car_part cp on cp.id = c.car_part_id 
        inner join version_control vc on cp.version_control_id=vc.id
        where c.version_control_id IS NULL
        )
    SELECT nextval('pk_entities'),vctc.active, vctc.from_version_id, vctc.to_version_id)
    FROM vc_to_create vctc
    RETURNING id
    )
SET version_control_id=(SELECT i_vc.id  FROM inserted_vc i_vc)
WHERE id=vc_to_create.car_id -->vc_to_create Not available here
4

1 に答える 1

1

トランザクション ブロック内の異なるテーブルで 2 つの変更を行いたいようです。

ここから始めます。http://www.postgresql.org/docs/9.1/static/tutorial-transactions.html

また、トランザクション内に入る前に、トランザクション分離レベルを SERIALIZABLE に設定する必要がある場合もあります。私が話していることを理解するには、http://www.postgresql.org/docs/9.1/static/sql-set-transaction.htmlを参照してください。

厳密な分離レベルが必要ない場合は、誰かが私を修正してください。残念ながら、そのレベルの分離が厳密に必要とされるシナリオの詳細については、私の頭がぼやけてしまいます。厳密に言えば、特に記述された SQL によっては、その分離レベルは必要ないかもしれませんが、これはそのような状況のような匂いがします。おそらく不必要な事前警告です。

編集:

わかりました、「単一のクエリで」これらすべてを行う必要はありません。厳密に言えば、どの行が挿入されたかを特定または追跡する必要があるだけです。そのために一時テーブルを使用できるはずです。あれは:

  1. 取引開始。
  2. トランザクション分離レベルを SERIALIZABLE に設定します。(繰り返しますが、必要に応じて、しかし、そうでないことが証明されない限り、設定しなかった場合は率直に心配します。また、SERIALIZABLEを使用すると、再試行する必要がある場合があることに注意してください:http://www.postgresql.org/docs/9.1/interactive /transaction-iso.html#XACT-SERIALIZABLE )
  3. version_control に挿入する行として (クエリを使用して) 一時テーブルを作成し、各バージョン管理行に関連する車の ID も同様に作成します。つまり、各行にはバージョン管理情報と ID 情報が含まれます。ここをつかむだけnextval('pk_entities')です。
  4. 一時テーブルからのデータをバージョン管理に挿入します (前述のように、キーは既に生成されています)。
  5. 一時テーブルのデータで車を更新します。
  6. テーブルをコミット/ドロップします。(これは、一時テーブルの create ステートメントで宣言することにより、テーブルがトランザクションのコミット時に実行できるようです。)

これは、私がどのように計画するかについての高/中レベルの説明ですが、そのためのコードをまだ明示的に書いていないため、何かを見落としている可能性があります。

于 2012-07-17T18:12:35.933 に答える