JDBC error with PreparedStatement - java

I'm trying to write a small function that gets an id u (integer), and returns the number of friends u have with distance <=3 (the friends information is stored in the table Likes: Likes(uid1, uid2) means: uid1 likes uid2).
I wrote this simple query:
String likesDistance =
"SELECT uid2 " + //DISTANCE = 1
"FROM Likes " +
"WHERE uid1 = ? " +
"UNION " +
"SELECT L2.uid2 " + //DISTANCE = 2
"FROM Likes L1, Likes L2 " +
"WHERE L1.uid1 = ? and L1.uid2 = L2.uid1 " +
"UNION "+
"SELECT L3.uid2 " + //DISTANCE = 3
"FROM Likes L1, Likes L2 , Likes L3 " +
"WHERE L1.uid1 = ? and L1.uid2 = L2.uid1 and L2.uid2 = L3.uid1 ";
Then, I do the following:
PreparedStatement pstmt2 = con.prepareStatement(likesDistance);
pstmt1.setInt(1, u);
pstmt1.setInt(2, u);
System.out.println("2");
pstmt1.setInt(3, u);
System.out.println("3");
pstmt1.setInt(4, u);
pstmt1.setInt(5, u);
Where u, as mention before, is an integer passed to the function.
All this code is within a 'try' block. When I try to run it, it prints the first printout ("2"), but not the second one ("3"), and I get the following exception message:
The column index is out of range: 3, number of columns: 2.
Why is it like this, and how can I change it to work as I want?
Thanks a lot.

Copy and paste? Guess you wanted to set parameters for statement 2.

Your prepared statement is pstmt2.
You are setting properties on pstmt1.
Try setting the properties on pstmt2 and it should work.

Though you set properties on pstmt2 you get exception as there are only three placeholders in the statement and you are setting for five placeholders.

Related

Bad SQL grammar -The column name was not found in this ResultSet?

