1

一部の行を削除し、Java の条件に基づいてテーブルを更新しているときに、以下のエラーが発生します。私のデータベースは PostgreSQL 8.4 です。以下はエラーです: エラー: 重複したキー値が一意の制約 "xak1fact_dim_relationship" に違反しています

この問題を引き起こすコードは次のとおりです。

/**
 * Commits job.  This does the following:
 * <OL>
 *  <LI> cancel previous datamart states </LI>
 *  <LI> drop diabled derived objects </LI>
 *  <LI> flip mirror relationships for objects with next states </LI>
 *  <LI> advance rolloff_state from start1 to complete1, from start2 to complete </LI>
 *  <LI> set 1/0 internal states to 0/-1 </LI>
 *  <LI> remove header objects with no letter rows </LI>
 *  <LI> mark mirror rel as OS if children are missing (e.g., semantic w/o agg build) </LI>
 *  <LI> mark mirror rel as OS if int-map not in sync with dim base (e.g., int-map SQL w/o semantic) </LI>
 * </OL>
 */
protected void CommitJobUnprotected()
    throws SQLException
{
    if (_repl.epiCenterCon== null)
        throw makeReplacementError(0);
    boolean oldAutoCommitStatus = _repl.epiCenterCon.getAutoCommit();

    try
    {

        _repl.epiCenterCon.setAutoCommit(false);

        Statement stmt = null;
        boolean committed = false;
        synchronized (SqlRepl.metaChangeLock)
        {
            try
            {
                stmt = _repl.epiCenterCon.createStatement();

                // update internal states for fact_dim_relationship
                metaExec(stmt, "DELETE from fact_dim_relationship WHERE internal_state = -1 AND "  +
                                " EXISTS (SELECT 1 FROM fact_dim_relationship WHERE internal_state = 1)",
                                " SELECT 1 from fact_dim_relationship WHERE internal_state = -1 AND "  +
                                " EXISTS (SELECT 1 FROM fact_dim_relationship WHERE internal_state = 1)"); /*1*/
                metaExec( stmt, "UPDATE fact_dim_relationship SET internal_state = internal_state - 1 " +
                             " WHERE EXISTS (SELECT 1 FROM fact_dim_relationship inner1 " +
                             "              WHERE inner1.internal_state = 1 " +
                             " AND inner1.fact_tbl_key = fact_dim_relationship.fact_tbl_key " +
                             " AND inner1.dim_base_key = fact_dim_relationship.dim_base_key ) ",
                             " SELECT 1 FROM fact_dim_relationship " +
                             " WHERE EXISTS (SELECT 1 FROM fact_dim_relationship inner1 " +
                             "              WHERE inner1.internal_state = 1 " +
                             " AND inner1.fact_tbl_key = fact_dim_relationship.fact_tbl_key " +
                             " AND inner1.dim_base_key = fact_dim_relationship.dim_base_key ) "); /*5*/

                System.out.println("Update done on fact_dim_relationship");
                _repl.doDrop(SqlReplLogger.DB_META, stmt, "fact_agg", "SELECT fact_agg_key FROM fact_agg f WHERE " +
                                                                      " NOT EXISTS (SELECT 1 FROM fact_agg_letter l WHERE " +
                                                                      "                 f.fact_agg_key = l.fact_agg_key) "); /*6*/

                _repl.doDrop(SqlReplLogger.DB_META, stmt, "dim_base_agg", "SELECT dim_base_agg_key FROM dim_base_agg d WHERE " +
                                                                          " NOT EXISTS (SELECT 1 FROM dim_base_agg_letter l WHERE " +
                                                                          "                 d.dim_base_agg_key = l.dim_base_agg_key) "); /*6*/

                CheckOutOfSync(stmt, "fact_agg", null); /*7*/
                CheckOutOfSync(stmt, "dim_base_agg", null); /*7*/

                metaExec( stmt, " update mirror_relationship set relation_to_current = 'Out Of Sync' " +
                                " where dim_col_intmap_key is not null " +
                                " and relation_to_current = 'One Back' " +
                                " and not exists ( " +
                                "       select 1 " +
                                "       from mirror_relationship m2, dim_col_view c, dim_col_intmap i " +
                                "       where m2.dim_base_key = c.dim_base_key " +
                                "       and c.dim_col_key = i.dim_col_key  " +
                                "       and i.dim_col_intmap_key = mirror_relationship.dim_col_intmap_key " +
                                "       and m2.relation_to_current = 'One Back') ",
                                " SELECT 1 FROM mirror_relationship " +
                                " where dim_col_intmap_key is not null " +
                                " and relation_to_current = 'One Back' " +
                                " and not exists ( " +
                                "       select 1 " +
                                "       from mirror_relationship m2, dim_col_view c, dim_col_intmap i " +
                                "       where m2.dim_base_key = c.dim_base_key " +
                                "       and c.dim_col_key = i.dim_col_key  " +
                                "       and i.dim_col_intmap_key = mirror_relationship.dim_col_intmap_key " +
                                "       and m2.relation_to_current = 'One Back') "); /*8*/

                // clean out the tables used by mombuilder, aggbuilder, and semantics
                metaExec( stmt,  "delete from relation_intermediary", "select 1 from relation_intermediary" );

                _repl.epiCenterCon.commit();
                committed = true;
            }
            finally
            {

                safeMetaRollbackIfNeeded( committed );
                _repl.safeClose( null, stmt );
            }
        } // end synchronized block
    }
    finally
    {
        _repl.epiCenterCon.setAutoCommit(oldAutoCommitStatus);
    }
}

最初の削除ステートメントは正常に実行されましたが、更新の実行中に上記の例外がスローされています....! SQLServer、Oracle、および DB2 をサポートしており、同じコードが他の DB でも問題なく動作します。ちなみに、これらのステートメントを READ_COMMITTED トランザクション レベルで実行し、その間に何かが失敗した場合は安全にロールバックするように自動コミットをオフに設定しています。上記のコードを autocommit true で実行すると、コードは正常に動作します! しかし、そうすべきではありません。PostgreSQL の複数バージョン同時実行制御機能が疑わしいのですが、分離レベルの設定が間違っていますか? できるだけ早く私を助けてください。あなたが欲しい情報は何でも提供できます。

4

1 に答える 1

1

この特定のクエリ セットのみの場合は、次を使用しますSET CONSTRAINT

BEGIN;
SET CONSTRAINT = xak1fact_dim_relationship DEFERRED;
-- Do your SQL
COMMIT;

これが非常に一般的なケースである場合は、データベース スキーマを次のように変更できます。データベース スキーマをサポートするように変更しますINITIALLY DEFERRED

于 2011-05-31T20:44:57.297 に答える