Get Exception while executing a oracle procedure in java - java

I am trying to execute a procedure in oracle, but i get a exception while executing the procedure.Please help me where i am wrong.
Error :
java.sql.SQLException: ORA-06550: line 1, column 36:
PLS-00103: Encountered the symbol ";" when expecting one of the following:
. ( ) , * # % & = - + < / > at in is mod remainder not rem =>
<an exponent (**)> <> or != or ~= >= <= <> and or like like2
like4 likec between || indicator multiset member submultiset
The symbol ")" was substituted for ";" to continue.
Procedure :
CREATE OR REPLACE PROCEDURE "TEST_101"."AVG_UNLOADING"
(
P_CODE IN VARCHAR2,
P_DATE IN VARCHAR2,
P_VANID IN NUMBER,
P_CURSOR OUT SYS_REFCURSOR
)
IS
BEGIN
OPEN P_CURSOR
FOR
select CARGO_NAME,IMP_EXP_NAME,'TEMP_CARGO_Import',ROUND(SUM(QTY)/((((extract(day from max(END_TIME)-DISCHRG_CMNCD_ANCHRG_TM)*(24*60))+
(extract(day from max(END_TIME)- DISCHRG_CMNCD_ANCHRG_TM)*(60)) + (EXTRACT(DAY FROM max(END_TIME)- DISCHRG_CMNCD_ANCHRG_TM)))-DELAYS)/(24*60))) QTY
from(SELECT (SELECT C.CARGO_CATEGORY_NAME FROM IPT_CARGOMASTER C WHERE C.CARGO_CODE =LL.CARGO_CODE )CARGO_NAME,IL.IMP_EXP_NAME,CASE L.CARGO_TYPE_CODE WHEN 'VC001' THEN LL.DISCHARGE_QUANTITY WHEN 'VC002' THEN LL.QUANTITY_GMT WHEN 'VC004' THEN LL.QUANTITY_GMT
else LL.DISCHARGE_QUANTITY end QTY ,L.DISCHRG_CMNCD_ANCHRG_TM,LL.END_TIME ,(SELECT SUM(T3.TOTAL_TIME) FROM IPT_LOADUNLOADDELAYLINES T3 WHERE T3.ID = L.ID AND T3.MINUS_DELAY_HOURS = 'true') AS DELAYS
,LL.LINE_ID,L.VAN_ID FROM IPT_LOADINGUNLOADING L JOIN IPT_LOADUNLOADOPERATIONLINES LL ON L.ID=LL.ID LEFT JOIN IPT_IMPORTEXPORTFORM I ON I.VAN_ID=L.VAN_ID JOIN IPT_IGMEPCARGOLINES IL ON I.ID=IL.ID AND LL.CARGO_CODE=IL.CARGO_CODE
where L.PORTDETAIL_CODE= P_CODE and I.PORTDETAIL_CODE=L.PORTDETAIL_CODE and IL.IMP_EXP_NAME like '%KKR%' AND LL.END_TIME<=TO_TIMESTAMP(TO_CHAR(P_DATE || ' 06:59'),'dd/MM/yyyy HH:MI')
and L.VAN_ID in (P_VANID )
)t group by CARGO_NAME, IMP_EXP_NAME, 'TEMP_CARGO_Import',DISCHRG_CMNCD_ANCHRG_TM,DELAYS;
END AVG_UNLOADING;
Executing procedure
stkagentlist = "{call AVG_UNLOADING(?,?,?,?}";
callableStatement = conn.prepareCall(stkagentlist);
callableStatement.setString(1, portCode);
callableStatement.setString(2, dt );
callableStatement.setString(3, vanids );
callableStatement.registerOutParameter(4, OracleTypes.CURSOR);
callableStatement.executeUpdate();

stkagentlist = "{call AVG_UNLOADING(?,?,?,?}";
I think in this statement the closing round bracket is missing, it should be:
stkagentlist = "{call AVG_UNLOADING(?,?,?,?)}";

Related

get a custom query result containing Clob in Java Spring App

