Getting Error Wrong number or types of arguments while calling stored procedure in Oracle using Spring Data Jpa - oracle

I have Oracle PL/SQL procedure as below
CREATE OR REPLACE FUNCTION getCollectorP2PSummary(inCollectorId IN VARCHAR2)
RETURN SYS_REFCURSOR
AS
p_cursor SYS_REFCURSOR;
BEGIN
OPEN p_cursor FOR
SELECT inCollectorId AS collectorId,
COALESCE(SUM(CASE WHEN A.PYMT_SCHD_SUM_STATUS_IND = 'BROKEN' AND TRUNC(TO_DATE(PYMT_SCHD_SUM_STATUS_DT, 'YYYYMMDD')) BETWEEN TRUNC(SYSDATE - INTERVAL '30' DAY) AND TRUNC(SYSDATE) THEN 1 ELSE 0 END), 0) as brokenInLast30Days,
COALESCE(SUM(CASE WHEN A.PYMT_SCHD_SUM_STATUS_IND = 'ACTIVE' THEN 1 ELSE 0 END), 0) AS activePromiseToPays,
COALESCE(SUM(CASE WHEN A.PYMT_SCHD_SUM_STATUS_IND = 'ACTIVE' THEN B.DLNQ_AMT ELSE 0 END), 0) as delinquencyAmount,
COALESCE(SUM(CASE WHEN A.PYMT_SCHD_SUM_STATUS_IND = 'ACTIVE' THEN A.TOTAL_SCHD_PYMT_AMT ELSE 0 END), 0) as promiseToPayAmount,
COALESCE(SUM(CASE WHEN A.PYMT_SCHD_SUM_STATUS_IND = 'ACTIVE' THEN A.TOTAL_SCHD_PYMT_AMT - A.total_actual_pymt_amt ELSE 0 END), 0) as remainingAmount,
COALESCE(COUNT(CASE WHEN A.PYMT_SCHD_SUM_STATUS_IND = 'ACTIVE' AND C.pymt_schd_status_ind = 'PENDING' THEN C.pymt_schd_sum_seq END), 0) as pendingPayments
FROM PYMT_SCHD_SUM A
LEFT JOIN COLL_ACCT B ON A.ACCT_NBR = B.ACCT_NBR
LEFT JOIN PYMT_SCHD C ON B.ACCT_NBR = C.ACCT_NBR
WHERE B.CLLCTR_ID = inCollectorId;
RETURN p_cursor;
END;
I'm calling it with JPA as below
ManagerSummaryEntity.java
#NamedStoredProcedureQuery(
name = "getManagerP2PSummary",
procedureName = "getManagerP2PSummary",
resultClasses = ManagerSummaryEntity.class,
parameters = {
#StoredProcedureParameter(mode = ParameterMode.REF_CURSOR, type = void.class),
#StoredProcedureParameter(mode = ParameterMode.IN, type = String.class)
}
)
#Data
#NoArgsConstructor
#AllArgsConstructor
#Entity
public class ManagerSummaryEntity implements Serializable {
#Id
private String collectorId;
Long brokenInLast30Days;
Long activePromiseToPays;
BigDecimal delinquencyAmount;
BigDecimal promiseToPayAmount;
BigDecimal remainingAmount;
Long pendingPayments;
}
EntityManagerUtils.java
#Transactional
public Optional<ManagerSummaryEntity> getManagerP2PSummary(EntityManager entityManager, String collectorId) {
try {
StoredProcedureQuery query = entityManager.createNamedStoredProcedureQuery("getManagerP2PSummary");
query.setParameter(2, collectorId);
List<ManagerSummaryEntity> entities = (List<ManagerSummaryEntity>) query.getResultList();
if (query.execute()) {
return Optional.of(entities.get(0));
}
return Optional.empty();
} catch (RuntimeException e) {
log.error(e.getMessage());
return null;
}
}
However, I'm getting below error:
2023-02-07 10:09:16,284 ERROR [org.hib.eng.jdb.spi.SqlExceptionHelper] (executor-thread-0) ORA-06550: line 1, column 7: PLS-00306: wrong number or types of arguments in call to 'GETCOLLECTORP2PSUMMARY' ORA-06550: line 1, column 7: PL/SQL: Statement ignored
Can anyone tell me how to resolve this ?
P.S: I tried passing named parameter as well, but it didn't work either.

