4

厳密モードを使用している MySQL DB があるため、行を挿入するときにすべての NOT NULL 値を入力する必要があります。API Im の作成では、DUPLICATE KEY UPDATE 機能のみを使用して、挿入/更新の両方を実行しています。

予期される NOT NULL 属性が挿入された場合、クライアント アプリケーションはエラーを返します。

基本的な例 (id は主キーで、NOT NULL aaa と xxx の 2 つのフィールドがあります)

INSERT INTO tablename (aaa, xxx, id ) VALUES ( "value", "value", 1)
ON DUPLICATE KEY UPDATE aaa=VALUES(aaa), xxx=VALUES(xxx)

これまでのところすべて順調です。挿入されると、システムは更新を許可します。それにもかかわらず、フィールドの 1 つだけを更新すると、次のエラーが発生します。

INSERT INTO tablename (aaa, id ) VALUES ( "newValue", 1)
ON DUPLICATE KEY UPDATE aaa=VALUES(aaa)

java.sql.SQLException: Field 'xxx' doesn't have a default value

行はすでに挿入されており、xxx 属性には値として「値」があるため、この例外は嘘です。次の文は次の文と同等だと思います。

UPDATE tablename SET aaa="newValue" WHERE id=1

誰かがこの問題についていくつかの光を当てることができれば幸いです.

編集:

PhpMyAdmin で SQL クエリを使用して 1 つのフィールドだけを正常に更新できるため、これは SQL の問題ではなく、JDBC のドライバーの問題であると思います。それでは解決しないかもしれません。

@Marc B:あなたの洞察はおそらく真実であり、私が今説明したことを示しています. これは、JDBC にバグがあることを意味します。挿入が ON DUPLICATE タイプの場合、行のデフォルト値が存在する可能性があるため、そのチェックを行うべきではないためです。実際のテーブル データを提供することはできませんが、上記の説明はすべて明確であると思います。

@ruakh: 挿入に失敗することはありません。また、検証の遅延も予想されません。サーブレットは行が存在するかどうかわからないため、同じクエリを使用して挿入/更新の両方を行う必要があります。JAVA API サービスは、挿入が完了したときに既に入力されている NOT NULL フィールドを含む行の更新のみに失敗します。フィールドには更新前に挿入されたデフォルト値があるため、例外は嘘です。

4

1 に答える 1

1

これは、DRY / SRP の失敗の典型的なケースです。コードを複製しないために、単一責任の原則に違反する関数を作成しました。

ステートメントのセマンティクスは、INSERT競合する行がないことを期待することです。このON DUPLICATE KEY UPDATEオプションは、別の別のクエリを必要とする、コード内での競合の処理を避けるためだけのものです。UPDATEこれは、少なくとも 1 つの一致する行が存在することが期待されるステートメントとはまったく異なります。

MySQL がINSERT競合しない場合にのみ列をチェックし、何らかの理由で行がデータベースから削除され、更新の実行を期待するコードが予期しない例外を処理する必要があると想像してください。ステートメントの動作の違いを考えると、挿入ロジックと更新ロジックを分離することをお勧めします。

理論はさておき、MySQL はクエリの実行時に実行計画をまとめます。ステートメントの場合は、INSERT試みたときに成功する可能性があると想定する必要があります。これが最適な戦略だからです。列が欠落していることを後で見つけるためだけにインデックスなどをチェックする必要がなくなります。

これは仕様によるものであり、JDBC のバグではありません。

于 2012-11-16T13:27:59.430 に答える