I need to get a very long string from Oracle DB in Spring App, but using a function returning clob leads to internal server error 500. How to get a custom query result containing Clob?
PL/SQL function returning a very long string in clob:
create or replace function getVeryLongString(id_ in number)
return clob as
CURSOR cur IS select x.TARGET || ' pX=' || x.px as tpx -- to get concat string in order of PX desc
from (
select distinct a.ID,
a.TARGET,
MAX(a.PX) OVER (PARTITION BY a.TARGET, a.ID) as px
from BA_ACTIVITYDATA A
where A.TARGET is not null
and a.ID = id_
order by px desc
) x;
l_data clob := '';
begin
FOR fld IN cur
LOOP
l_data := l_data || fld.tpx || ' | ';
end loop;
return rtrim( l_data, ' | ');
end
;
I use this function in Query in Java Spring app:
public interface TargetRepository extends JpaRepository<List, Long> {
#Query(
value = "select t1.fieldA,\n" +
" t1.fieldB,\n" +
" t2.fieldC,\n" +
" getVeryLongString(t3.value1) as fieldD\n" +
"from tableA t1\n" +
"join tableB t2 on t1.id = t2.id\n" +
"join tableC t3 on t3.id = t2.id\n" +
"where t.id = :id",
nativeQuery = true
)
DataTypePX getDataById(Long id);
}
TargetActivity interface looks like:
public interface DataTypePX {
String getFIELDA();
String getFIELDB();
String getFIELDC();
String getFIELDD();
}
Using the above code leads to 500 ERROR.
to fix it I need to change function getVeryLongString as returning varchar2 - it works, but it leads to cutting of result string only to 4000 symbols:
create or replace function getVeryLongString(id_ in number)
return varchar2 as
CURSOR cur IS select x.TARGET || ' pX=' || x.px as tpx -- to get concat string in order of PX desc
from (
select distinct a.ID,
a.TARGET,
MAX(a.PX) OVER (PARTITION BY a.TARGET, a.ID) as px
from BA_ACTIVITYDATA A
where A.TARGET is not null
and a.ID = id_
order by px desc
) x;
-- l_data varchar2(32767) := '';
l_data clob := '';
begin
FOR fld IN cur
LOOP
l_data := l_data || fld.tpx || ' | ';
end loop;
return rtrim( substr(l_data, 1, 4000), ' | ');
end;

Getting error in Procedure Call from Java Code

