1

監査トリガーで使用するために、次のテーブルを宣言しました。

CREATE TABLE audit_transaction_ids (id IDENTITY PRIMARY KEY, uuid VARCHAR UNIQUE NOT NULL, `time` TIMESTAMP NOT NULL);
  1. トリガーは、同じトランザクションで複数回呼び出されます。

  2. トリガーが初めて呼び出されたときに、現在の TRANSACTION_ID() と時刻を含む新しい行を挿入したいと考えています。

  3. その後、トリガーが呼び出されたときに、「uuid」または「time」を変更せずに、既存の「id」を返すようにします (最後に Statement.getGeneratedKeys() を呼び出します)。

現在のスキーマには 2 つの問題があるようです。

  1. 呼び出すと、次のMERGE INTO audit_transaction_ids (uuid, time) KEY(id) VALUES(TRANSACTION_ID(), NOW())ようになります。org.h2.jdbc.JdbcSQLException: Column "ID" contains null values; SQL statement: MERGE INTO audit_transaction_ids (uuid, time) KEY(id) VALUES (TRANSACTION_ID(), NOW()) [90081-155]

  2. 既存の行で MERGE を呼び出すと、「時間」が変更されると思われます。

これらの両方の問題を解決するにはどうすればよいですか?

4

2 に答える 2

1

MERGEに似てjava.util.Map.put(key, value)います。行が存在しない場合は挿入し、存在する場合は行を更新します。AUTO_INCREMENTそうは言っても、別の列をキーとして使用する限り、列を含むテーブルにマージできます。

customer[id identity, email varchar(30), count int]あなたができるとすればmerge into customer(id, email, count) key(email) values((select max(id) from customer c2 where c2.email='test@acme.com'), 'test@acme.com', 10)。つまり、レコードが存在する場合は id を再利用し、それ以外の場合は null を使用します。

行が既に存在するかどうかに応じて挿入または更新する移植可能な方法については、https://stackoverflow.com/a/18819879/14731も参照してください。


1. MERGE INTO audit_transaction_ids (uuid, time) KEY(id) VALUES(TRANSACTION_ID(), NOW())

新しい行を挿入するだけの場合は、次を使用します。 INSERT INTO audit_transaction_ids (uuid, time) VALUES(TRANSACTION_ID(), NOW())

MERGEをキーとして使用する場合、列の値を設定IDしないと意味がありません。これは、(理論上でも) 既存の行を更新できないためです。IDできることは、別のキー列を使用することです (上記の場合、使用できる列はありません)。詳細については、ドキュメントを参照しMERGEてください。

2. 既存の行で MERGE を呼び出すと、「時間」が変更されます

「時間」列の値が変更されたという事実について話しているかどうかはわかりません。ステートメントはその列を更新することになっているMERGE ... VALUES(.., NOW())ため、これは を使用する場合に予期される動作です。MERGE

または、古いバージョンの H2 が同じトランザクション内で異なる値を返したことを意味しているのかもしれません (同じトランザクション内で同じ値を返す他のほとんどのデータベースとは異なります)。これは事実ですが、H2 バージョン 1.3.155 (2011-05-27) 以降では、この非互換性は修正されています。変更ログも参照してください: 「CURRENT_TIMESTAMP() などは、トランザクション内で同じ値を返すようになりました。」バージョン1.3.155を使用しているように見えるため、これは問題ではないようです(エラーメッセージ[90081-155]にはビルド/バージョン番号が含まれています)。

于 2011-06-10T14:38:00.077 に答える
0

簡潔な答え:

MERGE INTO AUDIT_TRANSACTION_IDS (uuid, time) KEY (uuid, time) VALUES (TRANSACTION_ID(), NOW());

ちょっとしたパフォーマンスのヒント: uuid がインデックス化されていることを確認してください

長い答え:

MERGE基本的に、更新されるレコードが見つからない場合はUPDATEwhichです。INSERT

ウィキペディアは、 MERGEのより簡潔で標準化された構文を提供しますが、独自の更新と挿入を提供する必要があります。(これが H2 でサポートされるかどうかは、私の回答ではありません)

MERGEでは、H2を使用してレコードを更新するにはどうすればよいでしょうか? 検索するキーを定義し、それが見つかった場合は行を更新します (指定した列名を使用DEFAULTし、ここで定義して列をデフォルトにリセットできます)、それ以外の場合は行を挿入します。

今何Nullですか?Null不明、見つからない、未定義、探しているものではないことを意味します。

そのためNull、検索するキーとして機能します。レコードが見つからないことを意味するためです。

MERGE INTO table1 (id、col1、col2) KEY(id) VALUES (Null、1、2)

Null価値があります。それは値です。

それでは、SQL を見てみましょう。

MERGE INTO table1 (id、col1、col2) KEY(id) 値 (デフォルト、1、2)

それは何を意味していますか?私には、この [DEFAULT, 1, 2] があり、 columnでa を見つけて、DEFAULTidcol1見つかった場合は1 に更新し、 col22 に更新すると表示されます。idそれ以外の場合は、デフォルトを に、1 を にcol1、2 をに挿入しますcol2

私がそこで強調したことがわかりますか?それは一体何の意味ですか?とはDEFAULT? と比べDEFAULTidどうですか?

DEFAULTは単なるキーワードです。

次のようなことができます。

MERGE INTO table1 (id, col1, timeStampCol) KEY(id) VALUES (Null, 1, DEFAULT)

ただし、キー列に DEFAULT を入れないでください。

于 2011-06-15T01:35:16.880 に答える