Related

Oracle is having issues with hibernate generated query, generates query with _ in row num

I am using hibernate and using criteria query, database is Oracle. The below is the query that gets generated.
"
WITH query AS (
SELECT inner_query.*,
ROW_NUMBER() OVER (ORDER BY CURRENT_TIMESTAMP) as __hibernate_row_nr__
FROM (
select this_.MODIFIEDTIME as MODIFIED1_1_1_,
this_.FIELDNAME as FIELDNAM2_1_1_,
this_.EMPNBR as EMPNBR3_1_1_
from EMPLOYEEAUDIT this_
left outer join EMPLOYEE employee2_ on this_.EMPNBR=employee2_.EMPNBR
) inner_query
)
SELECT MODIFIED1_1_1_,FIELDNAM2_1_1_,EMPNBR3_1_1_
FROM query WHERE __hibernate_row_nr__ >= 1
AND __hibernate_row_nr__ < 10;"
It is throwing the below error:-
SQL Error: 911, SQLState: 22019
ORA-00911: invalid character
However, if i take the SQL query and repalce the hibernate_row_nr with hibernate_row_nr__ and run it in DbVisualizer it works. It seems Oracle is not able to recognize starting '_' as valid characters. How to fix this issue?
Below is my java code:-
public List<Employee> getEmployeeList(int start, int limit, AgSort sorter) throws UIFilterException {
DetachedCriteria detached = getEmployeeListCriteria(sorter, filters);
return (List<DealSetupAudit>) hibernateTemplate.findByCriteria(detached, start, limit);
}
private DetachedCriteria getEmployeeListCriteria(AgSort sorter) throws UIFilterException {
DetachedCriteria detached = getBaseCriteria(DealSetupAudit.class, sorter);
return detached;
}
protected <T> DetachedCriteria getBaseCriteria(Class<T> genericType, AgSort sorter) throws UIFilterException {
DetachedCriteria criteria = DetachedCriteria.forClass(genericType);
addSorter(criteria, sorter);
return criteria;
}
protected void addSorter(DetachedCriteria criteria, AgSort sort) {
if (sort != null) {
Order order = null;
if (sort.getDir().equalsIgnoreCase(Constants.DESC)) {
order = Order.desc(sort.getColumn());
} else {
order = Order.asc(sort.getColumn());
}
criteria.addOrder(order);
}
}
I am using Hibernate4, below is my application.properties :-
oracle.datasource.driver-class-name=oracle.jdbc.OracleDriver
oracle.datasource.url=******
oracle.datasource.username=*****
oracle.datasource.password=*****
oracle.jpa.database-platform=org.hibernate.dialect.Oracle10gDialect
oracle.jpa.properties.hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
Double quotes? Usually a really, really bad idea. I'd suggest you to avoid such things and use valid column names / aliases.
SQL> select dname _invalid_alias_
2 from dept
3 where deptno = 10;
select dname _invalid_alias_
*
ERROR at line 1:
ORA-00911: invalid character
SQL> select dname "_valid_alias_"
2 from dept
3 where deptno = 10;
_valid_alias_
--------------
ACCOUNTING
SQL>

Is there a way to optimize this query?

