Groovy SQL named list parameter - sql

I want to use a keyset of a Map as a list parameter in a SQL query:
query = "select contentid from content where spaceid = :spaceid and title in (:title)"
sql.eachRow(query, [spaceid: 1234, title: map.keySet().join(',')]) {
rs ->
println rs.contentid
}
I can use single values but no Sets or Lists.
This is what I've tried so far:
map.keySet().join(',')
map.keySet().toListString()
map.keySet().toList()
map.keySet().toString()
The map uses Strings as key
Map<String, String> map = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
Also, I don't get an error. I just get nothing printed like have an empty result set.

You appoach will not give the expected result.
Logically you are using a predicate such as
title = 'value1,value2,value3'
This is the reason why you get no exception but also no data.
Quick search gives a little evidence, that a mapping of a collections to IN list is possible in Groovy SQL.
Please check here and here
So very probably you'll have to define the IN list in a proper length and assign the values from your array.
title in (:key1, :key2, :key3)
Anyway something like this works fine:
Data
create table content as
select 1 contentid, 1 spaceid, 'AAA' title from dual union all
select 2 contentid, 1 spaceid, 'BBB' title from dual union all
select 3 contentid, 2 spaceid, 'AAA' title from dual;
Groovy Script
map['key1'] = 'AAA'
map['key2'] = 'BBB'
query = "select contentid from content where spaceid = :spaceid and title in (${map.keySet().collect{":$it"}.join(',')})"
println query
map['spaceid'] = 1
sql.eachRow(query, map) {
rs ->
println rs.contentid
}
Result
select contentid from content where spaceid = :spaceid and title in (:key1,:key2)
1
2
The key step is to dynamicall prepare the IN list with proper names of the bind variable using the experssion map.keySet().collect{":$it"}.join(',')
Note
You may also want to check the size if the map and handle the case where it is greater than 1000, which is an Oracle limitation of a single IN list.

It has worked for me with a little adaptation, I've added the map as a second argument.
def sql = Sql.newInstance("jdbc:mysql://localhost/databaseName", "userid", "pass")
Map<String,Long> mapProduitEnDelta = new HashMap<>()
mapProduitEnDelta['key1'] = 1
mapProduitEnDelta['key2'] = 2
mapProduitEnDelta['key3'] = 3
produits : sql.rows("""select id, reference from Produit where id IN (${mapProduitEnDelta.keySet().collect{":$it"}.join(',')})""",mapProduitEnDelta),
Display the 3 products (colums + values from the produit table) of id 1, 2, 3

Related

Multi-value object search in CrateDB when this one is within an array of objects

I'm trying to migrate our current ES to CrateDB and one of the issues I'm facing is searching for two specific values within the same object when this object is part of an array of objects.
CREATE TABLE test.artefact (
id INTEGER,
metadata ARRAY(OBJECT(STATIC) AS (
key_id INTEGER,
value TEXT
))
);
insert into test.artefact(id, metadata) values (
1,
[
{
"key_id" = 1,
"value" = 'TEST1'
},
{
"key_id" = 2,
"value" = 'TEST2'
}
]
);
So basically, I'm trying to search metadata providing key_id and value.
A select like this one finds artefact 1 as a match, even when key and value are in different objects:
select * from test.artefact where 1 = ANY(metadata['key_id']) AND 'TEST2' = ANY(metadata['value'])
I have tried other functions, like UNNEST, with no luck.
Copy from CrateDB Community:
One way that should work is
SELECT *
FROM test.artefact
WHERE {key_id = 1, value = 'TEST2'} = ANY(metadata)
however this is probably not the most performant way.
together with the queries on the fields it might be quick enough.
SELECT *
FROM test.artefact
WHERE
1 = ANY(metadata['key_id'])
AND 'TEST2' = ANY(metadata['value'])
AND {key_id = 1, value = 'TEST2'} = ANY(metadata)

Map data with fields value

