Java подготовленный оператор с oracle merge / upsert - отсутствует индекс IN или OUT в индексе - PullRequest
0 голосов
/ 14 февраля 2020

Я пытаюсь выполнить MERGE для одной таблицы (вставьте, если нет, еще обновите).

мое подготовленное утверждение выглядит так:

merge into table USING DUAL ON (primarykey=?) 
when not matched then insert (colum1,colum2,columnprimarykey,column4,column5,column6,column7,column8,column9,column10,column11,column12) VALUES (?,?,?,?,?,?,?,?,?,?,?,?) 
when matched then update set column1=?,column2=?,column4=?,column5=?,column6=?,column7=?,column8=?,column9=?,column10=?,column11=?,column12=?

Но я получаю следующую ошибку при выполнении подготовленного оператора:

Причина: java. sql .SQLException: отсутствует параметр IN или OUT в индексе :: 13 в oracle .jdb c .driver.OraclePreparedStatement.processCompletedBindRow (OraclePreparedStatement. java: 1937) ~ [ojdbc8-19.3.0.0.jar! /: 19.3.0.0.0]

Следующее работает нормально, если выполняется непосредственно в SQL разработчику. Он вставит новую запись с 12 столбцами, если primarykeycolumn = 99 не найден в таблице. Он обновит остальные 11 столбцов, если в таблице найден primarykeycolumn = 99.

merge into table USING DUAL ON (primarykey=99) 
when not matched then insert 
(colum1,colum2,column3/primarykey,column4,column5,column6,column7,column8,column9,column10,column11,column12) VALUES (somevalue,somevalue,99,somevalue,somevalue,somevalue,somevalue,somevalue,somevalue,somevalue,somevalue,somevalue) 
when matched then update set 
column1=somevalue,column2=somevalue,column4=somevalue,column5=somevalue,column6=somevalue,column7=somevalue,column8=somevalue,column9=somevalue,column10=somevalue,column11=somevalue,column12=somevalue

Java код:

public Mono<String> createData(final Mono<Record> inputMono) {
    final String someID = UUID.randomUUID().toString();

    final Mono<Integer> asyncUpdate = inputMono.flatMap(record -> {
        return beginUpdate(dataSource, 
  sqlStatementSharedAbove).withStatementEnricher(stmt -> {
            stmt.setString(1, record.getFirstName());
            stmt.setString(2, record.getLastName());
            stmt.setInt(3, record.getUserId());
            stmt.setString(4, record.getCOMPANYNAME());
            stmt.setInt(5, record.getCOMPANYID());
            stmt.setString(6, record.getEMAILID());
            stmt.setTimestamp(7,Timestamp.valueOf(now));
            stmt.setTimestamp(8,Timestamp.valueOf(now));
            stmt.setString(9,record.getDEPARTMENTNAME());
            stmt.setInt(10, record.getActiveInd());
            stmt.setInt(11, record.getTypeCode());
            stmt.setString(12, record..getTypeName());
        }).build();

    });
    return asyncUpdate.doOnSuccess(affectedRows -> LOGGER.debug("Added 
 {} rows with ID {}", affectedRows, someID))
        .map(affectedRows -> someID);
}

1 Ответ

0 голосов
/ 14 февраля 2020

Часть UPDATE может использовать только значения столбцов, возвращаемые таблицей (запросом) из части USING.

Так что вам нужно переписать ваше утверждение примерно так:

merge into the_table USING 
(
  select ? as primarykey, 
         ? as column1, 
         ? as column2, 
         ? as column3,
         ....
  from dual
) x ON (x.primarykey = the_table.primarykey) 
when not matched then 
  insert (column1,column2,primarykey,column3, ...) 
  VALUES (x.column1, x.column2, x.primarykey, x.column3, ...) 
when matched then update 
  set column1 = x.column1,
      column2 = x.column2,
      ....
...