A) Getting This Error :
" PLS-00306: wrong number or types of arguments in call to 'PRC_ST_PSB_BNK_REF_GEN'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored "
1) JAva Code
SqlParameterSource inParameters =
new MapSqlParameterSource().addValue("IN_BATCHRUNID", Long.valueOf(this.batchRunId));
this.jdbcCall =
new SimpleJdbcCall(this.jdbcTemplate).withProcedureName("PRC_ST_PSB_BNK_REF_GEN").declareParameters(new SqlParameter[]
{ new SqlOutParameter("OUT_REFCURSOR", -10, new BeanPropertyRowMapper(NetBankReconDTO.class)) });
this.recuMap = this.jdbcCall.execute(inParameters);
2) Procedure
CREATE or REPLACE PROCEDURE "PRC_ST_CSB_REF_GEN"
(
IN_BATCHRUNID NUMBER,
OUT_REFCURSOR OUT SYS_REFCURSOR,
OUT_TOTREC OUT NUMBER,
OUT_SUCCREC OUT NUMBER,
OUT_FAILEREC OUT NUMBER,
OUT_STATUSCODE OUT NUMBER,
OUT_STATUSDESC OUT VARCHAR2,
OUT_TOTALAMT OUT NUMBER,
OUT_TOTALREC OUT NUMBER
)
AS
LV_NETBANKID NUMBER;
LV_CNT NUMBER;
LV_AMT NUMBER(18,2);
LV_NTRP_STATUS NUMBER;
BEGIN
SELECT NETBANKID INTO LV_NETBANKID FROM VTSTBATCHPRCSTRN WHERE BATCHRUNID=IN_BATCHRUNID;
UPDATE VTSTREFVOIDREQ RREQ SET REFVOIDBATCHRUNID=IN_BATCHRUNID,CURRSTATUSCODE='A'
WHERE REFVOIDFLAG='V' AND CURRSTATUSCODE='I' AND
EXISTS ( SELECT 1 FROM VTSTAUTHZTRN AUTH WHERE AUTH.TRNREFNO = RREQ.TRNREFNO AND
AUTH.NETBANKID=LV_NETBANKID );
UPDATE VTSTSETTLEREQ SET NBREFBATCHRUNID=IN_BATCHRUNID, CURRSTATUSCODE=6040,CURRSTATUSDESC='Sent to NetBank for Refund'
WHERE NETBANKID=LV_NETBANKID AND CURRSTATUSCODE=6020 AND SETTLETYPE='R';
/* Update NTRP's transaction table */
LV_NTRP_STATUS := FN_NTRP_REFUND_UPDATE(IN_BATCHRUNID);
/* Tot Count And Tot Amount */
SELECT COUNT(1) , NVL(SUM(RREQ.REQAMT),0) INTO LV_CNT, LV_AMT
FROM VTSTREFVOIDREQ RREQ
INNER JOIN VTSTAUTHZTRN AUTH ON AUTH.TRNREFNO = RREQ.TRNREFNO
INNER JOIN CGCMN.VTMESTR STR ON STR.STOREID = AUTH.STOREID
WHERE REFVOIDBATCHRUNID=IN_BATCHRUNID ;
SELECT COUNT(1)+LV_CNT, NVL(SUM(SREQ.SETTLEAMT),0)+LV_AMT INTO LV_CNT, LV_AMT
FROM VTSTSETTLEREQ SREQ
INNER JOIN VTSTAUTHZTRN AUTH ON AUTH.TRNREFNO = SREQ.TRNREFNO
INNER JOIN CGCMN.VTMESTR STR ON STR.STOREID = AUTH.STOREID
WHERE SREQ.NBREFBATCHRUNID=IN_BATCHRUNID AND SREQ.NETBANKID=LV_NETBANKID AND SREQ.CURRSTATUSCODE=6040;
OPEN OUT_REFCURSOR for
SELECT
AUTH.TRNREFNO AS OTHPARAMETER,
'CSB' AS BANKNAME,
'WORLDLINE' AS MEBUSSNAME,
TO_CHAR(AUTH.HOSTTRNDATE,'DD/MM/YYYY HH:MI:SS') AS TRNDATE,
TO_CHAR(RREQ.REFUNDREQDATE,'DD/MM/YYYY HH:MI:SS') AS REFDATE,
NET.NETBANKMEID AS PAYEEID,
AUTH.RRN AS BANKREFNO,
AUTH.TRNREFNO AS TRNREFNO,
AUTH.TOTTRNAMT AS TRNAMT,
RREQ.REQAMT AS REFAMT
FROM VTSTREFVOIDREQ RREQ
INNER JOIN VTSTAUTHZTRN AUTH ON AUTH.TRNREFNO = RREQ.TRNREFNO
INNER JOIN VTSMNETBNK NET ON AUTH.NETBANKID=NET.NETBANKID
INNER JOIN CGCMN.VTMESTR STR ON STR.STOREID = AUTH.STOREID WHERE REFVOIDBATCHRUNID=IN_BATCHRUNID
UNION ALL
SELECT
AUTH.TRNREFNO AS OTHPARAMETER,
'CSB' AS BANKNAME,
'WORLDLINE' AS MEBUSSNAME,
TO_CHAR(AUTH.HOSTTRNDATE,'DD/MM/YYYY HH:MI:SS') AS TRNDATE,
TO_CHAR(SREQ.SETTLEREQDATE,'DD/MM/YYYY HH:MI:SS') AS REFDATE,
NET.NETBANKMEID AS PAYEEID,
AUTH.RRN AS BANKREFNO,
AUTH.TRNREFNO AS TRNREFNO,
AUTH.TOTTRNAMT AS TRNAMT,
SREQ.SETTLEAMT AS REFAMT
FROM VTSTSETTLEREQ SREQ
INNER JOIN VTSTAUTHZTRN AUTH ON AUTH.TRNREFNO = SREQ.TRNREFNO
INNER JOIN VTSMNETBNK NET ON AUTH.NETBANKID=NET.NETBANKID
INNER JOIN CGCMN.VTMESTR STR ON STR.STOREID = AUTH.STOREID
WHERE SREQ.NBREFBATCHRUNID=IN_BATCHRUNID AND SREQ.NETBANKID=LV_NETBANKID AND SREQ.CURRSTATUSCODE=6040;
/* Refund Response Ledger Posting */
SELECT COUNT(1) INTO LV_CNT FROM VTSTSETTLEREQ SREQ
INNER JOIN VTSMLVVEHICLE LV ON LV.LVID=SREQ.LVID AND LV.LVTYPE='A'
WHERE NBREFBATCHRUNID=IN_BATCHRUNID AND SETTLETYPE='R' ;
IF LV_CNT > 0 THEN
BEGIN
PRC_LED_NB_REF_FILERESP( IN_BATCHRUNID, 'SYSTEM','SYSTEM',OUT_STATUSCODE,OUT_STATUSDESC);
END;
END IF;
OUT_SUCCREC:=LV_CNT;
OUT_FAILEREC:=0;
OUT_STATUSCODE:=0;
OUT_STATUSDESC:='SUCCESS';
OUT_TOTALAMT:=LV_AMT;
OUT_TOTALREC:=LV_CNT;
EXCEPTION
WHEN NO_DATA_FOUND THEN
BEGIN
ROLLBACK;
OUT_STATUSCODE := 1;
OUT_STATUSDESC := 'No Data Found';
END;
WHEN OTHERS THEN
BEGIN
ROLLBACK;
OUT_STATUSCODE := 1;
OUT_STATUSDESC := SQLERRM;
END;
END PRC_ST_CSB_REF_GEN;
PLS-00306: wrong number or types of arguments in call to 'PRC_ST_PSB_BNK_REF_GEN'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

