web-dev-qa-db-fra.com

Db2 .SqlIntegrityConstraintViolationException: SQLCODE = -803, SQLSTATE = 23505

Je lis une table dans Oracle et insère l'intégralité du dump dans Db2. Les structures de table sont identiques. J'utilise la classe scala simple qui effectue la tâche susmentionnée. J'ai défini la taille de lot d'insertion sur 300. Après la mise à jour de quelques lots, la classe lève l'exception ci-dessous. 

com.ibm.db2.jcc.am.SqlIntegrityConstraintViolationException: Error for batch element #10: DB2 SQL Error: SQLCODE=-803, SQLSTATE=23505, SQLERRMC=1;PME.TM_ASSET_LQA_DETL, DRIVER=4.13.127
   at com.ibm.db2.jcc.am.id.a(id.Java:673) ~[db2jcc-4.13.127.jar:na]
    at com.ibm.db2.jcc.am.id.a(id.Java:60) ~[db2jcc-4.13.127.jar:na]
    at com.ibm.db2.jcc.am.id.a(id.Java:127) ~[db2jcc-4.13.127.jar:na]
    at com.ibm.db2.jcc.t4.cb.a(cb.Java:481) ~[db2jcc-4.13.127.jar:na]
    at com.ibm.db2.jcc.t4.cb.a(cb.Java:70) ~[db2jcc-4.13.127.jar:na]
    at com.ibm.db2.jcc.t4.q.a(q.Java:57) ~[db2jcc-4.13.127.jar:na]
    at com.ibm.db2.jcc.t4.tb.a(tb.Java:225) ~[db2jcc-4.13.127.jar:na]
    at com.ibm.db2.jcc.am.oo.a(oo.Java:3434) ~[db2jcc-4.13.127.jar:na]
    at com.ibm.db2.jcc.am.oo.d(oo.Java:5550) ~[db2jcc-4.13.127.jar:na]
    at com.ibm.db2.jcc.am.oo.a(oo.Java:4992) ~[db2jcc-4.13.127.jar:na]
    at com.ibm.db2.jcc.am.oo.c(oo.Java:4664) ~[db2jcc-4.13.127.jar:na]
    at com.ibm.db2.jcc.am.oo.executeBatch(oo.Java:2934) ~[db2jcc-4.13.127.jar:na]
    at com.baml.regw.db.replicator.ReplicationRunnable$$anonfun$run$3.apply(SimpleReplicator.scala:105) ~[regw-db-replicator-0.0.933-SNAPSHOT.jar:na]
    at com.baml.regw.db.replicator.ReplicationRunnable$$anonfun$run$3.apply(SimpleReplicator.scala:80) ~[regw-db-replicator-0.0.933-SNAPSHOT.jar:na]

Comme l'exception était liée à IntegrityConstraint, j'ai essayé de vérifier la présence de la clé primaire composite (ID + TimeStamp + 9999-12-31 00.00.000000), mais le combo n'est présent ni dans la table Oracle ni dans la table Db2. Les contraintes sur la table Db2 sont

 COLUMN NAME                         UNIQUE RULE
    +ID+BUSINESS_STOP+BUSINESS_START    Primary
    +ID                                 Duplicate
    +BUSINESS_START                     Duplicate
    +LOW_QUALITY_IND                    Duplicate
    +IDENTIFIER1                        Duplicate    
    +IDENTIFIER2                        Duplicate

J'ai parcouru les autres problèmes de ce type dans SO, mais aucun des correctifs n'a fonctionné pour moi. Le code qui exécute cette tâche

    logger.info("Retrieving based on query string: " + queryStr + " for thread " + threadNum)
    val start = System.currentTimeMillis()
    val rs = stmt.executeQuery(queryStr)
    val rsMd = rs.getMetaData()
    val end = System.currentTimeMillis()
    logger.info("Query execution time: " + (end - start) + "ms.")

    done = true
    var stmtCount = 0
    Iterator.continually(rs).takeWhile(_.next()).foreach { rs =>
      if (sourceConf.hasPath("blockSize")) {
        done = false
      }

      //Subtract one to ignore the timestamp field that we are using
      for (idx <- 1 to (rsMd.getColumnCount()-extraColumnCount)) {
        try  {  
          logger.info("destStmt.setObject"+rs.getObject(idx)+" column Type "+ rsMd.getColumnType(idx))
          destStmt.setObject(idx, rs.getObject(idx), rsMd.getColumnType(idx))
        }
        catch  {
          case e:Exception => {
            logger.warn("While attempting to set (1-based) index: " + idx + 
                " to value of type " + {if(rs.getObject(idx) != null) rs.getObject(idx).getClass().getName() else "[NULL]"} + 
                " received error: " + e.getMessage())
            throw e
          }
        }
      }


      destStmt.addBatch()
      stmtCount += 1

      if(stmtCount % { if (destConf.hasPath("batchSize")) destConf.getInt("batchSize") else 200 } == 0)  {           
        destStmt.executeBatch()
        destDbConn.commit()
        destStmt.clearBatch()
        stmtCount = 0
      }
    }

    if(stmtCount > 0)  {
      destStmt.executeBatch()
      destDbConn.commit()
      destStmt.clearBatch()
    }
    rs.close()
    stmt.close()
4
mavrav
  • Vérifiez s'il existe vraiment la même contrainte d'intégrité dans votre base de données source (Oracle). Sinon, vous pourriez importer des lignes qui existent dans votre table source (car il n'y a pas de contrainte), mais qui ne peuvent pas être importées dans la table cible.

  • Vérifiez si les index des colonnes sont vraiment les mêmes dans les deux tables (Oracle et DB2) du point de vue de JDBC . D'autres outils peuvent trier par nom de colonne, etc. Mieux encore: Utilisez des noms de colonne (parcourez les noms de colonne dans les métadonnées). Votre approche basée sur les index ne fonctionnera pas si les colonnes sont réorganisées, ce qui peut arriver, si les colonnes sont supprimées, ajoutées à nouveau, etc. Par exemple, si vous avez un select * from x et un insert into x values(...), l'ordre des colonnes est pertinent.

  • Vérifiez si vous avez des valeurs null dans votre table source dans les colonnes qui font partie de la contrainte. Peut-être Oracle gère-t-il les valeurs null de la contrainte différemment de DB2, si elle est protégée par un index.

0
Beryllium