declare
n_docid number;
n_orgid number;
n_docstateid number;
n_docstateversion number;
n_doctypeid number;
n_count number;
begin
for I in (select DOCID from DC_EXP_BO where INF_DATEDOCUMENT > '01.01.17' and
INF_DATEDOCUMENT < '31.12.17')
loop
begin
select DOCID, DOCSTATEID, DOCTYPEID, DOCSTATE_VERSION into
n_docid, n_docstateid, n_doctypeid, n_docstateversion from DOC
where DOCID = I.DOCID;
select ORGID into n_orgid from ORG
where systemname = (select distinct RB_CODEGRBS from DC_EXP_BO where DOCID = n_docid);
select count(*) into n_count from ROUTECONTEXT
where DOCID = n_docid and ORGID = n_orgid;
if (n_count = 0) then
insert into ROUTECONTEXT
(ROUTECONTEXTID, VERSION, DOCID, LOCALDOCSTATEID, OWNERID, LASTPRINTDATE, PRINTED, RECEIVED, ORGID, ARCHIVE, EXPORTSTATUS, DOCTYPEID, DOCSTATEID, DOCSTATE_VERSION, DELETED)
values
(sq_routeContext.NEXTVAL, 0, n_docid, n_docstateid, null, null, 0, 0, n_orgid, 0, 'NOT_EXPORTED', n_doctypeid, n_docstateid, n_docstateversion, 0);
end if;
exception
when no_data_found then
continue;
end;
end loop;
end;
/
We wrote datafix for production. And there is a problem.
For statement select can return about 1 million IDs. Is it possible someway to optimize this query?
The most effective optimization you can make is to replace the row-by-row inserts and lookups in a loop with a single set-based operation:
insert into ROUTECONTEXT
(ROUTECONTEXTID, VERSION, DOCID, LOCALDOCSTATEID, OWNERID, LASTPRINTDATE, PRINTED, RECEIVED, ORGID, ARCHIVE, EXPORTSTATUS, DOCTYPEID, DOCSTATEID, DOCSTATE_VERSION, DELETED)
select sq_routeContext.NEXTVAL,
0,
DOC.DOCID,
DOC.DOCSTATEID,
null,
null,
0,
0,
org.ORGID,
0,
'NOT_EXPORTED',
DOC.DOCSTATEID,
DOC.DOCTYPEID,
DOC.DOCSTATE_VERSION ,
0
from DC_EXP_BO
join doc
on DC_EXP_BO.DOCID = DOC.DOCID
join org
on org.systemname = DC_EXP_BO.RB_CODEGRBS
where DC_EXP_BO.INF_DATEDOCUMENT > date '2017.01.01'
and DC_EXP_BO.INF_DATEDOCUMENT < date '2017.12.31'
and not exists ( select null
from ROUTECONTEXT
where ROUTECONTEXT.DOCID = doc.docid
and ROUTECONTEXT.ORGID = org.orgid
)
/
Assuming DC_EXP_BO.INF_DATEDOCUMENT is a DATE datatype, using proper date semantics may be more performative and will certainly be safer. But it's a string replace that bit of the WHERE clause with what you posted in your question.

Oracle case statement not working

I want to use case statement for a column like below
SELECT sr_no, TYPE, stage, party_name, amount, remarks, exp_type, exp_id,
voucher_no, cheque_no, cheque_dt, chq_favr_name, attachment,
CASE NVL (amount, 0) = 0 THEN checkVal = 0
ELSE
checkVal = 1
FROM xxcus.xxacl_pn_expense_info
WHERE mkey = '354'
AND ((NVL (amount, 0) <> 0) OR (party_name IS NOT NULL))
ORDER BY sr_no
But I am getting error as
ORA-00923: FROM keyword not found where expected
SELECT sr_no, TYPE, stage, party_name, amount, remarks, exp_type, exp_id,
voucher_no, cheque_no, cheque_dt, chq_favr_name, attachment,
CASE WHEN NVL(amount, 0) = 0 THEN 0 ELSE 1 END AS checkVal
FROM xxcus.xxacl_pn_expense_info
WHERE mkey = '354'
AND ((NVL (amount, 0) <> 0) OR (party_name IS NOT NULL))
ORDER BY sr_no
you're missing an END
SELECT sr_no, TYPE, stage, party_name, amount, remarks, exp_type, exp_id,
voucher_no, cheque_no, cheque_dt, chq_favr_name, attachment,
CASE WHEN NVL (amount, 0) = 0 THEN checkVal = 0
ELSE
checkVal = 1
END
FROM xxcus.xxacl_pn_expense_info
WHERE mkey = '354'
AND ((NVL (amount, 0) <> 0) OR (party_name IS NOT NULL))
ORDER BY sr_no

