metaclass: (Default)
metaclass ([personal profile] metaclass) wrote2014-08-09 08:06 pm

SQL 'in' clause

Скажите мне такую вещь: список значений в in выражении в SQL можно вообще передать параметром, хоть в какой-нибудь СУБД?

В Firebird нельзя, ну я как-то не интересовался, как оно в других СУБД, использовал временную табличку и подзапрос с where exists (select 1 from TmpTbl ...) но что-то вот сегодня пришло в голову - а почему собственно нельзя?

[identity profile] tzirechnoy.livejournal.com 2014-08-09 05:11 pm (UTC)(link)
Видимо, потому, что ни у одного API нет варианта подставлять список вместо placeholderа.

[identity profile] cmotruc.livejournal.com 2014-08-09 05:41 pm (UTC)(link)
в оракле можно передать коллекцию:
select * from user_table1 where id in (select * from table(:my_collection))

table(:my_collection) -- это оператор, который коллекцию приводит к таблице

[identity profile] dennab.livejournal.com 2014-08-09 05:44 pm (UTC)(link)
Нэа. Приходицца генерить нное количество вопросов, да.

[identity profile] pit0n.livejournal.com 2014-08-09 06:06 pm (UTC)(link)
в MSSQL передаешь строкой или XML (потом конкатенируешь в строку), конструируешь запрос в строке и делаешь exec sql

[identity profile] vromanov.livejournal.com 2014-08-09 06:17 pm (UTC)(link)
Я делал хранимую процедуру, которая принимала строку а выдавала табличку. Вроде через yeld.

[identity profile] swamp-agr.livejournal.com 2014-08-09 06:32 pm (UTC)(link)
c1 IN (a1, a2, ...)
раскрывается как
c1 = a1 or c1 = a2 or ...

Можно сделать так
c1 = ANY(array)
что в принципе равносильно предыдущей записи с отличием, что в ANY можно передавать списки, массивы.

[identity profile] http://users.livejournal.com/_slw/ 2014-08-09 06:51 pm (UTC)(link)
параметром? в SQL? откуда в SQL параметры?
противогаз покусал?

[identity profile] autoench.livejournal.com 2014-08-09 07:03 pm (UTC)(link)
$stmt = $db->prepare("select id from table where gender in (?, ?, ?, ?)");
$stmt->execute(array("male", "female", "transgender", "developer"));

Увы, да(

[identity profile] anonim-legion.livejournal.com 2014-08-09 07:23 pm (UTC)(link)
Да, можно в постгресе, проверено. Использовались jdbc, java 7.

Запрос: select * from data.street where id_street in (select unnest(?)) где ? является параметром

Сам код:
PreparedStatement selectPs = connection.prepareStatement("select * from data.street where id_street in (select unnest(?))");
Integer[] a = new Integer[]{927,929,930,931,932,933,934,935,936,937};
Array a2 = connection.createArrayOf("int",a);
selectPs.setArray(1,a2);

Используется именно Integer, а не int, потому что требуется ссылочный тип. Значение параметра устанавливается по индексу, потому что это голый JDBC.

Функция unnest разворачивает массив в набор строк (http://www.postgresql.org/docs/9.3/static/functions-array.html)

[identity profile] shaman237.livejournal.com 2014-08-09 07:37 pm (UTC)(link)
В оракле динамическим SQL это решается без проблем

[identity profile] slavae.livejournal.com 2014-08-09 08:07 pm (UTC)(link)
Пора Еманову писать )
Кажется, ещё на ib.demo.ru я возмущался, что нелья делать группировку как и ордер бай - по номерам полей, и они это сделали.

[identity profile] lakedaemon.livejournal.com 2014-08-09 08:43 pm (UTC)(link)
не совсем то, но есть Table-Valued Parameters в хранимках для MSSQL 2008+

[identity profile] veonn.livejournal.com 2014-08-09 08:45 pm (UTC)(link)
В MSSQL делали похожее через кастом типы вроде
CREATE TYPE [dbo].[IdsTableType] AS TABLE (
[Id] INT NULL);
В дот.нете все работает через SqlMetaData и SqlDataRecord, в общем в итоге можно in засунуть в переменную собственного типа.
Только один забавный глюк - т.к. sql сервер строит планы запросов по имени переменных, то внезапно когда в in 2 значения и 10.000 значений - планы одинаковые.
Бороли это буквально таким кодом
var parameterName = name + GetRangePostfix(records.Count);
который по логарифму делает параметру разные имена :)

[identity profile] Дмитрий Васильев (from livejournal.com) 2014-08-09 10:50 pm (UTC)(link)
В постгресе
select * from foo where id = any(?)

В качеестве параметра передавать array

[identity profile] berezovsky.livejournal.com 2014-08-10 07:19 am (UTC)(link)
По-моему, у тебя в вопросе уже содержится в ответ. То есть это будет попытка запихать задачу SQL в его же параметры. Выходит не операция реляционной алгебры, а пони с хуем во лбу.

[identity profile] sbj-ss.livejournal.com 2014-08-10 09:28 pm (UTC)(link)
Можно сджойнить на TVF, разбирающую строку.
В MSSQL у решения есть очевидный недостаток: отсутствие статистики, т.е. в зависимости от объёма данных для "IN" может потребоваться подсказка "INNER MERGE JOIN". По умолчанию явно будет LOOP JOIN.

[identity profile] zmila.livejournal.com 2014-08-11 09:36 am (UTC)(link)
а у нас главная беда тут была: "How to put more than 1000 values into an Oracle IN clause" :)