SQL statement that uses a #variable fails when executed in java - java

I have the following statement which requires an SQL variable:
SELECT #i := 53; UPDATE my_table SET index = (SELECT #i := #i + 1), status = 0 WHERE id = '12345' ORDER BY seqindex ASC;
For some reason it works fine when I execute it on MySQL's workbench but it fails whenever I execute it within Java. I get org.springframework.jdbc.BadSqlGrammarException.
Any help will be appreciated.

Use Single quotes for table name or column name they have underscore like this 'my_table'
SELECT #i := 53; UPDATE 'my_table' SET index = (SELECT #i := #i + 1),
status = 0 WHERE id = '12345' ORDER BY seqindex ASC;

Related

Incorrect Syntax near WHERE error in generated SQL

I am generating the below SQL. From my code I am using a where condition list to collect all the Where logic and insert it after the Join logic is set-up. However, I am getting a very generic syntax error and I can't figure out why. I am pretty sure the logic is properly organized however, when inserting the where statement it throws the syntax error
Incorrect Syntax near WHERE
The {h-schema} are just generated database and table names.
The code:
SELECT count(*) AS ID
FROM (
SELECT 'PREAPPROVAL' AS type, pa.id AS id FROM {h-schema}preapproval AS pa
LEFT JOIN {h-schema}risk_limit AS lim ON pa.limit_id = lim.id
LEFT JOIN {h-schema}desk AS d ON lim.desk_enterprise_id = d.enterprise_id AND CAST(pa.creation_date_time AS date) BETWEEN d.start_date AND d.end_date
WHERE pa.status = 'APPROVED' AND pd.end_date = NULL <-------------------------SYNTAX ERR HERE
OR pa.status = 'DECLINED' AND pa.completion_date_time > '2021-01-28 13:02:13'
OR pa.status = 'IN_PROGRESS'
OR pa.creation_date_time > '2021-01-28 13:02:13'
AND COALESCE(lim.policy_enterprise_id, d.policy_enterprise_id) IN (6)
UNION
SELECT 'BREACH' AS type, br.id AS id FROM {h-schema}breach AS br
LEFT JOIN {h-schema}risk_limit AS lim ON br.limit_id = lim.id
LEFT JOIN {h-schema}desk AS d ON lim.desk_enterprise_id = d.enterprise_id
AND br.reporting_date BETWEEN d.start_date AND d.end_date
LEFT JOIN {h-schema}valid_breach_recommendation AS vbr_approve ON vbr_approve.id = (SELECT TOP(1) id FROM {h-schema}valid_breach_recommendation
WHERE breach_id = br.id AND outcome = 'APPROVE'
ORDER BY creation_date_time DESC, id DESC)
LEFT JOIN {h-schema}valid_breach_decision AS vbd
ON vbd.id = (SELECT TOP(1) id FROM {h-schema}valid_breach_decision
WHERE breach_id = br.id
ORDER BY creation_date_time DESC, id DESC)
LEFT JOIN {h-schema}breach AS child_br ON br.id = child_br.parent_breach_id
WHERE br.status = 'APPROVED' AND vbd.end_date = NULL <--------------------SYNTAX ERR HERE
OR br.status = 'DECLINED' AND br.completion_date_time > '2021-01-28 13:02:14'
OR br.status = 'IN_PROGRESS'
OR br.creation_date_time > '2021-01-28 13:02:14'
AND child_br.id IS NULL
AND CASE br.status
WHEN 'IN_PROGRESS' THEN vbr_approve.start_date
WHEN 'APPROVED' THEN vbd.start_date
WHEN 'CANCELLED' THEN vbd.start_date
ELSE NULL
END IS NOT NULL AND COALESCE(lim.policy_enterprise_id, d.policy_enterprise_id) IN (6)
) AS issue
This is actually version issue. In latest version of SQL support like
create procedure sp_name
(
#name varchar(50) NULL
)
...
But the older version of SQL doesn't support with this way. For older version we need to provide '=NULL'
There is some syntax error due to {h-schema}, remove {h-schema} and your code has no syntax error. Remove {h-schema} and your code works fine.

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

Select Count stored procedure with dynamic query not working correctly