Hello I am using a JDBC query and I am having this error but I don't understand why, or what exactly is the meaning of this error and what is wrong with the query.
The query is as below
private List<StatisticsLog> runStatistics(Integer partnerId, LocalDate ldStart, LocalDateTime ldtEnd, String statType)
{
return jdbcTemplate.query("SELECT S.APP_ID, S.LOG_TYPE, ACC.CONTACT_PERSON_FIRST_NAME, ACC.CONTACT_PERSON_LAST_NAME, ACV.VERSION_APP_NAME, "
+ "'" + statType.trim() + "' STATTYPE, "
+ "ACV.APP_CATALOG_ID, ACV.APP_CATALOG_VERSION_ID, ACV.VERSION, ACV.UPDATED_AT, ACV.VERSION_LOGO_EXT, ACV.HAS_LOGO, "
+ "LANG.LANGUAGE_NAME_SHORT, LANG.LANGUAGE_ID , S.count, S.PARTNER_ID, APP.CREATED_AT "
+ "FROM (SELECT partner_id, log_type, app_id, language_id, count(*) as count FROM public.statistics_log "
+ " WHERE partner_id = ? "
+ " and logged_at between ? and ? "
+ "group by 1, log_type, app_id, language_id) as S "
+ "INNER JOIN APP_CATALOG_ACCOUNT ACP ON ACP.APP_CATALOG_SERIAL_ID = S.APP_ID "
+ "INNER JOIN APP_CATALOG APP ON APP.APP_CATALOG_SERIAL_ID = S.APP_ID "
+ "INNER JOIN ACCOUNT ACC ON ACC.ACCOUNT_ID = S.PARTNER_ID "
+ "INNER JOIN APP_CATALOG_VERSION ACV on ACV.APP_CATALOG_SERIAL_ID = APP.APP_CATALOG_SERIAL_ID AND ACV.STATUS = 3 "
+ "INNER JOIN LANGUAGE LANG ON LANG.LANGUAGE_ID = ACV.LANGUAGE_ID "
+ "ORDER BY S.count desc ",
new Object[] { partnerId, ldStart, ldtEnd }, new StatisticsLogRowMapper());
}
and I am getting the error from this column CREATED_AT that is part of the app catalog, and I think it should be there, also for more detailed also I will attach StatisticsLogRowMapper
public class StatisticsLogRowMapper implements RowMapper<StatisticsLog>
{
#Override
public StatisticsLog mapRow(ResultSet rs, int rowNum) throws SQLException
{
StatisticsLog stat = new StatisticsLog();
stat.setAppId(rs.getInt("APP_ID"));
stat.setPartnerId(rs.getInt("PARTNER_ID"));
stat.setCount(rs.getLong("COUNT"));
stat.setCreatedAt(rs.getTimestamp("CREATED_AT").toLocalDateTime());
stat.setPartnerFirstName(rs.getString("CONTACT_PERSON_FIRST_NAME"));
stat.setPartnerLastName(rs.getString("CONTACT_PERSON_LAST_NAME"));
stat.setAppNameDefault(rs.getString("VERSION_APP_NAME"));
stat.setAppCatalogId(rs.getInt("APP_CATALOG_ID"));
stat.setStatType(rs.getString("STATTYPE"));
stat.setLogType(LogTypeEnum.valueOf(rs.getString("LOG_TYPE").trim()));
stat.setAppCatalogVersionId(rs.getInt("APP_CATALOG_VERSION_ID"));
stat.setVersion(rs.getInt("VERSION"));
stat.setUpdatedAt(rs.getDate("UPDATED_AT"));
stat.setVersionLogoExt(rs.getString("VERSION_LOGO_EXT"));
stat.setHasLogo(rs.getBoolean("HAS_LOGO"));
stat.setLanguageNameShort(rs.getString("LANGUAGE_NAME_SHORT"));
stat.setLanguageId(rs.getInt("LANGUAGE_ID"));
return stat;
}
}
THE ERROR IS: "PreparedStatementCallback; bad SQL grammar [SELECT S.APP_ID, S.LOG_TYPE, ACC.CONTACT_PERSON_FIRST_NAME, ACC.CONTACT_PERSON_LAST_NAME, ACV.VERSION_APP_NAME, 'days30' STATTYPE, ACV.APP_CATALOG_ID, ACV.APP_CATALOG_VERSION_ID, ACV.VERSION, ACV.UPDATED_AT, ACV.VERSION_LOGO_EXT, ACV.HAS_LOGO, LANG.LANGUAGE_NAME_SHORT, S.count, S.PARTNER_ID FROM (SELECT partner_id, log_type, app_id, language_id, count(*) as count FROM public.statistics_log WHERE logged_at between ? and ? group by 1, log_type, app_id, language_id, partner_id) as S INNER JOIN APP_CATALOG_ACCOUNT ACP ON ACP.APP_CATALOG_SERIAL_ID = S.APP_ID INNER JOIN APP_CATALOG APP ON APP.APP_CATALOG_SERIAL_ID = S.APP_ID INNER JOIN ACCOUNT ACC ON ACC.ACCOUNT_ID = S.PARTNER_ID INNER JOIN APP_CATALOG_VERSION ACV on ACV.APP_CATALOG_SERIAL_ID = APP.APP_CATALOG_SERIAL_ID AND ACV.STATUS = 3 INNER JOIN LANGUAGE LANG ON LANG.LANGUAGE_ID = ACV.LANGUAGE_ID ORDER BY S.count desc ]; nested exception is org.postgresql.util.PSQLException: The column name CREATED_AT was not found in this ResultSet."
IN THE ERROR SEEMS THIS FIELD ISN'T THERE SOMEHOW
If you have any idea what may be wrong or thing I can try please don't hesitate to comment, I would appreciate d even the smallest help thank you.
I can see there is an error in line 2 of the query - + "'" + statType.trim() + "' STATTYPE, ", right after the quote. STATTYPE does not have a table reference and is appended with a string. That could be another issue. I cannot comment on the question as I dont have enough reputation.

Single Row Sub query return more than one row

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

How to put a sum in a String and print it

I'm currently working on a receipt of an Java application and I can't seem to get the sum on the screen. When is use the following query I get the sum in PHPMyAdmin but can't seem to find it in Java. I just can't print it because Java tells me all the column names I try are wrong. Does anyone know how to fix this?
If you want more code than this I can provide that but I'm kinda sure there is something faulty in the query and Java can't read it out. Help will be appreciated.
String sql = "SELECT sum((`barorder_drink`.`quantity` * `drink`.`price`)) + sum((`kitchenorder_dish`.`quantity` * `dish`.`price`))"
+ "FROM `barorder`, `barorder_drink`, `drink`, `kitchenorder`, `kitchenorder_dish`, `dish`, `restaurantorder`"
+ "WHERE `barorder`.`restaurantOrderId` = `restaurantorder`.`id`"
+ "AND `kitchenorder`.`restaurantOrderId` = `restaurantorder`.`id`"
+ "AND `barorder_drink`.`barorderId` = `barorder`.`id`"
+ "AND `barorder_drink`.`drinkId` = `drink`.`id`"
+ "AND `kitchenorder_dish`.`kitchenOrderId` = `kitchenorder`.`id`"
+ "AND `kitchenorder_dish`.`dishId` = `dish`.`id`"
+ "AND `restaurantorder`.`id` = '" + ID + "' ;";
Put your sum as a val and get this value like this
String sql = "SELECT sum(myattributes) AS val";
and when you want to get the result
int som = getInt("val");
Maybe when you do ))"
+ "FROM ...
The result is: ))FROM
and it sould be )) FROM

