Я хочу создать PreparedStatement
для запроса следующим образом:
SELECT * FROM table WHERE (a, b) in ( (a1, b1), (a2, b2), (a3, b3) );
Как я могу отправить [(a1, b1), (a2, b2), (a3, b3)]
в PreparedStatement
с Java или создать его из пары массивов (a1, a2, a3)
и (b1, b2, b3)
?
попробуй это:
select blah from blam where hoot in (?)
Затем создайте один параметр следующим образом:
int[] leftArray = {1, 2, 3};
int[] rightArray = {7, 9, 11};
StringBuilder buffer = new StringBuilder();
for (int index = 0; index < leftArray.length; ++index)
{
if (index > 0)
{
buffer.append(',');
}
buffer.append('(');
buffer.append(leftArray[index]);
buffer.append(',');
buffer.append(rightArray[index]);
buffer.append(')');
}
Наконец, используйте значение из буфера в качестве параметра для подготовленного оператора.
Предположим, у вас есть 2 массива.
int[] tuple_left = int[]{1,2,3,4,5,6};
int[] tuple_right = int[]{1,2,3,4,5,6};
Затем вы создадите запрос:
if(tuple_left.length == tuple_right.length && tuple_left.length >= 1){
String placeholders = "";
for(int i=0; i < tuple_left.length; i++){
if(i == 0){
placeholders += "(?,?)";
}else{
placeholders += ",(?,?)";
}
}
String sql = "SELECT * FROM table WHERE (a,b) in ("+placeholders+")";
Затем вы должны подготовить запрос и добавить значения:
PreparedStatement ps = ....
for(int i=0; i < tuple_left.length; i++){
ps.setInt((2*i)+0,tuple_left[i]);
ps.setInt((2*i)+1,tuple_right[i]);
}
ps.execute();
И, конечно, обрабатывайте случай, когда нет аргументов или разных длин:
}else{
//Invalid argument count, throw an exception or handle the error otherwise.
}
Редактировать:
Я провел некоторое тестирование с помощью postgresql. При выборе (a, b) из таблицы он будет возвращать его как запись типа. Эта запись не может сравниться с массивом. Одним из способов обойти это ограничение является выбор значений из подзапроса. В случае 2D-массива мы можем сделать это как подзапрос:
SELECT
arr[i][1],
arr[i][2]
FROM
(SELECT
generate_series(1, array_upper(arr, 1)) AS i,
arr
FROM (SELECT ARRAY[[1,5],[1,10]] arr) t
) t
Мы могли бы сделать это в java:
Array arr = con.createArrayOf("int", new Object[][]{{1,2},{4,5},{7,8}});
String sql = "SELECT arr[i][1],arr[i][2]"+
"FROM ("+
" SELECT generate_series(1, array_upper(arr, 1)) AS i, arr"+
" FROM (SELECT ? AS arr) t"+
") t";
PreparedStatement ps = con.prepareStatement(sql);
ps.setArray(1, arr);
//Full prepared statement:
SELECT * FROM table WHERE (a,b) IN
(SELECT
arr[i][1],arr[i][2]
FROM
SELECT generate_series(1, array_upper(arr, 1)) AS i, arr
FROM (SELECT ? AS arr) t
) t)
С 2 массивами A и B (представляющими (a1, a2, a3) и (b1, b2, b3) соответственно), мы можем сделать то же самое, кроме select A [row], B [row]. Пример кода:
Array arr_a = con.createArrayOf("int", new Object[]{1,4,7});
Array arr_b = con.createArrayOf("int", new Object[]{2,5,9});
String sql =
"SELECT A[i],B[i]"+
"FROM ("+
" SELECT generate_series(1, array_upper(A, 1)) AS i, A, B"+
" FROM (SELECT ? AS A, ? AS B) t"+
") t";
PreparedStatement ps = con.prepareStatement(sql);
ps.setArray(1, arr_a);
ps.setArray(2, arr_b);
ps.execute();
ResultSet rs = ps.getResultSet();
while(rs.next()){
System.out.println("Row: " + rs.getInt(1) + " - " + rs.getInt(2));
}
Результатом в этом случае будет:
Row: 1 - 2
Row: 4 - 5
Row: 7 - 9