If statement within Where clause

I am working with a query which contains "IF" statements within a "WHERE" clause. But PL\SQL Developer is giving some errors while executing it. Can anyone please help me with the correct query? Here is the query:
SELECT t.first_name,
t.last_name,
t.employid,
t.status
FROM employeetable t
WHERE IF status_flag = STATUS_ACTIVE then t.status = 'A'
IF status_flag = STATUS_INACTIVE then t.status = 'T'
IF source_flag = SOURCE_FUNCTION then t.business_unit = 'production'
IF source_flag = SOURCE_USER then t.business_unit = 'users'
AND t.first_name LIKE firstname
AND t.last_name LIKE lastname
AND t.employid LIKE employeeid;
I receive the error "ORA-00920: invalid relational operator".
Placing brackets around status_flag = STATUS_ACTIVE results in error "ORA-00907: missing right parenthesis"
CASE might help you out:
SELECT t.first_name,
t.last_name,
t.employid,
t.status
FROM employeetable t
WHERE t.status = (CASE WHEN status_flag = STATUS_ACTIVE THEN 'A'
WHEN status_flag = STATUS_INACTIVE THEN 'T'
ELSE null END)
AND t.business_unit = (CASE WHEN source_flag = SOURCE_FUNCTION THEN 'production'
WHEN source_flag = SOURCE_USER THEN 'users'
ELSE null END)
AND t.first_name LIKE firstname
AND t.last_name LIKE lastname
AND t.employid LIKE employeeid;
The CASE statement evaluates multiple conditions to produce a single value. So, in the first usage, I check the value of status_flag, returning 'A', 'T' or null depending on what it's value is, and compare that to t.status. I do the same for the business_unit column with a second CASE statement.
You can't use IF like that. You can do what you want with AND and OR:
SELECT t.first_name,
t.last_name,
t.employid,
t.status
FROM employeetable t
WHERE ((status_flag = STATUS_ACTIVE AND t.status = 'A')
OR (status_flag = STATUS_INACTIVE AND t.status = 'T')
OR (source_flag = SOURCE_FUNCTION AND t.business_unit = 'production')
OR (source_flag = SOURCE_USER AND t.business_unit = 'users'))
AND t.first_name LIKE firstname
AND t.last_name LIKE lastname
AND t.employid LIKE employeeid;

PreparedStatement and 'null' value in WHERE clause

I am using PrepareStatement and BatchUpdate for executimg a UPDATE query. In for loop I create a Batch. At end of loop I execute batch.
Above logic works fine if SQL query used in PrepareStatement does not have null values in WHERE claues.
Update Statement fails if there is null value in WHERE clasue.
My code looks something like this,
connection = getConnection();
PreparedStatement ps = connection.prepareStatement(
"UPDATE TEST_TABLE SET Col1 = true WHERE Col2 = ? AND Col3 = ?");
for (Data aa : InComingData){
if(null == aa.getCol2()){
ps.setNull(1, java.sql.Types.INTEGER);
}
else {
ps.setInteger(1,aa.getCol2())
}
if(null == aa.getCol3()) {
ps.setNull(2, java.sql.Types.INTEGER);
}
else {
ps.setInteger(2,aa.getCol3())
}
ps.addBatch();
}
ps.executeBatch();
connection.commit();
Any help would be appreciated.
If you do not wish to generate SQL dynamically, you may use NVL on all the nullable columns in your WHERE clause to convert null into some value that the column will never contain; and while setting the bind variables in Statement just convert null to the same value used in NVL function. For example,
String sql = "UPDATE TEST_TABLE SET Col1 = true
WHERE NVL(Col2, -1) = ? AND NVL(Col3, -1) = ?";
And in Statement:
ps.setInt(1, aa.getCol2() == null ? -1 : aa.getCol2().intValue());
ps.setInt(2, aa.getCol3() == null ? -1 : aa.getCol3().intValue());
That's because in SQL, something = null is always false, even if something is null. To compare a column with null, you must use where col2 is null, instead of where col2 = null.

Resources