Intersection in DB2 using INTERSECT

I have a query in DB2 that I need intersection on.
SELECT * FROM records where id = 1
intersect
SELECT * FROM records where id = 2
Now this size of ids can grow dynamically, do we have anything in DB2 that can take the list of ids as the parameter? something like
intersect in (1,2,3,4,5) so that it may consider intersection on of result set on these ids using a single query?
You can create a TABLE with the ID LIST, and then create a procedure to create dinamically the SQL Statement to Execute.
Something like this:
CREATE PROCEDURE
YOUR_PROCEDURE
(
)
LANGUAGE SQL
SPECIFIC YOUR_PROCEDURE
NOT DETERMINISTIC
MODIFIES SQL DATA
CALLED ON NULL INPUT
INHERIT SPECIAL REGISTERS
SET OPTION
ALWBLK = *ALLREAD ,
ALWCPYDTA = *YES ,
COMMIT = *NONE ,
CLOSQLCSR = *ENDMOD ,
DECRESULT = (31, 31, 00) ,
DFTRDBCOL = *NONE ,
DLYPRP = *NO ,
DYNDFTCOL = *NO ,
DYNUSRPRF = *USER ,
SRTSEQ = *HEX ,
OUTPUT = *PRINT,
DBGVIEW = *SOURCE
BEGIN
DECLARE LAST_ELEMENT SMALLINT DEFAULT 0 ;
DECLARE FIRST_ELEMENT SMALLINT DEFAULT 1 ;
DECLARE STMT VARCHAR ( 5000 ) ;
DECLARE ID_CODE_TO_USE NUMERIC (9 , 0) ;
DECLARE ID_LIST CURSOR FOR
SELECT
ID_CODE
FROM
YOUR_TEMPORARY_TABLE ;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET LAST_ELEMENT = -1 ;
OPEN ID_LIST ;
SET STMT = '' ;
SET FIRST_ELEMENT = 1 ;
FETCH_ID_LIST:
LOOP
FETCH ID_LIST
INTO
ID_CODE_TO_USE ;
-------
IF LAST_ELEMENT = -1 THEN
LEAVE FETCH_ID_LIST ;
END IF ;
-------
IF FIRST_ELEMENT= 1 THEN
SET STMT = 'SELECT * FROM RECORD WHERE ID = ' CONCAT CHAR(ID_CODE_TO_USE)
SET FIRST_ELEMENT = 0 ;
END IF ;
-------
SET STMT = 'INTERSECT SELECT * FROM RECORD WHERE ID = ' CONCAT CHAR(ID_CODE_TO_USE)
END LOOP FETCH_ID_LIST;
CLOSE ID_LIST ;
IF STMT <> '' THEN
EXECUTE IMMEDIATE STMT ;
END IF ;
END ;
Run this as is:
with ids (id) as
(
select id
from xmltable
(
'for $id in tokenize($s, ",") return <i>{string($id)}</i>'
-- the following string of IDs may be passed as a parameter
passing '1,2,3' as "s"
columns id int path 'if (. castable as xs:integer) then xs:integer(.) else ()'
)
)
, tab (id, c1, c2) as
(
values
(1, 1, 1)
, (1, 1, 1)
, (2, 1, 1)
, (2, 1, 1)
, (3, 1, 1)
, (1, 2, 2)
, (2, 2, 2)
)
select t.c1, t.c2
from tab t
join ids i on i.id=t.id
group by t.c1, t.c2
having count(distinct t.id) = (select count(1) from ids);
C1 C2
-- --
1 1
If this is not you want to have, then provide some example with source data and the exact result desired.

