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

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

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

Date: 2014-08-09 05:16 pm (UTC)
From: [identity profile] metaclass.livejournal.com
Да хотя бы строку сунуть и один раз ее распарсить на список.
Ни у кого нет, хотя фича самоочевидная.

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

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

Date: 2014-08-09 06:07 pm (UTC)
From: [identity profile] brainslugs.blogspot.com (from livejournal.com)
Ага и в постгресе тоже есть такое, там этот оператор unnest() называется

Date: 2014-08-09 07:44 pm (UTC)
From: [identity profile] shaman237.livejournal.com
Разговор об sql, вас понесло в pl/sql

Date: 2014-08-09 07:58 pm (UTC)
From: [identity profile] shaman237.livejournal.com
Хотя и меня ниже туда же дернуло :)

Date: 2014-08-09 09:26 pm (UTC)
From: [identity profile] cmotruc.livejournal.com
любое решение будет расширением sql для соответствующей бд

в примере таки sql, но использующий коллецию pl/sql

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

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

Date: 2014-08-09 06:14 pm (UTC)
From: [identity profile] off roaming (from livejournal.com)
Не надо строк и exec sql. Команду OPENXML ввели в 2005 версии.

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

Date: 2014-08-09 06:19 pm (UTC)
From: [identity profile] jakobz.livejournal.com
Все делали

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

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

Date: 2014-08-09 07:25 pm (UTC)
From: [identity profile] anonim-legion.livejournal.com
>c1 IN (a1, a2, ...) раскрывается как c1 = a1 or c1 = a2 or ...

Это как-то очень уж неэффективно. Вроде нигде оно так не раскрывается.

Date: 2014-08-09 07:46 pm (UTC)
From: [identity profile] shaman237.livejournal.com
Именно так раскрывается, поэтому эффективней делать union all, если в IN несколько значений

Date: 2014-08-09 09:25 pm (UTC)
From: [identity profile] swamp-agr.livejournal.com
Приведите пример того, как по-вашему должна обрабатываться конструкция
IN (a1, a2, ...)

Date: 2014-08-09 09:58 pm (UTC)
From: [identity profile] anonim-legion.livejournal.com
Нужно понять, находится ли элемент в списке IN. Это делается либо через хэш, либо двоичным поиском по отсортированному списку IN. Если же просто сравнивать с каждым элементом, то это очевидно дольше хэша или поиска.

Date: 2014-08-10 11:06 am (UTC)
From: [identity profile] swamp-agr.livejournal.com
Как конкретно это делается через хэш?

Date: 2014-08-10 11:09 am (UTC)
From: [identity profile] anonim-legion.livejournal.com
В СУБД - не знаю. В программе я бы построил по значениям в IN обычную хэш-таблицу, где ключом является хэш от значения, значением - само значение. Если хэш совпал, сравниваем напрямую, если сравнение успешно - значит, есть вхождение.

Date: 2014-08-10 12:42 pm (UTC)
From: [identity profile] swamp-agr.livejournal.com
В Oracle, например, что в IN clause, что в нескольких OR, сравниваются хэши, если колонка проиндексирована. Там IN (a1, a2, ...) эквивалентен OR.

В T-SQL чуть ли не в MSDN пишут об эквивалентности запросов.

В PostgreSQL - точно не помню, но в плане выполнения тоже хэши видел, однако думаю, что конструкции эквивалентны.

А когда `IN (SQL statement)` встречается, то тут тот же принцип с той разницей, что в памяти надо хранить результат его выполнения. И PostgreSQL, и Oracle могут оказаться чувствительны к нему, если он достаточно велик, а в памяти они ограничены.

Date: 2014-08-10 04:15 pm (UTC)
From: [identity profile] e3c9bx.livejournal.com
псих, а что ты тут опять делаешь? иди пей таблеточки.

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

Date: 2014-08-09 07:01 pm (UTC)
From: [identity profile] metaclass.livejournal.com
Всю жизнь там были: sql bind variables

Date: 2014-08-09 07:29 pm (UTC)
From: [identity profile] vp.livejournal.com
>противогаз покусал?

Вы просто так хуйню пишете от жары али заказал такое кто?

Date: 2014-08-10 09:33 am (UTC)
From: [identity profile] nivanych.livejournal.com
Ну слава богу.
Теперь знаю хоть одну точную, достоверную деталь — противогаз не кусается.

Date: 2014-08-10 10:22 am (UTC)
From: [identity profile] berezovsky.livejournal.com
прирос?

Date: 2014-08-10 03:09 pm (UTC)
From: [identity profile] yantayga.livejournal.com
Он засасывает

Date: 2014-08-10 03:30 pm (UTC)
From: [identity profile] nivanych.livejournal.com
(Испуганно) Насмерть!?

Date: 2014-08-10 04:14 pm (UTC)
From: [identity profile] e3c9bx.livejournal.com
ты плохой человек. старайся быть добрее.

Date: 2014-08-10 02:07 pm (UTC)
From: [identity profile] denis dmitriev (from livejournal.com)
Фигасе, вы же интеллигентный человек. У себя в журнале, вона, не ругаетесь :)
Интеллигентные люди используют эвфемизм who knew.

Date: 2014-08-10 04:21 pm (UTC)
From: [identity profile] nivanych.livejournal.com
> У себя в журнале, вона, не ругаетесь :)
На него нашло что-то русское.

Date: 2014-08-10 04:32 pm (UTC)
From: [identity profile] berezovsky.livejournal.com
Или китайское.

Date: 2014-08-10 04:50 pm (UTC)
From: [identity profile] nivanych.livejournal.com
;-) Вы показываете какую-то хуйню!

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

Увы, да(

Date: 2014-08-09 07:23 pm (UTC)
From: [identity profile] anonim-legion.livejournal.com
Да, можно в постгресе, проверено. Использовались 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)

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

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

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

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

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

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

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

Date: 2014-08-10 04:13 pm (UTC)
From: [identity profile] e3c9bx.livejournal.com
Березофсский, а все-таки чем твои родетели болели в момент твоего зачания?
ты зря отмалчиваешься.

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

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

Profile

metaclass: (Default)
metaclass

April 2017

S M T W T F S
      1
2345678
9101112 131415
16171819202122
23242526272829
30      

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Aug. 19th, 2025 03:02 pm
Powered by Dreamwidth Studios