Ive a data set in below format and trying below big query
Some additional content, Key & value are array format.
Table format: id, {key: "abc", value: "true"} and when I unnest it looks as in above screenshot.
I want to run a SQL query based on key & value : ex, I want to get only those value if abc = false, def = true
Sample output I'm expecting.
I'm not sure if I'm making any sense. but this is what I'm trying to achieve.
Thanks!
With the data you shared you could use a CASE expression. The Query below should work fine for you:
SELECT
id,
key,
CASE key
WHEN 'abc' THEN 'FALSE'
WHEN 'def' THEN 'TRUE'
ELSE NULL
END
AS VALUE
FROM `project.dataset.table`
WHERE key='abc' or key='def'

Select where id = array (Oracle JDBC)

I'm currently working with trying to compare an ID in Oracle(A VARCHAR2) with an array of IDs I have as input.
This is what I want to do:
Select user, city where id = :arrayOfIds
In Postgres with JDBC I would use:
Select user, city where id = any(:arrayOfIds)
Is there an equivalent function in Oracle, or a way to do this?
You should use:
Select user, city where id in (:arrayOfIds)
and in you code, you need to trasform your array in string with ids:
arrayOfIds[0] --> 1
arrayOfIds[1] --> 3
arrayOfIds[2] --> 5
...
in
1, 3, 5, ...
and you can use:
Array array = conn.createArrayOf("arrayOfIds", new Object[]{"1", "2","3"});
pstmt.setArray(1, array);
How to use an arraylist as a prepared statement parameter

How to use where in list items

I have a database as below:
TABLE_B:
ID Name LISTID
1 NameB1 1
2 NameB2 1,10
3 NameB3 1025,1026
To select list data of table with ID. I used:
public static List<ListData> GetDataById(string id)
{
var db = Connect.GetDataContext<DataContext>("NameConnection");
var sql = (from tblB in db.TABLE_B
where tblB.LISTID.Contains(id)
select new ListData
{
Name= tblB.Name,
});
return sql.ToList();
}
When I call the function:
GetDataById("10") ==> Data return "NameB2, NameB3" are not correct.
The data correct is "NameB2". Please help me about that?
Thanks!
The value 10 will cause unintended matches because LISTID is a string/varchar type, as you already saw, and the Contains function does not know that there delimiters that should be taken into account.
The fix could be very simple: surround both the id that you are looking for and LISTID with extra commas.
So you will now be looking for ,10,.
The value ,10, will be found in ,1,10, and not in ,1025,1026,
The LINQ where clause then becomes this:
where ("," + tblB.LISTID + ",").Contains("," + id + ",")

Dynamic appending constraints in SQL query

I have this SQL
SELECT devudp1.deviceoid,devudp1.valueType
FROM DeviceUdpValues devUDP1
WHERE devudp1.udpname='TestUDP'
and <<either bdvalue or string value based on user selected value datatype>>
Here in the Query based on the devudp1.valueType I want to append below attribute
If the valueType is 3 then I want to append my above select clause with devudp1.bdvalue ='10', else it should be appended by devudp1.bdvalue = 'Hello'
So the above query when valueType is 3 will look like
SELECT devudp1.deviceoid,devudp1.valueType
FROM DeviceUdpValues devUDP1
WHERE devudp1.udpname='TestUDP'
AND devudp1.bdvalue = '10'
else it will look like
SELECT devudp1.deviceoid,devudp1.valueType
FROM DeviceUdpValues devUDP1
WHERE devudp1.udpname='TestUDP'
AND devudp1.stringValue = 'Hello'
Can anyone suggest me how to put this logic in place
Try this:
SELECT devudp1.deviceoid,devudp1.valueType
FROM DeviceUdpValues devUDP1
WHERE devudp1.udpname='TestUDP'
AND (
(<USER-SELECTED-VALUE> = 3 AND devudp1.bdvalue ='10') OR
(<USER-SELECTED-VALUE> <> 3 AND devudp1.stringvalue ='Hello')
)