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.
Related
I can't select inner join data from MYSQL in Java.
I'm using this code in Java:
Class.forName("com.mysql.jdbc.Driver");
Connection conexao = DriverManager.getConnection("jdbc:mysql://localhost:3306/despesas?useSSL=true", "root", "local");
Statement comando = conexao.createStatement();
String sqlInsert;
ResultSet rsTDP;
sqlInsert = "select id_historico, tipos_de_despesas.descricao, dt_desp, valor_despesa from tipos_de_despesas INNER JOIN historico_despesas ON tipos_de_despesas.id_despesa=historico_despesas.id_despesa ORDER BY dt_desp desc";
rsTDP = comando.executeQuery(sqlInsert);
while(rsTDP.next()){
System.out.println("ID da Despesa: " + rsTDP.getString("id_despesa") + " | Descrição: " + rsTDP.getString("descricao"));
}
This sintax works in MYSQL Workbench but in Java does not.
SELECT id_historico, tipos_de_despesas.descricao, dt_desp, valor_despesa from tipos_de_despesas INNER JOIN historico_despesas ON tipos_de_despesas.id_despesa=historico_despesas.id_despesa ORDER BY dt_desp desc
This is result in Workbench
Can anyone help me?
I'll bet the exception is actually coming from this line:
System.out.println("ID da Despesa: " + rsTDP.getString("id_despesa") + " | Descrição: " + rsTDP.getString("descricao"));
I don't see the id_despesa column in the select statement and the ResultSet can only read columns from the select statement. So the rsTDP.getString("id_despesa") will throw a SQLException.
If you don't need the id_despesa column, then you can just leave it out of the println. Otherwise, you can change your SQL to this:
sqlInsert = "select tipos_de_despesas.id_despesa, id_historico, tipos_de_despesas.descricao, dt_desp, valor_despesa from tipos_de_despesas INNER JOIN historico_despesas ON tipos_de_despesas.id_despesa=historico_despesas.id_despesa ORDER BY dt_desp desc";
With the column added to the query, then you will be able to get id_despesa out of the results.
this is what i got
com.mysql.jdbc.exceptions.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that
corresponds to your MySQl server version for the right syntax to use near 'order by idconsumo' at line 1
java.lang.IllegalArgumentException: Cannot set a null TableModel
code
sSQL = "select c.idconsumo,c.idreserva,c.idproducto,p.nombre,c.cantidad,c.precio_venta "
+ ",c.estado from consumo c inner join producto p on c.idproducto=p.idproducto"
+ " where c.idreserva = " + buscar +" order by idconsumo";
but still save it in the database. If i exit the app and open it again then the
record is added
First of all as Jon suggested, use the parametrized SQL.
You need to make few changes to the SQL as below:
"select c.idconsumo, c.idreserva, c.idproducto, p.nombre, c.cantidad, c.precio_venta, c.estado from consumo c inner join producto p on c.idproducto=p.idproducto where c.idreserva = " + buscar +" order by c.idconsumo";
Make sure if buscar is a variable and c.idreserva is non-int column then add single quotes around it like c.idreserva = '" + buscar +"' and order by c.idconsumo
Using prepared statement:
String sql = "select c.idconsumo, c.idreserva, c.idproducto, p.nombre, c.cantidad, c.precio_venta, c.estado from consumo c inner join producto p on c.idproducto=p.idproducto where c.idreserva = ? order by c.idconsumo";
PreparedStatement prepStmt = conn.prepareStatement(sql);
//if buscar is string type
prepStmt.setString(1, buscar);
ResultSet rs = prepStmt.executeQuery();
Query syntax error. Please check:
String sql = " select c.idconsumo,c.idreserva,c.idproducto,p.nombre,"
+" c.cantidad,c.precio_venta, c.estado "
+" from consumo c inner join producto p on "
+" c.idproducto=p.idproducto "
+" where c.idreserva ='" + buscar +"' order by c.idconsumo ";
PreparedStatement would be more accurate to use.
A PreparedStatement is a special kind of Statement object with some useful features. Remember, you need a Statement in order to execute either a query or an update. You can use a PreparedStatement instead of a Statement and benefit from the features of the PreparedStatement.
The PreparedStatement's primary features are:
Easy to insert parameters into the SQL statement. Easy to reuse the
PreparedStatement with new parameters. May increase performance of
executed statements. Enables easier batch updates.
String sql = " select c.idconsumo,c.idreserva,c.idproducto,p.nombre,"
+" c.cantidad,c.precio_venta, c.estado "
+" from consumo c inner join producto p on "
+" c.idproducto=p.idproducto "
+" where c.idreserva = ? order by c.idconsumo ";
PreparedStatement preStmt = conn.prepareStatement(sql);
preStmt.setInt(1, buscar);
ResultSet rs = preStmt.executeQuery();
I try to create a PreparedStatement:
stmt = conn.prepareStatement("SELECT POLBRP, POLTYP, POLNOP, INCPTP, TRMTHP, " +
"CLTKYP , CANDTP, POLSTP, EXPRYP, OINCPP, CANRNP, PAYMDP,
KCNFLP, KCRTSP, KACADP, KSCHMP, EXPRYP FROM "
+ POLHDR + " WHERE POLNOP = " + idNumber +
" AND POLBRP = " + branch + " AND POLTYP = " + product +
" AND OINCPP <= "+date );
And this throws an SQLException: [SQL0206] Column AD not in specified tables.
I have no idea where it's getting column AD from as I never specified it in the select clause (unless I'm being completely blind and stupid)
Can anyone help?
If your variables are strings, e.g. branch
" AND POLBRP = " + branch + " ...
then you forgot to quote the values
" AND POLBRP = '" + branch + "' ...
but the real solution is using placeholders
... AND POLBRP = ? ...
which would prevent such problems once and for all, this is what PreparedStatement is designed for
Try to change your query into this:
SELECT
POLBRP,
POLTYP,
POLNOP,
INCPTP,
TRMTHP,
CLTKYP,
CANDTP,
POLSTP,
EXPRYP,
OINCPP,
CANRNP,
PAYMDP,
KCNFLP,
KCRTSP,
KACADP,
KSCHMP,
EXPRYP
FROM TableName WHERE POLNOP = ? AND POLBRP = ? AND POLTYP = ? AND OINCPP <= ?";
Then use:
stmt.setString(1, "ValueOfPOLNOP");
...
When your query is being executed ? will be replaced with the value you passed into PreparedStatement#setString(int, String) method
Preventing SQL Injection in Java shows the proper use of PreparedStatement:
Prepared Statements Variables passed as arguments to prepared
statements will automatically be escaped by the JDBC driver.
Example: ps.1
String selectStatement = "SELECT * FROM User WHERE userId = ? ";
PreparedStatement prepStmt = con.prepareStatement(selectStatement);
prepStmt.setString(1, userId);
ResultSet rs = prepStmt.executeQuery();
From the same source, following in the same section:
Although Prepared Statements helps in defending against SQL Injection,
there are possibilities of SQL Injection attacks through inappropriate
usage of Prepared Statements. The example below explains such a
scenario where the input variables are passed directly into the
Prepared Statement and thereby paving way for SQL Injection attacks.
Example: ps.2
String strUserName = request.getParameter("Txt_UserName");
PreparedStatement prepStmt = con.prepareStatement("SELECT * FROM user WHERE userId = '+strUserName+'");
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.
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.