I have of values (1, 2, 3, for example), and I want to pass that list to a SQL query:
"select name from tbl where id in" + list
How might I achieve this?
you have to put your list directly to sql statement
example:
String sql="select name from tbl where id in ("+StringUtils.join(list, ',')+")";
Statement st=connection.createStatement();
st.execute(sql);
String.join(",", list), however this solution is not appropriate for String parameters.it depends on how you are constructing your sql. If you are constructing it yourself (bad idea) you need to do make the sql look like -
... where id in (1,2,3)...
Since in your comment you specify hibernate hql, something like -
Query query = session.createSQLQuery("from User where id in :ids ");
query.setParameter("ids", idsList);
List list = query.list();
should get you started. Note User is the name of the Object you mapped to the table you want to query.
Pass the list in as a comma seperated list and use a split function to split it into a temporary table variable.
CREATE FUNCTION dbo.Split (@sep char(1), @s varchar(512))
RETURNS table
AS
RETURN (
WITH Pieces(pn, start, stop) AS (
SELECT 1, 1, CHARINDEX(@sep, @s)
UNION ALL
SELECT pn + 1, stop + 1, CHARINDEX(@sep, @s, stop + 1)
FROM Pieces
WHERE stop > 0
)
SELECT pn,
SUBSTRING(@s, start, CASE WHEN stop > 0 THEN stop-start ELSE 512 END) AS s
FROM Pieces
)
You can write code like and then pass uuidsWithRequiredPattern to SQL. Here in below example I had a requirement to have a uuids prefixed with single quote , suffixed with single quote and delimited with comma.
List<UUID> uuidList = Arrays.asList("581394be-6a27-11ea-bc55-0242ac130003","681394be-6a27-11ea-bc55-0242ac130003")
String uuidsWithRequiredPattern = uuidList.stream()
.map(UUID::toString)
.collect(Collectors.joining(",", "'", "'"));
I know this is a long time past but this was the page that returned when I looked for a solution to exactly this problem. It seems that all answers are not perfect for one reason or another (including the possibility of SQL injection which is a real concern).So, here's my solution:-
/**
* Checks if this range exists in the database already.
* If it does, it will return the original name.
* @param products the list of product names to check
* @return The range's name in the database
* @throws SQLException if SQL fails
* (or if it exists but with multiple names)
*/
private String getOriginalName(final List<String> products)throws SQLException {
if (products.isEmpty()) {
throw new SQLException("Cannot check an empty list");
}
try (Connection connection = ConnectionPoolConfigRulesUtils.getConnection();
PreparedStatement statement = connection.prepareCall(
"SELECT [rangeName] FROM [dbo].[products] WHERE [productName] IN ("
+ repeatString("?", ", ", products.size()) + ") GROUP BY [rangeName]")) {
int fieldNo = 1; //NOPMD DU anomaly
for (final DbProduct product: products) {
statement.setInt(fieldNo++, product.getId());
}
try (ResultSet rset = statement.executeQuery()) {
final String rangeName;
if (rset.next()) {
//Get the first range name
rangeName = Nz.nz(rset.getString("rangeName"));
} else {
//There isn't one so return empty string
rangeName = "";
}
if (rset.next()) {
//But, if there are multiple ranges, this is an error so treat it as such
throw new SQLException("The products you are trying to save exist already in the dabase under more than one range. "
+ "Cannot process the change");
}
return rangeName;
}
}
}
I'm adding this here in case someone stumbles upon it - like me. The easy way to parameterize the list to be used in the "IN" clause is to use the STRING_SPLIT function.
Declare @FirstNamesList nvarchar(100) = 'Mark,John,Sara' Select * from STRING_SPLIT(@FirstNamesList, ',')
https://www.pragimtech.com/blog/sql-optimization/sql-server-select-where-in-list/
You could also use regex inside of your query to be able to parse input provided as a single string/varchar composed of multiple ids separated by commas. In my case, it was useful in a plain slq environment without orm knowing the size of the provided parameters collection. It could be something like this:
select name from tbl where id in
(SELECT REGEXP_SUBSTR(:ids, '[^,]+', 1, LEVEL) FROM DUAL
CONNECT BY REGEXP_SUBSTR(:ids, '[^,]+', 1, LEVEL) IS NOT NULL)
In order for it to work the ids varchar should look something like: 'id1,id2,id3'.
You can control :ids parsing with regex as you wish, sometimes it might be useful to have nonalphanumeric signs combination to avoid unnecessary parsing.
private static String sqlFormatedList(List<String> list){
StringBuilder sb = new StringBuilder();
sb.append("('");
for (String i : list){
sb.append(i+"','");
}
sb.deleteCharAt(sb.length() -1);
sb.deleteCharAt(sb.lastIndexOf(","));
sb.append(")");
return sb.toString();
}
listas some SQL collection and modify SQL query to perform lookup in the collection. Here is an example for Oracle, for MySQL or Postgres it is even easier since there are built-in db array types. I don't recommend using solutions based on assembling string of variable length for production usage.