Sub-Select query error in SQL Server 2008 - java

Consider the below query:
insert into dbo.SubscriptionDetails (taxonomyid)
values(select objectid from SubscriptionObjects where objectname=?)
This query works fine in my local environment and but gives issues while executed the production environment.
Does the sub-select query needs any properties to be set on the SQL-Server level?
I use Java - JDBC for SQL transactions.
See stack trace below:
2013.03.28 15:42:11 CDT ERROR Error while inserting records into SubscriptionDetails table..
java.sql.BatchUpdateException: Subqueries are not allowed in this context. Only scalar expressions are allowed.

I'm surprised your version works in any environment! Try to omit values:
insert into dbo.SubscriptionDetails
(taxonomyid)
select objectid
from SubscriptionObjects
where objectname=?
For more than one subquery, you can:
insert into dbo.SubscriptionDetails
(taxonomyid, contenttypeid)
select (select objectid from SubscriptionObjects where objectname=?)
, (select objectid from SubscriptionObjects where objectname=?)
Alternatively, use parenthesis to force scalar context with values:
insert into dbo.SubscriptionDetails
(taxonomyid, contenttypeid)
values ((select objectid from SubscriptionObjects where objectname=?),
(select objectid from SubscriptionObjects where objectname=?))

Related

Delete from table on same select same table mariadb using jpa

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);

PostgreSQL query works in pgAdmin but not in Java EclipseLink

I have a SQL that counts rows per date truncate (months, days, hours). Think a history graph. Query works fine if executed in pgAdmin but fails in Java using EclipseLink.
pgAdmin query:
SELECT date_trunc( 'hour', delivered_at ),
COUNT(date_trunc( 'hour', delivered_at )) AS num
FROM messages
WHERE channel_type='EMAIL'
AND created_at>='2016-02-28 16:01:08.882'
AND created_at<='2016-02-29 16:01:08.882'
GROUP BY date_trunc( 'hour', delivered_at );
JPQL Named query
SELECT FUNCTION('date_trunc', 'hour', m.deliveredAt ),
COUNT(FUNCTION('date_trunc', 'hour', m.deliveredAt )) AS num
FROM Message m
WHERE m.channelType = :channelType
AND m.createdAt >= :fromDate
AND m.createdAt <= :toDate
GROUP BY FUNCTION('date_trunc', 'hour', m.deliveredAt )
EclipseLink debugging log:
SELECT date_trunc(?, delivered_at), COUNT(date_trunc(?, delivered_at)) FROM messages
WHERE (((channel_type = ?) AND (created_at >= ?)) AND (created_at <= ?)) GROUP BY date_trunc(?, delivered_at)
bind => [hour, hour, EMAIL, 2015-12-27 00:00:00.0, 2015-12-27 00:00:00.0, hour]
Error:
ERROR: column "messages.delivered_at" must appear in the GROUP BY
clause or be used in an aggregate function Position: 23
PostgreSQL log:
2016-03-01 13:22:08 CET ERROR: column "messages.delivered_at" must
appear in the GROUP BY clause or be used in an aggregate function at
character 23 2016-03-01 13:22:08 CET STATEMENT: SELECT date_trunc($1,
delivered_at), COUNT(delivered_at) FROM messages WHERE (((channel_type
= $2) AND (created_at >= $3)) AND (created_at <= $4)) GROUP BY date_trunc($5, delivered_at) 2016-03-01 13:22:08 CET LOG: execute
S_2: SELECT 1
If I replace the binded variables from EclipseLink logged query and execute it in pgAdmin the query works. What is going on here?
Edit: Just to clarify, it also works using em.createNativeQuery.
PostgreSQL can have trouble with resolving parameter binding, which in this case manifests as native SQL with parameters inline work, while JPA generated SQL which defaults to bound parameters fails.
One solution is to turn off parameter binding by passing "eclipselink.jdbc.bind-parameters" with a value of "false" as either a query hint for the specific query, or as a persistence unit property to turn off parameter binding by default for all queries.
On postgresql, you can use the following syntax
GROUP BY 1
That means you will group you agregate using the first selected attribute in the SELECT clause. That might be helpful there

Hibernate 2 with MSSQL for ORDER BY

