0

テーブルに行を挿入しようとするクエリがあります。その ID を持つ行が既に存在するため、主キー制約が失敗したためにクエリが失敗する可能性があります。

挿入を試みる前にこれを確認できましたが、SQLException の SQL 状態を確認することでこれを検出することもできます。これは、この種のことを行う有効な方法ですか? または、事前に明示的なチェックを行う必要がありますか?

私が尋ねる理由は、挿入を実行する前に明示的なチェックを行う必要がある場合、矛盾を防ぐためにチェックしているテーブルをロックする必要があるからです。エラー コード チェックを使用すると、テーブルをロックする必要がなくなります。

事前に確認

try {
    con.setAutoCommit(false);
    con.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
    Statement statement = con.createStatement();
    ResultSet rs = statement.executeQuery("SELECT * FROM SomeTable WHERE Id = 123");
    if(rs.next()) {
        con.setAutoCommit(true);
        System.err.println("Entry with Id 123 already exists!");
        return;
    }
    statement = con.createStatement();
    statement.executeQuery("INSERT INTO SomeTable(Id) VALUES(123)");
    con.commit();
    con.setAutoCommit(true);
} catch(SQLException e) {
    // These 2 lines actually need to be wrapped in a try/catch too.
    con.rollback();
    con.setAutoCommit(true);
}

エラーコードチェック

try {
    Statement = con.createStatement();
    statement.executeQuery("INSERT INTO SomeTable(Id) VALUES(123)");
} catch(SQLException e) {
    if(e.getSQLState().equals("23505"))
        System.err.println("Entry with Id 123 already exists!");
}
4

3 に答える 3

1

あなたの「エラーコードチェック」アプローチは有効であり、実際に慣例です。違反したSQL制約の名前の例外Messageプロパティを解析することもできることに注意してください。そのため、制約をきめ細かくすることをお勧めします(つまり、いくつかの複雑な制約ではなく、多くの単純な制約を作成する側でエラーが発生します)。それぞれに意味のある名前を付けます。

于 2011-10-17T10:54:46.047 に答える
0

個人的には、そのようなことを防御的にコーディングすることを好みます。クエリを次のように記述します。

INSERT INTO SomeTable(ID)
SELECT 123
WHERE NOT EXISTS (SELECT 1 FROM SomeTable WHERE id = 123)

もちろん、SQL のフレーバーに応じて、そのクエリを変更する必要があります。多分:

SELECT 123
FROM DUAL 
WHERE NOT EXISTS...

挿入後、影響を受ける行数をテストし、PK 違反があったかどうかを判断できます。

于 2011-10-15T04:37:08.833 に答える
-1

PK のシーケンスまたは自動インクリメント列を使用して、このようなエラーを最初から回避する必要があります。

ただし、他のあらゆる種類のエラーが発生する可能性があるため、SQLExceptions を適切に処理する必要があります。

于 2011-10-15T04:58:38.973 に答える