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();
Related
just switched to spring boot from .NET Core, in .NET core we can easily nest a select inside a select like this:
var result = from c in context.Cars
join br in context.Brands
on c.BrandId equals br.Id
join col in context.Colors
on c.ColorId equals col.Id
select new CarDetailDto
{
Id = c.Id,
BrandName = br.Name,
CarName = c.Name,
ColorName = col.Name,
DailyPrice = c.DailyPrice,
ModelYear = c.ModelYear,
CarImages = (from cimg in context.CarImages
where cimg.CarId == c.Id
select new CarImage
{
Id = cimg.Id,
ImagePath = cimg.ImagePath,
CarId = c.Id,
Date = cimg.Date
}).ToList()
};
I want to do that in JPQL as well but didnt manage to solve
#Query( select column1, column2, column3 from tablename1 where coluname=(select columname from tablename2 where columnname=abcd) )
Your JPQL query should look like above.
Whatever subquery you write with condition.
If your query is fetching 3 column you need to create a DTO with same column name.
If your query is fetching list of rows then your actual jpql will look like this.
#Query( select column1, column2, column3 from tablename1 where coluname=
(select columname from tablename2 where columnname=abcd) )
List<ResultDTO> findAllResultList(Parameter value);
Above it is mapping the result to list of DTO objects to result rows.
If your query is fetching single row then your actual jpql will look like this.
#Query( select column1, column2, column3 from tablename1 where coluname=
(select columname from tablename2 where columnname=abcd) )
ResultDTO findResult(Parameter value);
The single result is mapped to one DTO object.
Make sure your result column name and DTO column name matches
Using the JPA repository call the names of the method which you used for the particular query.
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 have list of data and a table like below.
Data : {ABC111,ABC112,ABC113,111111,111112,111113}
Table:
Column 1 Column 2
ABC111 ABC115
ABC115 111333
111111 ABC112
111111 111112
ABC123 111113
111113 ABC113
My result should be like below
Result : {ABC115,111333,111113,ABC113,ABC123,ABC112,111112}
Explanation:
Data - ABC111 is associated to ABC115 which is also associated to 111333. Hence the result is ABC115,111333.
Similarly, ABC113 is associated to 111113 which is also associated to ABC123. Result = 111113,ABC123.
Is it possible to implement the above using a query. Looking for Prepared statement to which I will pass the Data that I mentioned above.
Try this:-
/*CREATING RECORDS FOR THE MAIN TABLE*/
CREATE TABLE TABLES(Column1 text, Column2 text);
INSERT INTO TABLES VALUES('ABC111','ABC115');
INSERT INTO TABLES VALUES('ABC115','111333');
INSERT INTO TABLES VALUES('111111','ABC112');
INSERT INTO TABLES VALUES('111111','111112');
INSERT INTO TABLES VALUES('ABC123','111113');
INSERT INTO TABLES VALUES('111113','ABC113');
COMMIT;
/*CREATE LIST TO BE SUPPLIED*/
CREATE TABLE LIST(Column1 text);
INSERT INTO LIST VALUES('ABC111');
INSERT INTO LIST VALUES('ABC112');
INSERT INTO LIST VALUES('ABC113');
INSERT INTO LIST VALUES('111111');
INSERT INTO LIST VALUES('111112');
INSERT INTO LIST VALUES('111113');
COMMIT;
/*CODE TO GET THE RESULT*/
SELECT CONCAT('{',GROUP_CONCAT(RESULT),'}') AS RESULT FROM
(
SELECT DISTINCT COLUMN1 AS RESULT FROM
(
Select a.column2 as column1,b.column2
from
(
Select * from
tables
where column1 in (SELECT COLUMN1 FROM LIST)
) a
inner join
tables b
on a.column2=b.column1
UNION ALL
Select b.column2 as column1,b.column1 as Column2
from
(
Select * from
tables a
where column2 in (SELECT COLUMN1 FROM LIST)
) a
inner join
tables b
on a.column1=b.column2
) a
UNION ALL
SELECT DISTINCT COLUMN2 AS RESULT FROM
(
Select a.column2 as column1,b.column2
from
(
Select * from
tables
where column1 in (SELECT COLUMN1 FROM LIST)
) a
inner join
tables b
on a.column2=b.column1
UNION ALL
Select b.column2 as column1,b.column1 as Column2
from
(
Select * from
tables a
where column2 in (SELECT COLUMN1 FROM LIST)
) a
inner join
tables b
on a.column1=b.column2
) a
UNION ALL
SELECT DISTINCT COLUMN2 AS RESULT FROM
(
Select distinct a.Column1, a.column2
from
(
Select * from
tables a
where column2 in (SELECT COLUMN1 FROM LIST)
) a
inner join
(
Select * from
tables a
where column2 in (SELECT COLUMN1 FROM LIST)
) b
on a.column1=b.column1
where a.column2 not in
(
Select column1 from
(
Select b.column2 as column1,b.column1 as Column2
from
(
Select * from
tables a
where column2 in (SELECT COLUMN1 FROM LIST)
) a
inner join
tables b
on a.column1=b.column2
) a
)
) a
) a;
Hope this helps:-)
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 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.