I have a begin end block in SQL and I did something like this to call it from Java, but when I check if it executes correctly it gives me an error like this :
Missing IN or OUT parameter at index:: 1 Error Code: 17041
My code is this :
public void setDate(){
String startDate = null, endDate = null;
Query query = manager.createNativeQuery("Declare "
+ "dStartDate date := ADD_MONTHS( sysdate, - 60);"
+ "begin "
+ "schema.table.SetDateLimits( dStartDate, ADD_MONTHS( sysdate, - 1));"
+ ":END := To_Char(SYSDATE,'yyyy/mm');"
+ ":START := To_Char(dStartDate,'yyyy/mm');" + "end;");
Object v = query.getSingleResult();
System.out.println("The limits are " + startDate+ " " +endDate);
}
Does anybody know why? Thanks in advance!
Related
This is my function:
query = "CREATE FUNCTION CheckSex(personID INT, G CHAR) " +
"RETURNS BIT " +
"BEGIN " +
"DECLARE Flag BIT; " +
"SET Flag = 1; " +
"If (G NOT IN (SELECT Sex FROM PERSONS WHERE ID = personID)) " +
"THEN SET Flag = 0; " +
"RETURN Flag; " +
"END";
pState = conn.prepareStatement(query);
pState.executeUpdate();
This is the error code:
check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
I have tried putting it into the mysql command line manually and I get an error after DECLARE Flag BIT;, also I have tried to change the delimiter which gave an error.
I have switched to an online compiler for now and this function works fine in MySql 2014 express written as follows
CREATE FUNCTION CheckSex(#personID AS INT, #G as CHAR)
RETURNS BIT
AS
BEGIN
DECLARE #Flag BIT = 1
If (#G NOT IN (SELECT Sex FROM PERSONS WHERE ID = #personID))
SET #Flag = 0
RETURN #FLAG
END;
Thank you for any feedback.
I am struggling with checking if a table exist in the DB. What I have done so far is as follows:
public boolean isTableExist(String tableName) {
JdbcTemplate jdbc = getJdbcTemplate();
String query =
"IF (OBJECT_ID(?) IS NOT NULL ) "
+ "BEGIN "
+ " PRINT 1 "
+ " RETURN "
+ "END "
+ "ELSE "
+ "BEGIN "
+ " PRINT 0 "
+ " RETURN "
+ "END";
Integer result = jdbc.queryForObject(query, Integer.class, tableName);
return result == 1 ? true : false;
}
Output (Error):
PreparedStatementCallback; uncategorized SQLException for SQL [IF
(OBJECT_ID(?) IS NOT NULL ) BEGIN PRINT 1 RETURN END ELSE BEGIN
PRINT 0 RETURN END]; SQL state [null]; error code [0]; The statement
did not return a result set.; nested exception is
com.microsoft.sqlserver.jdbc.SQLServerException: The statement did not
return a result set.
You can also run a query like so:
select count(*)
from information_schema.tables
where table_name = 'yourtablename'
-- optionally this too
-- and table_schema = 'dbo';
If you get zero, table doesn't exist.
Based on jdbctemplate count queryForInt and pass multiple parameters answer, it seems like you might have to use something like this once you store the query
jdbc.queryForObject(
"select count(*) from information_schema.tables where table_name = ?"
, new Object[] { tableName }
, Integer.class
);
Update:
The problem has been resolved with the help of this post and the final solution based on the above info is:
String query =
"select count(*) "
+ "from information_schema.tables "
+ "where table_name = ? and table_schema = 'dbo'";
Integer result = jdbc.queryForObject(query, Integer.class, tableName);
Update
I've changed the first method to return a List, but I get the same exception.
I have 2 native queries in my Repository class. One is typed to return all records, the other returns just one row. See below:
#Query(nativeQuery = true, value = NATIVE_SUMMARY_QUERY_PARTIAL + "group by (rjd.refresh_job_identifier)) as rc")
List<RefreshSummary> getRefreshJobDetailSummary();
#Query(nativeQuery = true, value = NATIVE_SUMMARY_QUERY_PARTIAL + " WHERE rjd.refresh_job_identifier = :refreshJobId" +
" group by (rjd.refresh_job_identifier)) as rc")
List<RefreshSummary> getRefreshJobDetailSummaryById(#Param("refreshJobId") String refreshJobId);
interface RefreshSummary {
String getRefreshJobId();
Date getRefreshJobStart();
Date getRefreshJobComplete();
String getUserId();
long getTotalRecords();
long getSuccessfulRecords();
long getPendingRecords();
long getErrorRecords();
long getCancelledRecords();
String getRefreshJobStatus();
}
String NATIVE_SUMMARY_QUERY_PARTIAL = "SELECT rc.refresh_job_identifier as refresh_job_id, ..."
The first method, getRefreshJobDetailSummary, works fine. But the second method, where I want only one row, gives me this exception:
org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.lang.String] to type [com.company.repository.RefreshJobDetailRepository$RefreshSummary]
The full query looks like this:
String NATIVE_SUMMARY_QUERY_PARTIAL = "SELECT rc.refresh_job_identifier as refresh_job_id, " +
"rc.refresh_job_start_time as refresh_job_start, " +
"rc.record_completion_time as refresh_job_complete, " +
"rc.user_id as user_id, " +
"rc.pending + rc.successful + rc.cancelled + rc.error as total_records, " +
"rc.successful as successful_records, " +
"rc.pending as pending_records, " +
"rc.error as error_records, " +
"rc.cancelled as cancelled_records, " +
"CASE WHEN pending > 0 THEN 'In progress' " +
"ELSE 'Complete' " +
"END as refresh_job_status " +
"FROM " +
"(SELECT rjd.refresh_job_identifier as refresh_job_identifier, " +
"MAX(rjd.refresh_job_start_time) as refresh_job_start_time, " +
"MAX(rjd.record_completion_time) as record_completion_time, " +
"MAX(rjd.org_usr_nu) as user_id, " +
"SUM(CASE WHEN LOWER(record_status) = 'pending' THEN 1 ELSE 0 END) as pending, " +
"SUM(CASE WHEN LOWER(record_status) = 'successful' THEN 1 ELSE 0 END) as successful, " +
"SUM(CASE WHEN LOWER(record_status) = 'cancelled' THEN 1 ELSE 0 END) as cancelled, " +
"SUM(CASE WHEN LOWER(record_status) = 'error' THEN 1 ELSE 0 END) as error " +
"from erd_cfg_owner.refresh_job_detail rjd " ;
And the value the query returns looks like this:
'{20191218204913458hc35, 2019-12-18 20:49:13.314, 2019-12-18 20:49:24.335, hc35, 1, 1, 0, 0, 0, Complete}'
Can someone shed any light on this? Why would one method work but not the other?
I would replace the return type of your 2nd method from RefreshSummary to List<RefreshSummary>. In theory your method is supposed to return a list not a single value
Could you try using constructor expression in query declaration or by creating custom converter.
Eg-SELECT NEW com.example.MyClass(e.attribute1, e.attribute2...) FROM MyEntity e");
I wrote a SQL query which updates the record, in most cases it runs fine, but from yesterday it fails to update the row.I am currently working on Spring MVC based Web application, in which I need to perform the DML operation by calling update()method.
I am using JDBC template and in my update method i wrote this query.
It fetches the 947 records for January month 2018 and I already checked all records are unique.
I am here stuck, i am not able to find the duplication of record.I thought this exception occurred because of multiple record, but I think i am wrong, there is something which i am not able to identify.
Here is the query:
UPDATE SALARY_DETAIL_REPORT_012018 sd
SET sd.EMP_ID =
(SELECT e.emp_id from EMPLOYEE e
WHERE e.VERIFY_STATUS = 1
AND e.RELIEF_TYPE IS NULL
AND e.emp_code = to_char(sd.emp_code)
AND e.EMP_TYPE_ID!=03)
WHERE EXISTS
(SELECT e.emp_id from EMPLOYEE e
WHERE e.VERIFY_STATUS = 1
AND e.emp_code = to_char(sd.emp_code)
AND e.EMP_TYPE_ID!=03 AND e.RELIEF_TYPE IS NULL)
AND sd.EMP_ID IS NULL
AND sd.REFERENCE_ID LIKE '203-%'
and HERE is Java Code in my DAOImpl class
public void update(String tableSuffix, String regionId, String circleId) {
String tabName = "SALARY_DETAIL_REPORT_" + tableSuffix;
String q = "UPDATE " + tabName + " sd"
+ " SET sd.EMP_ID = (SELECT e.emp_id "
+ " from EMPLOYEE e WHERE e.VERIFY_STATUS = 1 AND e.RELIEF_TYPE IS NULL "
+ " AND e.emp_code = to_char(sd.emp_code) AND e.EMP_TYPE_ID!=03) "
+ " WHERE "
+ " EXISTS (SELECT e.emp_id from EMPLOYEE e WHERE e.VERIFY_STATUS = 1 "
+ " AND e.emp_code = to_char(sd.emp_code) AND e.EMP_TYPE_ID!=03 AND e.RELIEF_TYPE IS NULL) "
+ " AND sd.EMP_ID IS NULL";
if (circleId != null && !circleId.trim().equals("")) {
q += " AND sd.REFERENCE_ID LIKE '" + circleId + "-%' ";
} else {
q += " AND sd.REFERENCE_ID LIKE '" + regionId + "-%' ";
}
// System.out.println("q " + q);
MapSqlParameterSource param = new MapSqlParameterSource();
getNamedParameterJdbcTemplate().update(q, param);
}
Please suggest me the best solution
You need to find the rows that prevent your query from running.
Run this query:
SELECT sd.emp_code, COUNT(*) as cnt
FROM EMPLOYEE e
WHERE e.VERIFY_STATUS = 1 AND
e.RELIEF_TYPE IS NULL AND
e.emp_code = to_char(sd.emp_code) AND
e.EMP_TYPE_ID <> 03
GROUP BY sd.emp_code
HAVING COUNT(*) > 1;
This has the candidate problems. What can you do? The simplest thing is one of the problems:
Change the SELECT to SELECT MAX(sd.emp_code)
Change the WHERE with AND rownum = 1
If i insert a quote symbol " in the codContract parameter I receive the following error.
Error querying database. Cause: java.sql.SQLSyntaxErrorException:
ORA-00972: identifier too long
The error may exist in mappers/existence.xml The error may involve
com.iv.queryinterface.AssistenzaMapper.getTitlesFromCodContratct-Inline
The error occurred while setting parameters
SQL:
SELECT t.id_title,
c.des_lastname,
c.des_firstname,
to_char(t.dta_raw, 'DD/MM/YYYY') AS DTA_RAW,
DECODE(t.cod_statustitle, '1', 'Raw', '2', 'Stated') AS STATUS_TITLE
FROM Ivf_Policy p,
Ivf_Title t,
Ivg_Client c,
Ivf_Price pr
WHERE Cod_Contract = TEST
AND p.id_policy = t.id_policy
AND t.cod_type_title IN(2, 3, 13)
AND t.cod_statustitle IN(1, 2)
AND t.cod_client = c.cod_client
AND t.id_price = pr.id_price;
Cause: java.sql.SQLSyntaxErrorException: ORA-00972: identifier too
long
In this example, i set " TEST as value for the codContract parameter. My questions are:
Is this an exploitable SQL injection or a false positive that just prints an sql error into the stack trace?
The code is susceptible to SQL injection, and does no escaping. All that is avoidable by the use of PreparedStatement. Where the query string is not composed dynamically.
Now "TEST is the first part of an SQL identifier till a closing double quote.
I do not want to instruct readers on hacking, but think what something like
"'' OR 1=1 "
+ "UNION SELECT u.login, u.password, '', '', '', '' "
+ "FROM users"
+ "\u0000-- ";
might reveal on data.
Use java.sql.PreparedStatement for avoiding SQL injection.
String query =
"SELECT " +
" t.id_title , " +
" c.des_lastname , " +
" c.des_firstname , " +
" TO_CHAR(t.dta_raw, 'DD/MM/YYYY') AS DTA_RAW, " +
" DECODE(t.cod_statustitle, '1', 'Raw', '2', 'Stated') AS STATUS_TITLE " +
"FROM " +
" Ivf_Policy p, " +
" Ivf_Title t, " +
" Ivg_Client c, " +
" Ivf_Price pr " +
"WHERE " +
"1 = 1 AND " +
" Cod_Contract = ? " +
"AND p.id_policy = t.id_policy " +
"AND t.cod_type_title IN(2, " +
" 3, " +
" 13) " +
"AND t.cod_statustitle IN(1, " +
" 2) " +
"AND t.cod_client = c.cod_client " +
"AND t.id_price = pr.id_price;";
PreparedStatement stmt = connection.prepareStatement(query);
stmt.setString(1, 'TEST');
ResultSet rs = stmt.executeQuery();
To avoid SQL injection, do not append parameter values directly to SQL queries.
Use bind variables instead.
Thanks.