I have been working with Oracle and Postgre and recently switched to MS SQL 2012.
I use hibernate in my application and wherever I have used the Order by Criteria:
(criteria.addOrder(Order.asc("applicationId")));
It causes an error saying:
aggregate functions dont work.
Once I comment that line out my program works and data can be retrieved.
I'm using Hibernate 3.
Is there any way to order it through hibernate without this error?
edit..
This is one error I get,
Column "SKY.tcrent.RENTNO" is invalid in the ORDER BY clause because
it is not contained in either an aggregate function or the GROUP BY
clause.
Edit 2..
MY query
Query tcSchaduleQ = getSession().createQuery("SELECT SUM(tcs.dueAmount) FROM TrialCalculationSchedule tcs WHERE tcs.facilityId=:facilityId AND tcs.rentalNumber>:rentalNumber AND tcs.dueDate>:dueDate AND dueTypeId IN(:dueTypeId) ORDER BY tcs.rentalNumber ").setInteger("rentalNumber", facility.getPeriod() - noOfprePayments).setInteger("facilityId",facility.getFacilityId()).setDate("dueDate", date).setParameterList("dueTypeId", plist);
Number tcsAmt = (Number) tcSchaduleQ.uniqueResult();
and this is what hibernate generates in HQL
SELECT
SUM(tcs.dueAmount)
FROM
TrialCalculationSchedule tcs
WHERE
tcs.facilityId=:facilityId
AND tcs.rentalNumber>:rentalNumber
AND tcs.dueDate>:dueDate
AND dueTypeId IN(
:dueTypeId
)
ORDER BY
tcs.rentalNumber
and this is the SQL
select
SUM(trialcalcu0_.DUEAMT) as col_0_0_
from
SKYBANKSLFHP.tcrent trialcalcu0_
where
trialcalcu0_.FACID=?
and trialcalcu0_.RENTNO>?
and trialcalcu0_.DUEDATE>?
and (
trialcalcu0_.DUETYPEID in (
? , ?
)
)
order by
trialcalcu0_.RENTNO
Look Like you mix aggregate and non-aggregate expressions .If you are using any aggregate function like AVG() in Select query with some other non-aggregate then you must use Group By ..
Try something like this
createQuery("SELECT SUM(tcs.dueAmount) As DueAmount ...
If you are using Criteria then it should be like this
Criteria crit = sess.createCriteria(Insurance.class);
ProjectionList proList = Projections.projectionList();
proList.add(Projections.sum("investementAmount"));
crit.setProjection(proList);
List sumResult = crit.list();

SQL generated by Hibernate invalid for MS SQL

Hibernate (HQL) generated the following SQL for which I inserted the parameters:
select
sum(activity0_.calculated_work) as col_0_0_
, employee2_.id as col_1_0_
, projectele1_.id as col_2_0_
from
activity activity0_
inner join generic_object activity0_1_ on activity0_.id=activity0_1_.id
left outer join project_element projectele1_ on activity0_.project_element_id=projectele1_.id
left outer join employee employee2_ on activity0_.owner_id=employee2_.id
left outer join org_unit orgunit3_ on employee2_.org_unit_id=orgunit3_.id
where
activity0_1_.deleted=0 and
activity0_.client_id=22
group by
employee2_.id order by SUM(activity0_.calculated_work) DESC
Error message: Column 'project_element.id' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
I executed this SQL directly in the SQL Server Studio with the same result. I commented this line:
, projectele1_.id as col_2_0_
The SQL was then accepted by the SQL Server
The table project_element definitely has a column with the name id it is also referenced in the LEFT OUTER JOIN and there this column is not causing an error.
Removing the alias projectele1_ had no effect.
To me this looks like a really simple SQL statement. I cannot imagine what is wrong with it and the error message is not helping at all. Any ideas what could be wrong with the SQL?
Your SQL syntax is wrong.If you add projectele1_.id to group by clause it will work.Only aggregate functions work in select statement with group by clause.Or if you remove projectele1_.id from select it will work fine.
My mistake. I should have read the error message several times. projectele1_id is not in the group by clause. MS SQL does not allow to include such a column into the select list. This seems to be a consistency check.
Too bad though that the usage of HQL leads to such an exception in SQL Server but not in MySQL Server.

jOOQ - error with alias and quotes

I have this query:
Field<String> yearMonth = DSL.field("FORMATDATETIME({0}, 'yyyy-MM')",
String.class, LICENZE.CREATION_DATE).as("anno_mese");
List<Record3<Integer, String, String>> records =
create.select(DSL.count().as("num_licenze"), LICENZE.EDIZIONE, yearMonth).
from(LICENZE).
groupBy(LICENZE.EDIZIONE, yearMonth).
orderBy(yearMonth).
fetch();
this query generates:
select
count(*) "num_licenze",
"PUBLIC"."LICENZE"."EDIZIONE",
FORMATDATETIME("PUBLIC"."LICENZE"."CREATION_DATE", 'yyyy-MM') "anno_mese"
from "PUBLIC"."LICENZE"
group by
"PUBLIC"."LICENZE"."EDIZIONE",
"anno_mese"
order by "anno_mese" asc
executing it i get: Column "anno_mese" not found; SQL statement
Testing the generated query and removing the quotes from anno_mese in every parts of the query make the query works instead.
Is my query wrong or am I using jooq in the wrong way?
The alias in this query is not so important, I can run the query without using it too but just to understand how it works.
I am using h2 as database.
Thanks for the help
I suspect this is a bug in H2, which I've reported here, because the query looks fine to me. Here are some workarounds that you can do from the jOOQ side:
Don't reference the "anno_mese" column by name
While SQL is a bit repetitive otherwise, you won't notice the difference with jOOQ. I simply moved the as("anno_mese") method call into the SELECT clause. You don't really need it in the GROUP BY and ORDER BY clauses.
Field<String> yearMonth = DSL.field("FORMATDATETIME({0}, 'yyyy-MM')",
String.class, LICENZE.CREATION_DATE);
List<Record3<Integer, String, String>> records =
create.select(DSL.count().as("num_licenze"),
LICENZE.EDIZIONE,
yearMonth.as("anno_mese")).
from(LICENZE).
groupBy(LICENZE.EDIZIONE, yearMonth).
orderBy(yearMonth).
fetch();
Disable quoting in jOOQ generated queries
You can use jOOQ's Settings to prevent schema / table / column names from being quoted. Example:
DSLContext create = DSL.using(connection, SQLDialect.H2,
new Settings().withRenderNameStyle(RenderNameStyle.AS_IS);
Use upper case column names
This will probably work: DSL.field(...).as("ANNO_MESE")

Categories