Launching two query via java code

I want to execute two queries in my PostgreSQL database via code java.
The first one create a temporary view and the second one get some data from this view.
This is my code:
String sql = "create or replace temp view recap as "
+ "select id_salarie, concat(nom, ' ', prenom) as np, hour_salary, id_chantier, id_activity, SUM(nb_heures) as s_hn, SUM(nb_heures_s) as s_hs, value_update, (hour_salary*SUM(nb_heures)) as cost_hn, ((hour_salary*value_update)*SUM(nb_heures_s)) as cost_hs "
+ "from pointage_full pf, salarie s, hs_increase hsi "
+ "where s.id = pf.id_salarie "
+ "and hsi.etat = 1 "
+ "and id_chantier = "+this.idProject+" and id_salarie <> id_chef "
+ "group by id_salarie, np, hour_salary, id_activity, id_chantier, value_update "
+ "order by id_salarie DESC;"
+ ""//=================execute the second query to get costs from created view===========================
+ "select id_activity, sum(cost_hn) as sm_cost_hn, sum(cost_hs) as sm_cost_hs, (sum(cost_hn)+sum(cost_hs)) as cost_activity "
+ "from recap "
+ "group by id_activity "
+ "order by id_activity asc;";
ResultSet res = state.executeQuery(sql);
while (res.next()) {
//---doing my stuff...
}
But I get this error:
org.postgresql.util.PSQLException: No results returned by the query.
You cannot execute more than one statement with a single executeXXX() call - especially not a DDL statement and a query.
But you don't need to create that (temporary) view in the first place. Also the order by inside the view is also useless as you are re-ordering the rows in the final statement again.
You can do what you want with one single statement:
select id_activity, sum(cost_hn) as sm_cost_hn, sum(cost_hs) as sm_cost_hs, (sum(cost_hn)+sum(cost_hs)) as cost_activity
from (
select id_salarie,
concat(nom, ' ', prenom) as np,
hour_salary,
id_chantier,
id_activity,
SUM(nb_heures) as s_hn,
SUM(nb_heures_s) as s_hs,
value_update,
(hour_salary*SUM(nb_heures)) as cost_hn,
((hour_salary*value_update)*SUM(nb_heures_s)) as cost_hs
from pointage_full pf, salarie s, hs_increase hsi
where s.id = pf.id_salarie
and hsi.etat = 1
and id_chantier = ?
and id_salarie <> id_chef
group by id_salarie, np, hour_salary, id_activity, id_chantier, value_update
) as recap
group by id_activity
order by id_activity asc;
You should also use a PreparedStatement instead of concatenating parameters into your SQL. If you have the above query in a String, you can do something like this:
PreparedStatement pstmt = connection.prepareStatement(QUERY);
pstmt.setInt(1, this.idProject);
ResultSet rs = pstmt.executeQuery();
while (rs.next()
{
// process result set
}
I'm pretty sure this will be faster than first creating a temp view and then querying that.

SQL Query Will Not Execute SQLite, Java

Problem Synopsis:
When attempting to execute a SQL query in Java with a SQLite Database, the SQL statement fails to return from the execute() or executeQuery() method. In other words, the system "hangs" when executing this SQL statement.
Question:
What am I doing wrong to explain why the ResultSet never "returns?"
TroubleShooting
I tried to narrow the problem and the problem seems to be with the Java execute() or executeQuery(). A ResultSet never seems to return. For example, I tried executing exactly the same query directly in SQLite (that is, using a SQLite DB manager). The query (outside Java) executes in about 5ms and returns the valid result set.
NOTE: No exception is thrown. The system merely seems to "hang" and becomes unresponsive until a manual kill. (waiting more than 10 minutes.)
Code:
I heavily edited this code to make the problem simpler to see. (In production, this uses Prepared Statements. But, the error occurs in both methods--straight Statement and prepared Statement versions.)
Basically, the SELECT returns a single DB item so the user can review that item.
Statement st = conn.createStatement() ;
ResultSet rs = st.executeQuery("SELECT DISTINCT d1.id, d1.sourcefullfilepath, " +
"d1.sourcefilepath, d1.sourcefilename, d1.classificationid, d1.classid, " +
"d1.userid FROM MatterDataset, (SELECT MatterDataset.id, " +
"MatterDataset.sourcefullfilepath, MatterDataset.sourcefilepath, " +
"MatterDataset.sourcefilename, MatterDataset.matterid , " +
"DocumentClassification.classificationid, DocumentClassification.classid," +
" DocumentClassification.userid FROM MatterDataset " +
"LEFT JOIN DocumentClassification ON " +
"DocumentClassification.documentid = Matterdataset.id " +
"WHERE ( DocumentClassification.classid = 1 OR " +
"DocumentClassification.classid = 2 ) AND " +
"DocumentClassification.userid < 0 AND " +
"MatterDataset.matterid = \'100\' ) AS d1 " +
"LEFT JOIN PrivilegeLog ON " +
"d1.id = PrivilegeLog.documentparentid AND " +
"d1.matterid = PrivilegeLog.matterid " +
"WHERE PrivilegeLog.privilegelogitemid IS NULL " +
"AND MatterDataset.matterid = \'100\' " +
"ORDER BY d1.id LIMIT 1 ;") ;
Configuration:
Java 6,
JDBC Driver = Xerial sqlite-jdbc-3.7.2,
SQLite 3,
Windows
Update
Minor revision: as I continue to work with this, adding a MIN(d1.id) to the beginning of the SQL statement at least returns a ResultSet (rather than "hanging"). But, this is not really what I wanted as the MIN obviates the LIMIT function.
Statement st = conn.createStatement() ;
ResultSet rs = st.executeQuery("SELECT DISTINCT MIN(d1.id), d1.id,
d1.sourcefullfilepath, " +
"d1.sourcefilepath, d1.sourcefilename, d1.classificationid, d1.classid, " +
"d1.userid FROM MatterDataset, (SELECT MatterDataset.id, " +
"MatterDataset.sourcefullfilepath, MatterDataset.sourcefilepath, " +
"MatterDataset.sourcefilename, MatterDataset.matterid , " +
"DocumentClassification.classificationid, DocumentClassification.classid," +
" DocumentClassification.userid FROM MatterDataset " +
"LEFT JOIN DocumentClassification ON " +
"DocumentClassification.documentid = Matterdataset.id " +
"WHERE ( DocumentClassification.classid = 1 OR " +
"DocumentClassification.classid = 2 ) AND " +
"DocumentClassification.userid < 0 AND " +
"MatterDataset.matterid = \'100\' ) AS d1 " +
"LEFT JOIN PrivilegeLog ON " +
"d1.id = PrivilegeLog.documentparentid AND " +
"d1.matterid = PrivilegeLog.matterid " +
"WHERE PrivilegeLog.privilegelogitemid IS NULL " +
"AND MatterDataset.matterid = \'100\' " +
"ORDER BY d1.id LIMIT 1 ;") ;
What a messy SQL statement (sorry)! I don't know SQLite, but why not simplify to:
SELECT DISTINCT md.id, md.sourcefullfilepath, md.sourcefilepath, md.sourcefilename,
dc.classificationid, dc.classid, dc.userid
FROM MatterDataset md
LEFT JOIN DocumentClassification dc
ON dc.documentid = md.id
AND (dc.classid = 1 OR dc.classid = 2 )
AND dc.userid < 0
LEFT JOIN PrivilegeLog pl
ON md.id = pl.documentparentid
AND md.matterid = pl.matterid
WHERE pl.privilegelogitemid IS NULL
AND md.matterid = \'100\'
ORDER BY md.id LIMIT 1 ;
I was uncertain whether you wanted to LEFT JOIN or INNER JOIN to DocumentClassification (using LEFT JOIN and then put requirements on classid and userid in the WHERE statement is - in my opinion - contradictory). If DocumentClassification has to exist, then change to INNER JOIN and put the references to classid and userid into the WHERE clause, if DocumentClassification may or may not exist in your result set, then keep the query as I suggested above.
I went back and started over. The SQL syntax, while it worked outside Java, simply seemed too complex for the JDBC driver. This cleaned-up revision seems to work:
SELECT DISTINCT
MatterDataset.id, MatterDataset.sourcefullfilepath, MatterDataset.sourcefilepath,
MatterDataset.sourcefilename
FROM MatterDataset , DocumentClassification
ON DocumentClassification.documentid = MatterDataset.id
AND MatterDataset.matterid = DocumentClassification.matterid
LEFT JOIN PrivilegeLog ON MatterDataset.id = PrivilegeLog.documentparentid
AND MatterDataset.matterid = PrivilegeLog.matterid
WHERE PrivilegeLog.privilegelogitemid IS NULL
AND MatterDataset.matterid = '100'
AND (DocumentClassification.classid = 1 OR DocumentClassification.classid = 2)
AND DocumentClassification.userid = -99
ORDER BY MatterDataset.id LIMIT 1;
A nice lesson in: just because you can in SQL doesn't mean you should.
What this statement does is essentially locates items in the MatterDataset Table that are NOT in the PrivilegeLog table. The LEFT JOIN and IS NULL syntax locate the items that are "missing." That is, i want to find items that are in MatterDataset but not yet in PrivilegeLog and return those items.

Categories