-I'm trying to execute a stored procedure that should returns me the result of a Count, but it gives me the following error(it's in portuguese):
2019-04-01 10:13:49.215 WARN 7068 --- [io-8080-exec-10] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 214, SQLState: S0002
2019-04-01 10:13:49.216 ERROR 7068 --- [io-8080-exec-10] o.h.engine.jdbc.spi.SqlExceptionHelper : O procedimento espera o parĂ¢metro '#statement' do tipo 'ntext/nchar/nvarchar'.
-I dont quite understand, because the only parameter that i setted is the table name, which i'm passing on my repository execution code.
-This is my stored procedure:
ALTER PROCEDURE [dbo].[usp_verificarTabelaCadMov] (
#NomeTabela VARCHAR(20)
)
AS
BEGIN
SET NOCOUNT ON;
Declare #Comando Varchar(1000)
Declare #Resultado INT;
Set #Comando = 'SELECT #Resultado = COUNT(*) FROM sysobjects WHERE nome = ' + QUOTENAME(#NomeTabela)
exec sp_executesql #Comando , N'#Resultado INT OUTPUT', #Resultado = #Resultado OUTPUT
SELECT #Resultado
END;
GO
-This is my execution in my Repository:
#Query(value = "EXECUTE usp_verificarTabelaCadMov :tabela", nativeQuery = true)
public Integer verificarTabela(#Param("tabela") String tabela);
-In my controller:
String tabela = ("M00"+(String.valueOf(Math.round(funcionario.getEmpresa().getCodigo())))+anoInicio+mesAtual);
if (eventoEspelhoPontoRepository.verificarTabela(tabela) > 1) {
registros.addAll(eventoEspelhoPontoRepository.findAllRegistrosByFuncionarioTableUnica(
tabela, dataInicioString, dataFimString, funcionario.getCracha()));
}
EDIT1 - what i'm trying to do here, is select a row of tables, but sometimes some of the tables doesn't exist, so i'm trying to do a verification if the table exists, and if it does, it should execute the Select * from that table, otherwise, should ignore. This is the only way i found to do it, if anyone has a better way please help me.
Btw, this is my select mentioned above, I tried to verify the existance of the table with the clause IF EXISTS but it doest work, I keep getting the error COULD NOT EXTRACT RESULT SET on my main program.
ALTER PROCEDURE [dbo].[usp_listarRegistrosMov]
--PARĂ‚METROS
#NomeTabela VARCHAR(20),
#DataInicial VARCHAR(20),
#DataFinal VARCHAR(20),
#Cracha FLOAT
AS
IF EXISTS(SELECT name FROM sysobjects WHERE name = #NomeTabela AND xtype = 'U')
BEGIN
Declare #Comando Varchar(1000)
Set #Comando = 'SELECT * FROM ' + #NomeTabela + ' WHERE mov_data BETWEEN ''' + #DataInicial + ''' AND ''' + #DataFinal + ''' AND mov_cracha = ' + CAST(#Cracha AS VARCHAR(50))
Exec(#Comando)
END
GO
EDIT 2: I tried using OBJECT_ID in the same sp also:
IF OBJECT_ID(#NomeTabela) IS NOT NULL
But always get the error:
2019-04-01 11:18:03.147 WARN 7068 --- [nio-8080-exec-8] o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 0, SQLState: null
2019-04-01 11:18:03.148 ERROR 7068 --- [nio-8080-exec-8] o.h.engine.jdbc.spi.SqlExceptionHelper : The statement did not return a result set.
I would do something like this:
ALTER PROCEDURE dbo.usp_verificarTabelaCadMov
(
#NomeTabela VARCHAR(20)
)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Comando NVARCHAR(1000);
DECLARE #Resultado INT;
SET #Resultado = -1
-- Or set to NULL depending on how you would like to handle table existence in the application code;
--SET #Resultado = NULL
IF OBJECT_ID(QUOTENAME(#NomeTabela), 'U') IS NOT NULL
BEGIN
SET #Comando = N'SELECT #Resultado = COUNT(*) FROM ' + QUOTENAME(#NomeTabela);
EXEC sys.sp_executesql
#Comando
, N'#Resultado INT OUTPUT'
, #Resultado OUTPUT;
END;
SELECT #Resultado AS resultado;
END;
So depending on your choice how to handle table existence, calling
EXEC dbo.usp_verificarTabelaCadMov #NomeTabela = 'thistabledoesNOTexist';
would return -1 or NULL (see stored proc comment) and
EXEC dbo.usp_verificarTabelaCadMov #NomeTabela = 'thistableDOESexist';
would return a value > -1.
Fixed it, I had to:
1 - Change my stored procedure to this:
ALTER PROCEDURE dbo.usp_verificarTabelaCadMov
#NomeTabela VARCHAR(20)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Exists INT
IF EXISTS(SELECT name
FROM sysobjects
WHERE name = #NomeTabela)
BEGIN
SET #Exists = 1
END
ELSE
BEGIN
SET #Exists = 0
END
RETURN #Exists
END
2 - Change my call on Repository to this:
#Query(value = "Declare #Exists int "
+ "Exec #Exists = usp_verificarTabelaCadMov :tabela"
+ " Select #Exists", nativeQuery = true)
RESULT: it's checking whether the table exists or not.

creating a trigger on a dynamically added table inside a procedure

I'am creating dynamic tables from java. What I want is that I want to create a trigger on every new table added which will just use the sequence to populate the primary key(serial_no) which is common in every table.How to achieve this ???
EDIT:
I have tried this code but I'am getting a message "procedure created with compilation errors"
create or replace procedure "TRIGGER_CALL" (trigger_name IN VARCHAR2, table_name IN VARCHAR2, sno IN NUMBER) as begin CREATE SEQUENCE abc MINVALUE 1 MAXVALUE 10000 INCREMENT BY 1 START WITH 141 CACHE 20 NOORDER NOCYCLE; CREATE OR REPLACE TRIGGER trigger_name before insert on table_name for each row begin select s_no.nextval into :new.sno from dual; end; end;
EDIT2:
My code
CREATE OR REPLACE
PROCEDURE "TRIGGER_CALL" (p_table_name IN VARCHAR2)
AUTHID CURRENT_USER
AS
l_sql VARCHAR2(4000);
l_dummy NUMBER;
l_trigger_name VARCHAR2(30);
l_seq_name VARCHAR2(30);
BEGIN
--SELECT '1'
--INTO l_dummy
--FROM all_tables
-- WHERE table_name = UPPER(p_table_name);
l_trigger_name := p_table_name || '_trg';
l_seq_name := p_table_name || 's_no';
EXECUTE IMMEDIATE 'CREATE SEQUENCE l_seq_name start with 1 increment by 1 ';
l_sql :=
'CREATE OR replace TRIGGER ' || l_trigger_name ||
' BEFORE INSERT ON ' || p_table_name ||
' FOR EACH ROW
BEGIN
SELECT l_seq_name.NEXTVAL
INTO :new.sno
FROM dual;
END;';
EXECUTE IMMEDIATE l_sql;
END;
/
Please check following code:
CREATE SEQUENCE my_sequence;
/
CREATE OR REPLACE
PROCEDURE "TRIGGER_CALL" (p_table_name IN VARCHAR2)
AUTHID CURRENT_USER
AS
l_sql VARCHAR2(4000);
l_dummy NUMBER;
l_trigger_name VARCHAR2(30);
BEGIN
-- Validate if a p_table_name is a valid object name
-- If you have access you can also use DBMS_ASSERT.SQL_OBJECT_NAME procedure
SELECT '1'
INTO l_dummy
FROM all_tables
WHERE table_name = UPPER(p_table_name);
l_trigger_name := p_table_name || '_trg';
l_sql :=
'CREATE OR replace TRIGGER ' || l_trigger_name ||
' BEFORE INSERT ON ' || p_table_name ||
' FOR EACH ROW
BEGIN
SELECT my_sequence.NEXTVAL
INTO :new.sno
FROM dual;
END;';
EXECUTE IMMEDIATE l_sql;
END;
/
CREATE TABLE my_test(sno NUMBER);
/
BEGIN
trigger_call('my_test');
END;
/
Important notes:
Usage of AUTHID CURRENT_USER eliminates the "insufficient privileges" problem. For reference see: Execute Immediate within a stored procedure keeps giving insufficient priviliges error
Because the dynamic sql simply concatenates the input parameter it needs to be validated to protect against SQL Injection. See also DBMS_ASSERT.
Because of point 2. I used table name to build trigger name.

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