I'm trying to join two tables but can't get the SQL right. My SQL statement is far more complex than the below SQL but the below SQL will do to show the principle. I get an invalid identifier exception when trying to refer to t or p. How come I cannot refer to these? I'm using Oracle DB.
SQL:
SELECT * FROM ((SELECT * FROM transactions t) FULL JOIN (SELECT * FROM payments p) ON (t.id = p.trans_id));
Exception:
Caused by: java.sql.SQLException: ORA-00904: "P"."TRANS_ID": invalid identifier
You are not really giving your querys an alias, you should do:
SELECT *
FROM (SELECT * FROM transactions) t
FULL JOIN (SELECT * FROM payments) p
ON (t.id = p.trans_id);
Of course, assuming that you are using real derived tables instead of those simple SELECTs, otherwise you should just use the tables directly.
The aliases are in the wrong place. The alias for a derived table should be just after the closing parenthesis:
SELECT *
FROM
(SELECT * FROM transactions) t
FULL JOIN
(SELECT * FROM payments) p
ON t.id = p.trans_id
Note that it makes no sense to use derived tables with such a simple query. I assume that you do actually need the derived tables and that you just simplified your query for the question.
Related
Is it possible to execute a SQL query in Java for which sub query result is already fetched
e.g. Suppose I have a query
SELECT A.NAME FROM (SELECT NAME, CLASS FROM ABC_TABLE) A WHERE A.CLASS = 1;
What I want is that if I execute the sub query separately i.e.,
SELECT NAME, CLASS FROM ABC_TABLE
and the result which I get from Result Set will get modified based on some Java calculations & then that modified result needs to be passed to the 1st main query.
Is it possible.
Note: The example given above is a sample. Actually sub query is very big of 300-400 lines & so is the main query
Use Alias to sort it out. Following is the query which I used and it is working:
Select * from (select * from
(select * from school.questionbank where class='class-II'
AND Subject='Physic') A
where chapter='chapter 1') B
where isMCQ=1;
Note that A and B are temporary tables created in the memory by SQL
I need delete from table on operation of same table .JPA query is
DELETE FROM com.model.ElectricityLedgerEntity a
Where a.elLedgerid IN
(SELECT P.elLedgerid FROM
(SELECT MAX(b.elLedgerid)
FROM com.model.ElectricityLedgerEntity b
WHERE b.accountId='24' and b.ledgerType='Electricity Ledger' and b.postType='ARREARS') P );
I got this error:
with root cause org.hibernate.hql.ast.QuerySyntaxException: unexpected
token: ( near line 1, column 109 [DELETE FROM
com.bcits.bfm.model.ElectricityLedgerEntity a Where a.elLedgerid IN (
SELECT P.elLedgerid FROM ( SELECT MAX(b.elLedgerid) FROM
com.bcits.ElectricityLedgerEntity b WHERE b.accountId='24'
and b.ledgerType='Electricity Ledger' and b.postType='ARREARS') P ) ]
at
org.hibernate.hql.ast.QuerySyntaxException.convert(QuerySyntaxException.java:54)
at
org.hibernate.hql.ast.QuerySyntaxException.convert(QuerySyntaxException.java:47)
at
org.hibernate.hql.ast.ErrorCounter.throwQueryException(ErrorCounter.java:82)
at
org.hibernate.hql.ast.QueryTranslatorImpl.parse(QueryTranslatorImpl.java:284)
Same query is running on mysql terminal ,but this is not working with jpa .Can any one tell me how i can write this query using jpa .
I don't understand why do you use Pbefore the last parenthesis...
The following code is not enough ?
DELETE FROM com.model.ElectricityLedgerEntity a
Where a.elLedgerid IN
(SELECT MAX(b.elLedgerid)
FROM com.model.ElectricityLedgerEntity b
WHERE b.accountId='24' and b.ledgerType='Electricity Ledger' and
b.postType='ARREARS')
Edit for bypassing mysql subquery limitations :
The new error java.sql.SQLException: You can't specify target table 'LEDGER' for update in FROM clause
is known in mysql when you use it with JPA. It's one MySQL limitation.
A recent stackoverflow question about it
In brief, you cannot "directly" updated/deleted a table that you query in a select clause
Now I understand why your original query did multiple subqueries seemingly not necessary (while it was useful for mysql) and had a "special" syntax.
I don't know tricks to solve this problem in JPA (I don't use the MySQL DBMS for a long time now).
At your place, I would do two queries. The first where you select the expected max elLedgerid and the second where you could delete line(s) with the id retrieved in the previous query.
You should not have performance issues if your sql model is well designed, the sql indexes well placed and the time to access to the database is correct.
You cannot do this in a single query with Hibernate. If you want to delete the max row(s) with Hibernate you will have to do so in two steps. First, you can find the max entry, then you can delete using that value in the WHERE clause.
But the query you wrote should actually run as a raw MySQL query. So why don't you try executing that query as a raw query:
String sql = "DELETE FROM com.model.ElectricityLedgerEntity a " +
"WHERE a.elLedgerid IN (SELECT P.elLedgerid FROM " +
"(SELECT MAX(b.elLedgerid) FROM com.model.ElectricityLedgerEntity b " +
"WHERE b.accountId = :account_id AND b.ledgerType = :ledger_type AND " +
" b.postType = :post_type) P );";
Query query = session.createSQLQuery(sql);
query.setParameter("account_id", "24");
query.setParameter("ledger_type", "Electricity Ledger");
query.setParameter("post_type", "ARREARS");
Just want to extend existing answer:
In brief, you cannot "directly" updated/deleted a table that you query in a select clause
This was lifted with starting from MariaDB 10.3.1:
Same Source and Target Table
Until MariaDB 10.3.1, deleting from a table with the same source and target was not possible. From MariaDB 10.3.1, this is now possible. For example:
DELETE FROM t1 WHERE c1 IN (SELECT b.c1 FROM t1 b WHERE b.c2=0);
SELECT *
FROM employee e FULL OUTER JOIN salarydetails s ON (e.Eid=s.Eid)
WHERE s.Month="January" AND e.Eid="0002"
UNION
SELECT *
FROM salarydetails s FULL OUTER JOIN bonus b ON (s.Eid=b.Eid)
WHERE b.Month="January" AND b.Eid="0002"
I have 3 tables: employee, salarydetails, and bonus. I’m writing a Java code to load a JTable. I have to get the data from these three tables. The query I’m trying to use is the above one. But it gives errors. What am I supposed to do?
so tried to put that SQL code into my java-aplication:
SELECT DISTINCT
StRzImRo.Rohstoff, StRo.Bezeichnung,
CAST (SUM(BwLsImAt.Lieferungen * StRzImRo.Menge * StAt.PROD__REZEPTURGEWICHT / Coalesce(StRz.PARM__BEZUGSGROESSE,1)) AS NUMERIC (9,3)) Rohstoffverbrauch_Gesamt FROM BwLsImAt
JOIN StAt ON (StAt.IntRowId = BwLsImAt.Artikel)
JOIN StRz ON (StRz.IntRowId = StAt.PROD__REZEPTUR)
JOIN StRzImRo ON (StRzImRo.Master = StRz.IntRowId)
JOIN StRo ON (StRzImRo.Rohstoff = StRo.IntRowId)
WHERE StAt.IntRowId > 0
GROUP BY StRzImRo.Rohstoff, StRo.Bezeichnung
-- GROUP BY StRzImRo.Rohstoff, StRzImRo.Menge, StAt.PROD__REZEPTURGEWICHT, Coalesce(StRz.PARM__BEZUGSGROESSE,1)
The code is fully funcional and tested in IBSQL but not working in my java-application.
My app does work properly with other code. I get this error:
org.firebirdsql.jdbc.FBSQLException: GDS Exception. 335544569. Dynamic SQL Error
SQL error code = -104
Token unknown - line 1, column 266
ON
I would be very happy if someone could help me with this problem. Thanks!
P.S.: Sorry for my bad language, but i´m not a native speaker
The error suggests there is an ON in an unexpected place in your query, and as the query itself looks fine, my guess is the problem is with the way you construct the query in your Java application. There might be some whitespace missing in your query.
My guess is that you have something like
query = "SELECT * " +
"FROM table1" +
"JOIN table2 ON " //.....
The missing whitespace will make the SQL:
SELECT * FROM table1JOIN table2 ON ....
For the parser, this is perfectly valid until it encounters the ON token, which triggers the error. Eg the parser identifies it is a SELECT with * (all) columns from table1JOIN with alias table2. During parsing the server doesn't check if the table actually exists, so it doesn't trip over the fact that table1JOIN doesn't exist. That is checked after parsing is successfully completed.
I'm having some trouble executing a nested sql query. It works fine when i run it on TOAD (for Oracle DB) but when I try and execute the same query from my java program it gives me an error : ORA-00923: FROM keyword not found where expected:
Here is the query:
Select *
from(select tb1.Number, tb1.Desc, tb1.Local, tb2.Division
from tb1
inner join tb2
on tb1.Number = tb2.Number
and Local in ('ENG_USA', 'ENG_CHINA', 'FR_FRENCH'))
where Number in ('7512','4706')
Like I mentioned, it executes fine on Toad and is able to retrieve data but the same query throws the ORA-00923 exception.
rset = stmt.executeQuery(Select *
from(select tb1.Number, tb1.Desc, tb1.Local, tb2.Division
from tb1
inner join tb2
on tb1.Number = tb2.Number
and Local in ("+loc+"))
where Number in ("+s+")
Reply With Quote
I had a similar issue with mysql. My problem was that i splitted the query in multiple rows without leaving a space between 2 rows.
So your query should be:
rset = stmt.executeQuery("Select * from(select tb1.Number, tb1.Desc, tb1.Local, tb2.Division from tb1 inner join tb2 on tb1.Number = tb2.Number and Local in ("+loc+")) where Number in ("+s+")"
PS: I would like to write this as a comment but for some reason i can't in this question. Sorry!
First off, I don't see the beginning or ending double-quotes in your Java code. Since your Java code must compile in order to get far enough to receive an Oracle error, I'm assuming that there is a double quote prior to the SELECT, a double-quote after the final close paren, and then another close parent to match to the open paren on the executeQuery. So I'm assuming that your actual code is something like
rset = stmt.executeQuery(
"Select *
from(select tb1.Number, tb1.Desc, tb1.Local, tb2.Division
from tb1
inner join tb2
on tb1.Number = tb2.Number
and Local in ("+loc+"))
where Number in ("+s+")");
Is there a reason that you're building the SQL statement dynamically rather than using bind variables? Using bind variables is more secure since you don't need to worry about SQL injection attacks. It is more efficient since you're not forcing the database to hard parse the query every time. And it saves you from many sorts of errors around quoting and escaping. In your case, assuming that the local variable loc does not have the leading and trailing single quotes, you'd need to include those in your query
rset = stmt.executeQuery(
"Select *
from(select tb1.Number, tb1.Desc, tb1.Local, tb2.Division
from tb1
inner join tb2
on tb1.Number = tb2.Number
and Local in ('"+loc+"'))
where Number in ("+s+")");
Had you used bind variables and just bound loc to the first bind variable, on the other hand, you wouldn't need to worry about adding the single quotes (or escaping any single quotes in loc.