JPA / Hibernate pagination in MS SQL Server 2008 eror mapping to object

Given my code below:
Query q = em.createNativeQuery(sql.toString(), SearchDTO.class);
for (String k : parameters.keySet()) {
q.setParameter(k, parameters.get(k));
}
q.setFirstResult((criteria.getPage()-1) * criteria.getLimit());
q.setMaxResults(criteria.getLimit());
return q.getResultList();
Where page is > 1, the sql generated is incorrect:
WITH query AS (SELECT inner_query.*, ROW_NUMBER() OVER (ORDER BY CURRENT_TIMESTAMP) as hibernate_row_nr FROM ( select TOP(?) cc.company_id as page0_, cc.long_name as page1_, cc.reuters_org_id as page2_, ccdom.country_name as country_of_domicile, ccinc.country_name as country_of_incorporation, ccr.region_name as region, ci.industry_name as industry from zz_prp_common_company cc left join zz_prp_common_country ccdom on cc.country_of_domicile = ccdom.country_id left join zz_prp_common_region ccr on ccr.region_id = ccdom.region_id left join zz_prp_common_country ccinc on cc.country_of_domicile = ccinc.country_id left join zz_prp_common_industry ci on cc.industry_id = ci.industry_id where 1=1 order by cc.long_name ) inner_query ) SELECT page0_, page1_, page2_, country_of_domicile, country_of_incorporation, region, industry FROM query WHERE hibernate_row_nr >= ? AND hibernate_row_nr < ?
I cannot understand why it is replacing the alias to my columns to page0_, page1_ and page2_. Due to this the where page0_ replaced the company_id column alias, I am getting this error:
Caused by: com.microsoft.sqlserver.jdbc.SQLServerException: The column name company_id is not valid.
I am using MS SQL Server 2008 R2, and I have setup my hibernate dialect to use org.hibernate.dialect.SQLServer2008Dialect.
I have found the answer to this issue. The sql native query I was using did NOT have any alias on the first 3 columns (company_id, long_name and reuters_org_id). When I debugged the SQLServer2008Dialect, it lead to the method getProcessedSql():
public String getProcessedSql() {
StringBuilder sb = new StringBuilder( sql );
if ( sb.charAt( sb.length() - 1 ) == ';' ) {
sb.setLength( sb.length() - 1 );
}
if ( LimitHelper.hasFirstRow( selection ) ) {
final String selectClause = fillAliasInSelectClause( sb );
int orderByIndex = shallowIndexOfWord( sb, ORDER_BY, 0 );
if ( orderByIndex > 0 ) {
// ORDER BY requires using TOP.
addTopExpression( sb );
}
encloseWithOuterQuery( sb );
// Wrap the query within a with statement:
sb.insert( 0, "WITH query AS (" ).append( ") SELECT " ).append( selectClause ).append( " FROM query " );
sb.append( "WHERE __hibernate_row_nr__ >= ? AND __hibernate_row_nr__ < ?" );
}
else {
hasOffset = false;
addTopExpression( sb );
}
return sb.toString();
}
The private method that sets the page0_, page1_, and page2, is done by fillAliasInSelectClause, an excerpt that does this is:
// Inserting alias. It is unlikely that we would have to add alias, but just in case.
alias = StringHelper.generateAlias( "page", unique );
The solution that worked for me is to provide the column alias on the 3 columns that initially did not have any. So basically, you will need to put alias on all your columns.

