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
Related
I am working with the JSON_VALUE function and I need a kind of dynamic query
I have a column called Criteria and sometimes it has 1 value but sometimes it has 2 or 3 vales like:
Example of 1 value: $.IRId = 1
Example of 2 values: $.IROwner = 'james.jonson#domain.com' AND DaysTillDue < 10
So in order to read the values from a JSON column and taking the Criteria column I am using this logic:
DECLARE #CriteriaValue int
,#CriteriaStatement VARCHAR(50)
SELECT #CriteriaValue=SUBSTRING(Criteria, CHARINDEX('=',Criteria)+1, len(Criteria)) FROM #SubscriptionCriteria;
SELECT #CriteriaStatement= SUBSTRING(Criteria,0, CHARINDEX('=',Criteria)) FROM #SubscriptionCriteria;
SELECT #CriteriaValue,#CriteriaStatement
SELECT *
FROM [SAAS].[ObjectEvent]
WHERE
JSON_VALUE(JSONMessageData, #CriteriaStatement) = #CriteriaValue
That SQL code is taking only the Criteria Column with only 1 value ($.IRId = 1), but the idea is to have something that reads the criteria no matter the different filters and apply them into the final query. The idea I have is that the query would look like this:
SELECT *
FROM [SAAS].[ObjectEvent]
WHERE
JSON_VALUE(JSONMessageData, #CriteriaStatement1) = #CriteriaValue1 ADN JSON_VALUE(JSONMessageData, #CriteriaStatement2) = #CriteriaValue2 AND
JSON_VALUE(JSONMessageData, #CriteriaStatement3) = #CriteriaValue3
ETC
Any suggestion?
I'm using PostgreSQL 9.6 and I have the following table, let's call it table1:
id | json_data
____________________
200 | {"state": [3, 4, 5]}
I want to be able to perform the following query: extract the array inside the "state" key in json_data for the record with id 1, but also remove some of the integers from the array in the process.
For example (in pseudo-code):
extract_state(id = 200, remove_numbers_from_json_data_state = [3, 5]) should return [4]
There is no built-in function for that, but you can easily write your own:
create function remove_numbers(p_array jsonb, p_nr variadic int[] )
returns jsonb
as
$$
select jsonb_agg(x)
from jsonb_array_elements(p_array) as t(x)
where t.x::int <> ALL(p_nr);
$$
language sql
immutable;
Then you can use it like this:
select id, remove_numbers(json_data -> 'state', 4,5)
from t1
where id = 1;
If you prefer to pass a JSON array value, you can define the function like this:
create function remove_numbers(p_array jsonb, p_to_remove jsonb)
returns jsonb
as
$$
select jsonb_agg(x)
from jsonb_array_elements(p_array) as t(x)
where t.x not in (select *
from jsonb_array_elements(p_to_remove))
$$
language sql;
Then you would need to use remove_numbers(json_data -> 'state', '[4,5]')
You'd use a query like this:
SELECT json_data->'state'->>1 FROM table1 WHERE id = 200;
You can test this way, without having a table:
SELECT '{"state": [3, 4, 5]}'::jsonb->'state'->>1
Here is a reference for using JSON in Postgres:
https://www.postgresql.org/docs/current/functions-json.html
It returns 4, not [4], so if you need to, you could select it as an array:
SELECT ARRAY[('{"state": [3, 4, 5]}'::jsonb->'state'->>1)::int]
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
I'm trying to put together a postgres query that checks to see if a json field with an array of id's contains any id's from a subselect query. Eg: a typical user table looks like this:
User
.id // Int --> 1
.first_name // String --> Joe
.last_name // String --> Doe
.tags // JSON --> [4, 9, 21, 26, 39]
the tags table is this:
Tags
.id // Int --> 1
.name // String --> "Peaches"
But anyway, here is what I am trying to achieve:
select u.id, u.first_name from users u
where u.tags = any( array (
select t.id from tags t where t.name in ('Peaches', 'Nuts and Honey', 'Flour')
));
This results in the following error:
No function matches the given name and argument types. You might need to add explicit type casts.
Any thoughts on how to fix this would be awesome!
I have some queries like this:
List listOfIntegers = Arrays.asList(new Integer[] {1, 2, 3});
List objects =
namedParameterJdbcTemplate.query("select * from bla where id in ( :ids )",
Collections.singletonMap("ids", listOfIntegers),
myRowMapper);
This will send this SQL query to the database:
select * from bla where id in ( 1, 2, 3 )
Now I want to send this type of query to the database:
select * from bla where (id,name) in ( (1,'foo'), (2,'bar'), (3,'foobar'))
Do I need to pass a List<List<Object>> to accomplish this? Will it work with Spring JDBCTemplate?
I have debugged Spring code and found that it expects tuples to be provided as Object[], so for it to work with a List it should be a List<Object[]>.