我在Java PreparedStatement和Oracle方面有问题。
简而言之,我想在我的Oracle DB中使用Java创建一个批处理插入。我尝试使用以下代码:
PreparedStatement preparedStmt = connection.prepareStatement(
"INSERT INTO EFM_BAS_DATA_CLEAN_NUM (date_measured, time_measured, value_reported, data_point_id) " +
" VALUES(?,?,?,?)");
PreparedStatement preparedStmt = connection.prepareStatement(query);
for (EfmBasDataCleanNum measure : measuresToInsert) {
preparedStmt.setString(1, new java.sql.Date(measure.getDateMeasured().getTime()));
preparedStmt.setString(2, measure.getTimeMeasured());
preparedStmt.setDouble(3, measure.getValueReported());
preparedStmt.setInt(4, measure.getDataPointId());
preparedStmt.addBatch();
}
try {
preparedStmt.executeBatch();
}catch (SQLException e){ ...
但是,当表中已存在某些记录时,就会出现此错误:
ORA-00001:违反了唯一约束(AFM.UNIQUE_EFM_CLEAN_NUM)
因为我对此字段有限制。
因此,在线上,我找到了许多解决方案。
我尝试了以下查询:
String query = "INSERT INTO EFM_BAS_DATA_CLEAN_NUM (date_measured, time_measured, value_reported, data_point_id) "+
" SELECT TO_DATE(?,'DD/MM/YYYY HH24:MI:SS'),TO_DATE(?,'DD/MM/YYYY HH24:MI:SS'),?,? FROM DUAL "+
" MINUS "+
" SELECT date_measured, time_measured, value_reported, data_point_id FROM efm_bas_data_clean_num";
或:
String query = " INSERT INTO EFM_BAS_DATA_CLEAN_NUM ( date_measured, time_measured, value_reported, data_point_id ) "
+" SELECT TO_DATE(?, 'DD/MM/YYYY HH24:MI:SS'), TO_DATE(?, 'DD/MM/YYYY HH24:MI:SS'),?,? FROM DUAL "
+" WHERE not exists("
+" SELECT * FROM EFM_BAS_DATA_CLEAN_NUM "
+" WHERE DATE_MEASURED=TO_DATE(?, 'DD/MM/YYYY HH24:MI:SS') "
+" AND TIME_MEASURED=TO_DATE(?, 'DD/MM/YYYY HH24:MI:SS') "
+" AND VALUE_REPORTED=? "
+" AND DATA_POINT_ID=? )";
最后是:
String query = "MERGE INTO EFM_BAS_DATA_CLEAN_NUM bd1 USING ("
+" SELECT TO_DATE(?, 'DD/MM/YYYY HH24:MI:SS') as DATE_MEASURED, "
+" TO_DATE(?, 'DD/MM/YYYY HH24:MI:SS') as TIME_MEASURED,"
+" ? as VALUE_REPORTED,"
+" ? as DATA_POINT_ID FROM DUAL "
+" ) bd2 on (bd1.DATE_MEASURED=bd2.DATE_MEASURED AND"
+" bd1.TIME_MEASURED=bd2.TIME_MEASURED AND"
+" bd1.VALUE_REPORTED=bd2.VALUE_REPORTED AND"
+" bd1.DATA_POINT_ID=bd2.DATA_POINT_ID)"
+" WHEN NOT MATCHED THEN "
+" INSERT (date_measured, time_measured, value_reported, data_point_id) "
+" VALUES(bd2.DATE_MEASURED,bd2.TIME_MEASURED,bd2.VALUE_REPORTED,bd2.DATA_POINT_ID)";
但是,尽管在AquaData Studio中执行查询一直可行(或者,当是新记录时,它会被插入,而当记录已经存在时,它不会被插入,没有错误),但是在应用程序运行时,我仍然可以相同的错误:
ORA-00001:违反了唯一约束(AFM.UNIQUE_EFM_CLEAN_NUM)
也许我错了? 谢谢!
答案 0 :(得分:0)
代码的“不存在的地方”版本应该可以使用。
我会再次检查您是否正在设置?值正确显示在Java代码中,以便插入值与“不存在的地方”值相同。
我用自己的表尝试了您的代码,它起作用了。我使用select'X'代替*,但这没关系。我的sorydct_cert_key是唯一密钥。
private void testInsert() throws SQLException {
String first = "8ADA";
Integer second = 8;
String third = "ADA Failed";
String fourth = "EXC";
String sql = "INSERT INTO SORYDCT(SORYDCT_CERT_KEY," +
" SORYDCT_CERT_CODE," +
" SORYDCT_CERT_DESC," +
" SORYDCT_PROGRAM," +
" SORYDCT_COUNT_CODE)" +
" SELECT ?,?,?,?, NULL" +
" FROM DUAL" +
" WHERE NOT EXISTS ( SELECT 'X'" +
" FROM SORYDCT" +
" WHERE SORYDCT_CERT_KEY = ?)";
PreparedStatement insertStatement = null;
try {
insertStatement = conn.prepareStatement(sql);
insertStatement.setNString(1, first);
insertStatement.setInt(2, second);
insertStatement.setString(3, third);
insertStatement.setString(4, fourth);
insertStatement.setString(5, first);
insertStatement.executeUpdate();
conn.commit();
} catch (SQLException e) {
System.out.println(ERROR_STRING);
System.out.println("Failure while inserting records - 1");
onException(e);
} finally {
try {
insertStatement.close();
} catch (SQLException e) {
}
}
first = "TEST";
second = 0;
third = "Test";
fourth = "EXC";
System.out.println(sql);
insertStatement = null;
try {
insertStatement = conn.prepareStatement(sql);
insertStatement.setNString(1, first);
insertStatement.setInt(2, second);
insertStatement.setString(3, third);
insertStatement.setString(4, fourth);
insertStatement.setString(5, first);
insertStatement.executeUpdate();
conn.commit();
} catch (SQLException e) {
System.out.println(ERROR_STRING);
System.out.println("Failure while inserting records - 2 ");
onException(e);
} finally {
try {
insertStatement.close();
} catch (SQLException e) {
}
}
} }