Getting an error while calling mySql proceedure

I have created a single procedure for update for different table say country & department.
and in procedure i'hve mentioned an input parameter for table name along with other parameter.
But unfortunately i got an error. Here is mySql Procedure:
CREATE DEFINER=`satish`#`%` PROCEDURE `p_update_Master_Name`(
IN tbl_Name VARCHAR(35),
IN tbl_column_old_value VARCHAR(35),
IN tbl_column_new_value VARCHAR(35),
IN tbl_user_id INT,
OUT msg INT
)
BEGIN
IF EXISTS (SELECT Name from tbl_name where Name = tbl_column_new_value) then
SET msg := '1';
-- failed case
else
UPDATE tbl_name SET Name= tbl_column_value, Modified_Date=now(), Modified_by=tbl_user_id where Name = tbl_column_old_value;
set msg := '0';
-- success
END IF;
END
Im calling this procedure from java file.
CallableStatement cs = conn.prepareCall("{ call p_update_Master_Name(?,?,?,?,?)}");
cs.setString(1, "country");
cs.setString(2, real);
cs.setString(3, mod);
cs.setInt(4, 01);
cs.execute();
cs.registerOutParameter(5, Types.INTEGER);
int i=cs.getInt(5);
but it gives me a mysql.jdbc exception.
com.mysql.jdbc.exceptions.MySQLSyntaxErrorException: Table 'sims.tbl_name' doesn't
exist
Please help me. Thanx in advance
You can't use variables to define table or column (or any other db object for that matter) names in static SQL queries. They should be literals.
You have to use dynamic SQL to achieve your goal. Read more on the topic SQL Syntax for Prepared Statements
Your stored procedure might look like
DELIMITER $$
CREATE PROCEDURE p_update_Master_Name
(
IN tbl_Name VARCHAR(35),
IN tbl_column_old_value VARCHAR(35),
IN tbl_column_new_value VARCHAR(35),
IN tbl_user_id INT,
OUT msg INT
)
BEGIN
SET #sql = CONCAT('SELECT (COUNT(*) > 0) INTO #result FROM ', tbl_name, ' WHERE Name = \'', tbl_column_new_value, '\'');
PREPARE stmt FROM #sql;
EXECUTE stmt;
SET msg = #result;
IF #result = 0 THEN
SET #sql = CONCAT('UPDATE ', tbl_name,
' SET Name = \'', tbl_column_new_value,
'\', Modified_Date = NOW(), Modified_by = ', tbl_user_id,
' WHERE Name = \'', tbl_column_old_value, ' \'');
PREPARE stmt FROM #sql;
EXECUTE stmt;
END IF;
DEALLOCATE PREPARE stmt;
END$$
DELIMITER ;
Here is SQLFiddle demo
It seems there is some error with the procedure syntax
wrong one:
1. SELECT Name from *tbl_name* where Name = tbl_column_new_value) then
SET msg := '1'
In the above line of code you didn't set any value to tal_name;
You can refer the below syntax concentrate on INTO in the query:
CREATE OR REPLACE PROCEDURE getDBUSERByUserId(
p_userid IN DBUSER.USER_ID%TYPE,
o_username OUT DBUSER.USERNAME%TYPE,
o_createdby OUT DBUSER.CREATED_BY%TYPE,
o_date OUT DBUSER.CREATED_DATE%TYPE)
IS
BEGIN
SELECT USERNAME , CREATED_BY, CREATED_DATE
INTO o_username, o_createdby, o_date
FROM DBUSER WHERE USER_ID = p_userid;
END;

Categories