I need to insert a huge amount of data in a table that is in FK with another one that has a two big fields in Eager.
The HQL query is:
insert into DeviceAuthorizationEntry (id, osc, moduleName, delegateModule, functionName, groupName, owner)
select concat(item0.id.uuid, '1413971469473'), item0.osc, 'aaaaaaaa',
'devices', 'view_devices', 'administrator', item0
from device.model.Device as item0
where item0.osc IN (:oscNameList0)
and item0.nodeTypeDefinition.QN IN (:nodeTypesList0)
and not exists (select 1 from device.model.DeviceAuthorizationEntry as auth
where auth.moduleName != 'aaaaaaa'
and auth.delegateModule != 'devices'
and auth.functionName != 'view_devices'
and auth.groupName != 'administrator'
and auth.owner != item0 )
But the one executed on Oracle is:
INSERT
INTO DeviceAuthorizationEntry
(
id,
osc,
moduleName,
delegateModule,
functionName,
groupName,
owner_uuid
)
SELECT device0_.uuid
||'1413965664136' AS col_0_0_,
device0_.osc AS col_1_0_,
'aaaaaaaa' AS col_2_0_,
'devices' AS col_3_0_,
'view_devices' AS col_4_0_,
'administrator' AS col_5_0_,
device0_.uuid AS col_6_0_
FROM dem_device device0_,
cor_noddef nodetypede1_
WHERE device0_.uuid_ndtypedef=nodetypede1_.uuid
AND 1 =1
AND (device0_.osc IN (? , ?))
AND (nodetypede1_.QN IN (? , ? , ? , ? , ? , ? , ? , ? , ?))
AND NOT (EXISTS
(SELECT 1
FROM DeviceAuthorizationEntry deviceauth2_
WHERE deviceauth2_.moduleName <>'aaaaaaaa'
AND deviceauth2_.delegateModule<>'devices'
AND deviceauth2_.functionName <>'view_devices'
AND deviceauth2_.groupName <>'administrator'
AND deviceauth2_.owner_uuid <>uuid
))
As you can see in the last "and" of the exists subquery, hibernate does not precede the "uuid" field with the alias "device0_".
Hibernate supports the insert into select as you can see here https://docs.jboss.org/hibernate/orm/4.1/devguide/en-US/html/ch11.html#d5e2610
I don't know where I'm wrong.
Related
Iam using coalesce mybatis switch case in my query, where iam getting error like
Error querying database. Cause: java.sql.SQLException: ORA-01427:
single-row subquery returns more than one row
this is my query
(select
(case when (coalesce(t1.col1,t2.col1, t1.col2, t1.col3) is null)
then (select sysdate from dual)
else (coalesce(t1.col1,t2.col1, t1.col2, t1.col3))
end )
from table1 t1
join table2 t2
on t1.id IN (t2.id))
Thanks in advance
Seems you have a lot of () but overall you should use = operator and not IN (t2.id) for join t2.id
select
case when coalesce(t1.col1,t2.col1, t1.col2, t1.col3) is null
then sysdate
else coalesce(t1.col1,t2.col1, t1.col2, t1.col3)
end
from table1 t1
join table2 t2 on t1.id = t2.id
And looking at the code you posted in sample you have a select as a column result and this select return several rows, ( this raise the error). You also have a mixin of join syntax some based on explicit join syntax some based on old implicit join syntax based on comma separated table name and where condition. You should try using this
<select id="Trigger" parameterType="hashmap" resultType="java.util.HashMap" flushCache="true">
SELECT
select case when coalesce(table1.col1, table2.col2,table1.col3, table1.col4) is null
then sysdate
else coalesce(table1.col1, table2.col2,table1.col3, table1.col4) end as "ProgressDate"
, table3.id as "ID"
from table1
INNER join table2 on table1.id = table2.id
INNER JOIN table3 ON table1.id = table3.id
INNER JOIN table4 table2.action = table4.action
WHERE table3.transaction = #{inputvaluepassed}
</select>
The query you mention in the question takes the place of a scalar subquery included in another... main query. I formatted the whole query (for readability) and it looks like this:
SELECT
(
select case when coalesce(table1.col1, table2.col2,table1.col3,
table1.col4) is null
then (select sysdate from dual)
else coalesce(table1.col1, table2.col2,table1.col3, table1.col4)
end
from table1
join table2 on table1.id = table2.id
) as "ProgressDate",
table3.id as "ID"
FROM table3, table1, table2, table4
WHERE table3.transaction = #{inputvaluepassed}
AND table1.id = table3.id
AND table2.id=table1.id and table2.action = table4.action
Now, by definition, scalar subqueries can only return zero or one row. In your case it seems that at runtime this subquery is returning multiple rows, and the main query crashes.
You'll need to somehow produce a single row at most: maybe by aggregating the rows (using GROUP BY), maybe by picking one row only from the result set (using LIMIT); there are other options. If we choose the to limit the rows to 1 at most your query could look like:
SELECT
(
select case when coalesce(table1.col1, table2.col2,table1.col3,
table1.col4) is null
then (select sysdate from dual)
else coalesce(table1.col1, table2.col2,table1.col3, table1.col4)
end
from table1
join table2 on table1.id = table2.id
limit 1 -- added this line
) as "ProgressDate",
table3.id as "ID"
FROM table3, table1, table2, table4
WHERE table3.transaction = #{inputvaluepassed}
AND table1.id = table3.id
AND table2.id=table1.id and table2.action = table4.action
This is just one possible cheap solution to the issue. A better understanding on how to pick the right row over multiples ones can produce a better solution.
I want to query my database (H2) using the following code:
PreparedStatement x = connection.prepareStatement("INSERT INTO tree(ancestor, desc) (select ancestor,? from tree where desc = ? union all select ?,? )");
x.setInt(1,99219);
x.setInt(2,4);
x.setInt(3,99219);
x.setInt(4,99219);
but it doesn't work and I get the following error:
org.h2.jdbc.JdbcSQLException: Unknown data type: "?, ?"; SQL statement:insert into tree(ancestor, desc) (select ancestor,? from tree where desc = ? union all select ?,? ) [50004-192]
Executing the query in the console (without JDBC) works fine. What is wrong with this code?
"INSERT INTO tree(ancestor, desc) (select ancestor,? from tree where desc = ? union all select ?,? )"
This SQL statement is incomplete. it is mising a FROM part after this:
union all select ?,?
The column returned by UNION select have to match by type the columns in the first select. You can do an explicit cast.
I'm required to write a couple of UPDATE queries to parse data from a .csv file, but i do not know how the table works, i don't even have direct access to the Database, i just got an INSERT query like this one :
insert into lr_umbrales_valores (umcod_id, uvfec_dt, uvval_nm)
values ((select umcod_id from lr_umbrales
where lrcod_nm = (
select lrcod_id from lr_lineas_referencia
where me_metrica_nm = ?
and fecha_baja_dt is null)
and umtip_tx='S'), sysdate, ?)
So i'm trying this :
UPDATE LR_UMBRALES_VALORES SET UVVAL_NM = ?
WHERE (
SELECT UMCOD_ID FROM LR_UMBRALES
WHERE LRCOD_NM = (
SELECT LRCOD_ID FROM LR_LINEAS_REFERENCIA
WHERE ME_METRICA_NM = ?
AND FECHA_BAJA_DT IS NULL
)
AND UMTIP_TX = 'S')
AND UVFEC_DT = TO_DATE(?, 'DD/MM/YYYY HH24:MI:SS')");
This gives me a 'Missing Expression' Error (ORA-00936)
This is the only Information about the tables i got :
This is the Table i need to Update (its UVVAL_NM)
From this one, i get the UMCOD_ID when LRCOD_NM is the same as the LRCOD_ID from the next table.
Get the LRCOD_ID when ME_METRICA_NM is the same as the '?' parameter
Any tip in how to approach this? Needless to say, i'm completely new with SQL so this may be a very obvious mistake but i cannot get it right.
This part
WHERE (
SELECT UMCOD_ID FROM LR_UMBRALES
WHERE LRCOD_NM = (
SELECT LRCOD_ID FROM LR_LINEAS_REFERENCIA
WHERE ME_METRICA_NM = ?
AND FECHA_BAJA_DT IS NULL
)
AND UMTIP_TX = 'S')
causes the error. Maybe you wanted something like
WHERE UMCOD_ID = (
SELECT UMCOD_ID FROM LR_UMBRALES
WHERE LRCOD_NM = (
SELECT LRCOD_ID FROM LR_LINEAS_REFERENCIA
WHERE ME_METRICA_NM = ?
AND FECHA_BAJA_DT IS NULL
)
AND UMTIP_TX = 'S')
I have a table like this:
create table images (
image_id serial primary key,
user_id int references users(user_id),
date_created timestamp with time zone
);
I then have a tag table for tags that images can have:
create table images_tags (
images_tag_id serial primary key,
image_id int references images(image_id),
tag_id int references tags(tag_id)
);
To get the results I want, I run a query like this:
select image_id,user_id,tag_id from images left join images_tags using(image_id)
where (?=-1 or user_id=?)
and (?=-1 or tag_id in (?, ?, ?, ?)) --have up to 4 tag_ids to search for
order by date_created desc limit 100;
The problem is, I want to limit based on the number of unique image_ids because my output will look like this:
{"images":[
{"image_id":1, "tag_ids":[1, 2, 3]},
....
]}
Notice how I group the tag_ids into an array for output, even though the SQL returns a row for each tag_id and image_id combo.
So, when I say limit 100, I want it to apply to 100 unique image_ids.
Maybe you should put one image on each row? If that works, you can do:
select image_id, user_id, string_agg(cast(tag_id as varchar(2000)), ',') as tags
from images left join
images_tags
using (image_id)
where (?=-1 or user_id=?) and
(?=-1 or tag_id in (?, ?, ?, ?)) --have up to 4 tag_ids to search for
group by image_id, user_id
order by date_created desc
limit 100;
If that doesn't work, then use a CTE:
with cte as (
select image_id, user_id, tag_id,
dense_rank() over (order by date_created desc) as seqnum
from images left join
images_tags
using (image_id)
where (?=-1 or user_id=?) and
(?=-1 or tag_id in (?, ?, ?, ?)) --have up to 4 tag_ids to search for
)
select *
from cte
where seqnum <= 100
order by seqnum;
Select 100 qualifying images first, and then join images_tags.
Use an EXISTS semi-join to satisfy the condition on images_tags and take care to get the parentheses right.
SELECT i.*, t.tag_id
FROM (
SELECT i.image_id, i.user_id
FROM images i
WHERE (? = -1 OR i.user_id = ?)
AND (? = -1 OR EXISTS (
SELECT 1
FROM images_tags t
WHERE t.image_id = i.image_id
AND t.tag_id IN (?, ?, ?, ?)
))
ORDER BY i.date_created DESC
LIMIT 100
) i
LEFT JOIN images_tags t
ON t.image_id = i.image_id
AND (? = -1 OR t.tag_id in (?, ?, ?, ?)) -- repeat condition
This should be faster than a solution with window functions and CTEs.
Test performance with EXPLAIN ANLAYZE. As always run a couple of times to warm up cache.
Can JOOQ do 'insert into select' syntax for specified columns? I run several different tries..
The Tables:
table1 (Expected insert)
id column1 column2 column3 ... timestamp
1 John Leo null 2012/1/28 23:32:23 (Expected insert)
table2
id col1 col2 col3
101 John xxx xxx (from table2.col1)
102 xxx xxx xxx
table3
id col1 col2 col3
101 xxx Leo xxx (from table3.col2)
102 xxx xxx xxx
INSERT INTO table1 ( column1, column2 )
SELECT table2.col1, table3.col2
FROM table2 join table3 t3 on table2.id = table3.id
where table2.id = 101;
JOOQ code:
create.insertInto(table1, column1, column2 )
.values( create.select( table2.col1, table3.col2 )
.from(table2)
.join(table3)
.on( table12.id.equal(table3.id) )
.where( table2.id.equal(101) ))
.execute(); //.getSQL();
JOOQ show error message:
The number of values must match the number of fields
Anyone know what problem I make and how I can fix my JOOQ code.
thanks, Pay.
Reference:
Example: INSERT SELECT syntax support
You're using the INSERT .. VALUES syntax, instead of the INSERT .. SELECT syntax. Your subquery provides values column1 but you don't provide any value for column2. What you want to do is described further down in the manual at "Example: INSERT SELECT syntax support". In your case, this would read (jOOQ 2.x syntax, no longer available in jOOQ 3.x):
create.insertInto(table1,
create.select( table2.col1, table3.col2 )
.from(table2)
.join(table3)
.on( table12.id.equal(table3.id) )
.where( table2.id.equal(101) ))
.execute(); //.getSQL();
Or with a custom projection (jOOQ 3.x syntax):
create.insertInto(table1, column1, column2)
.select(create.select(...))
.execute();