Выполнение Oracle Query со списком элементов в строке [duplicate]

В терминалах, совместимых с Xterm, вы можете показать изображение непосредственно в терминале. [D0]

ImageMagick's "logo:" image in Xterm (show picture in new tab for full size viewing) [!d1]

см. [D0] мой ответ на «Изображение PPM для ASCII-искусства в Python»
299
задан Jonas 30 August 2011 в 19:54
поделиться

27 ответов

Здесь доступны различные доступные варианты, а также плюсы и минусы каждого из них здесь .

Предлагаемые варианты:

  • Подготовьте SELECT my_column FROM my_table WHERE search_column = ?, выполните его для каждого значения, а UNION - на стороне клиента. Требуется только одно подготовленное заявление. Медленный и болезненный.
  • Подготовьте SELECT my_column FROM my_table WHERE search_column IN (?,?,?) и выполните его. Требуется один подготовленный оператор в размере IN-списка. Быстро и очевидно.
  • Подготовьте SELECT my_column FROM my_table WHERE search_column = ? ; SELECT my_column FROM my_table WHERE search_column = ? ; ... и выполните его. [Или используйте UNION ALL вместо этих точек с запятой. --ed] Требуется один подготовленный оператор в размере IN-списка. Глубоко медленно, строго хуже, чем WHERE search_column IN (?,?,?), поэтому я не знаю, почему блоггер даже предложил его.
  • Используйте хранимую процедуру для построения набора результатов.
  • Подготовьте N разных запрос размера списка IN-list; скажем, с 2, 10 и 50 значениями. Чтобы выполнить поиск IN-list с 6 различными значениями, введите запрос размера-10, чтобы он выглядел как SELECT my_column FROM my_table WHERE search_column IN (1,2,3,4,5,6,6,6,6,6). Любой достойный сервер будет оптимизировать повторяющиеся значения перед запуском запроса.

Однако ни один из этих параметров не супер.

В этих местах ответили на дублирующие вопросы с одинаково разумными альтернативами, все еще ни один из них не супер:

Правильный ответ, если вы используете JDBC4 и сервер, который поддерживает x = ANY(y), должен использовать PreparedStatement.setArray, как описано здесь :

Кажется, что нет способа заставить setArray работать с IN-lists.

164
ответ дан Community 16 August 2018 в 01:23
поделиться
  • 1
    Прошлое доступно только для чтения;) – Vladimir Dyuzhev 13 February 2014 в 03:35
  • 2
    Это хороший анализ теоретических обходных путей, чтобы не переходить в список. Тем не менее, некоторые базы данных позволяют вам переходить в список, и лучший ответ показывает, как это сделать, например, ответ Бориса. – Brandon 11 July 2014 в 00:18
3
ответ дан Adam Bellaire 16 August 2018 в 01:23
поделиться

Я столкнулся с рядом ограничений, связанных с подготовленным оператором:

  1. Подготовленные операторы кэшируются только внутри одного сеанса (Postgres), поэтому он действительно будет работать только с пулом соединений
  2. Множество разных подготовленных операторов, предложенных @BalusC, может привести к переполнению кеша, а ранее кэшированные операторы будут удалены
  3. Запрос должен быть оптимизирован и использовать индексы. Звучит очевидно, однако, например, заявление ANY (ARRAY ...), предложенное @Boris в одном из лучших ответов, не может использовать индексы, и запрос будет медленным, несмотря на кеширование
  4. . Подготовленный оператор также кэширует план запроса, а фактические значения любые параметры, указанные в инструкции, недоступны.

Среди предлагаемых решений я бы выбрал тот, который не уменьшает производительность запроса и уменьшает количество запросов. Это будет # 4 (партия нескольких запросов) из ссылки @Don или указание значений NULL для ненужных '?' знаки, предложенные В.Дужевым

1
ответ дан Alexander 16 August 2018 в 01:23
поделиться

Изучив различные решения на разных форумах и не найдя подходящего решения, я чувствую, что я получил нижний взломанный код, который проще всего отслеживать и кодировать:

Пример. Предположим, у вас есть несколько параметров для перейдите в предложение «IN». Просто поместите фиктивную строку в предложение «IN», скажем, «PARAM» обозначить список параметров, которые будут появляться на месте этой фиктивной строки.

    select * from TABLE_A where ATTR IN (PARAM);

Вы можете собрать все параметров в одну переменную String в вашем Java-коде. Это можно сделать следующим образом:

    String param1 = "X";
    String param2 = "Y";
    String param1 = param1.append(",").append(param2);

Вы можете добавить все ваши параметры, разделенные запятыми, в одну переменную String, 'param1', в нашем случае.

После сбора всех параметры в одну строку вы можете просто заменить фиктивный текст в вашем запросе, то есть «PARAM» в этом случае, с параметром String, т. е. param1. Вот что вам нужно сделать:

    String query = query.replaceFirst("PARAM",param1); where we have the value of query as 

    query = "select * from TABLE_A where ATTR IN (PARAM)";

Теперь вы можете выполнить свой запрос с помощью метода executeQuery (). Просто убедитесь, что в вашем запросе нет слова «PARAM». Вы можете использовать комбинацию специальных символов и алфавитов вместо слова «PARAM», чтобы убедиться, что в запросе нет такого слова. Надеюсь, вы получили решение.

Примечание. Хотя это не подготовленный запрос, он выполняет работу, которую я хотел, чтобы мой код выполнял.

0
ответ дан bnsk 16 August 2018 в 01:23
поделиться
105
ответ дан Boris 16 August 2018 в 01:23
поделиться

Просто для полноты: пока набор значений не слишком велик, вы могли бы также просто построить строку с выражением, подобным

... WHERE tab.col = ? OR tab.col = ? OR tab.col = ?

, который вы могли бы затем перейти к prepare (), а затем использовать setXXX () в цикле для установки всех значений. Это выглядит yucky, но многие «большие» коммерческие системы обычно делают такие вещи до тех пор, пока они не достигнут ограничений, специфичных для БД, таких как 32 КБ (я думаю, это так) для операторов в Oracle.

Конечно, вы необходимо убедиться в том, что набор никогда не будет необоснованно большим или будет захват ошибок в том случае, если это будет.

0
ответ дан Carl Smotricz 16 August 2018 в 01:23
поделиться
  • 1
    Да, ты прав. Моя цель в этом случае состояла в том, чтобы повторно использовать PreparedStatement с различным количеством элементов каждый раз. – Chris Mazzola 9 October 2008 в 17:24
  • 2
    Использование "ИЛИ" будет запутывать намерение. Stick с "IN & quot; так как его легче читать, а намерение более ясное. Единственная причина для переключения - если планы запросов были разными. – James Schek 9 October 2008 в 22:41

Вот полное решение в Java для создания подготовленного оператора для вас:

/*usage:

Util u = new Util(500); //500 items per bracket. 
String sqlBefore  = "select * from myTable where (";
List<Integer> values = new ArrayList<Integer>(Arrays.asList(1,2,4,5)); 
string sqlAfter = ") and foo = 'bar'"; 

PreparedStatement ps = u.prepareStatements(sqlBefore, values, sqlAfter, connection, "someId");
*/



import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class Util {

    private int numValuesInClause;

    public Util(int numValuesInClause) {
        super();
        this.numValuesInClause = numValuesInClause;
    }

    public int getNumValuesInClause() {
        return numValuesInClause;
    }

    public void setNumValuesInClause(int numValuesInClause) {
        this.numValuesInClause = numValuesInClause;
    }

    /** Split a given list into a list of lists for the given size of numValuesInClause*/
    public List<List<Integer>> splitList(
            List<Integer> values) {


        List<List<Integer>> newList = new ArrayList<List<Integer>>(); 
        while (values.size() > numValuesInClause) {
            List<Integer> sublist = values.subList(0,numValuesInClause);
            List<Integer> values2 = values.subList(numValuesInClause, values.size());   
            values = values2; 

            newList.add( sublist);
        }
        newList.add(values);

        return newList;
    }

    /**
     * Generates a series of split out in clause statements. 
     * @param sqlBefore ""select * from dual where ("
     * @param values [1,2,3,4,5,6,7,8,9,10]
     * @param "sqlAfter ) and id = 5"
     * @return "select * from dual where (id in (1,2,3) or id in (4,5,6) or id in (7,8,9) or id in (10)"
     */
    public String genInClauseSql(String sqlBefore, List<Integer> values,
            String sqlAfter, String identifier) 
    {
        List<List<Integer>> newLists = splitList(values);
        String stmt = sqlBefore;

        /* now generate the in clause for each list */
        int j = 0; /* keep track of list:newLists index */
        for (List<Integer> list : newLists) {
            stmt = stmt + identifier +" in (";
            StringBuilder innerBuilder = new StringBuilder();

            for (int i = 0; i < list.size(); i++) {
                innerBuilder.append("?,");
            }



            String inClause = innerBuilder.deleteCharAt(
                    innerBuilder.length() - 1).toString();

            stmt = stmt + inClause;
            stmt = stmt + ")";


            if (++j < newLists.size()) {
                stmt = stmt + " OR ";
            }

        }

        stmt = stmt + sqlAfter;
        return stmt;
    }

    /**
     * Method to convert your SQL and a list of ID into a safe prepared
     * statements
     * 
     * @throws SQLException
     */
    public PreparedStatement prepareStatements(String sqlBefore,
            ArrayList<Integer> values, String sqlAfter, Connection c, String identifier)
            throws SQLException {

        /* First split our potentially big list into lots of lists */
        String stmt = genInClauseSql(sqlBefore, values, sqlAfter, identifier);
        PreparedStatement ps = c.prepareStatement(stmt);

        int i = 1;
        for (int val : values)
        {

            ps.setInt(i++, val);

        }
        return ps;

    }

}
1
ответ дан dwjohnston 16 August 2018 в 01:23
поделиться

Просто для полноты и потому, что я не видел, чтобы кто-либо еще предлагал это:

Перед тем, как применить какие-либо сложные предложения, рассмотрите вопрос о том, действительно ли SQL-инъекция является проблемой в вашем сценарии.

Во многих случаях значение, предоставляемое IN (...), представляет собой список идентификаторов, которые были сгенерированы таким образом, что вы можете быть уверены, что инъекция невозможна ... (например, результаты предыдущий select some_id from some_table, где some_condition.)

Если это так, вы можете просто связать это значение и не использовать службы или подготовленный оператор для него или использовать их для других параметров этого запроса.

query="select f1,f2 from t1 where f3=? and f2 in (" + sListOfIds + ");";
0
ответ дан epeleg 16 August 2018 в 01:23
поделиться

Ограничения оператора in () являются корнем всего зла.

Он работает для тривиальных случаев, и вы можете расширить его с помощью «автоматической генерации подготовленного заявления», однако он всегда имеет свои пределов.

  • , если вы создаете оператор с переменным числом параметров, который будет обрабатывать служебные данные SQL для каждого вызова
  • на многих платформах, количество параметров of () ограничены
  • на всех платформах, общий размер текста SQL ограничен, что делает невозможным отправку 2000 заполнителей для параметров in
  • , отправляющих переменные связывания 1000- 10k невозможно, так как драйвер JDBC имеет свои ограничения

Подход in () может быть достаточно хорош для некоторых случаев, но не для защиты от ракеты:)

Ракетно-защитное решение состоит в том, чтобы передать произвольное количество параметров в отдельный вызов (например, путем передачи клока параметров), а затем иметь представление (или любой другой способ) для представления их в SQL и использовать в вашем месте критерии.

Вариант грубой силы здесь http://tkyte.blogspot.hu/2006/06/varying-in-lists.html

Однако, если вы можете использовать PL / SQL, этот беспорядок может стать довольно опрятным.

function getCustomers(in_customerIdList clob) return sys_refcursor is 
begin
    aux_in_list.parse(in_customerIdList);
    open res for
        select * 
        from   customer c,
               in_list v
        where  c.customer_id=v.token;
    return res;
end;

Затем вы можете передать произвольное количество идентификаторов клиентов, разделенных запятыми, в параметре и:

  • не будет получать задержку синтаксического анализа, так как SQL для select является стабильным
  • Отсутствие сложностей с конвейерными функциями - это всего лишь один запрос
  • , когда SQL использует простое соединение, вместо этого из оператора IN, который довольно быстр
  • в конце концов, это хорошее эмпирическое правило not , попадающее в базу данных с любым простым выбором или DML, поскольку это Oracle, который предлагает lightyears больше, чем MySQL или аналогичные простые двигатели баз данных. PL / SQL позволяет скрыть модель хранилища от вашей модели домена приложения эффективным способом.

Трюк здесь:

  • нам нужен звонок который принимает длинную строку и хранит где-нибудь, где сеанс db может получить к ней доступ (например, простая переменная пакета или dbms_session.set_context)
  • , тогда нам нужно представление, которое может анализировать это на строки
  • , а затем у вас есть представление, которое содержит идентификаторы, которые вы запрашиваете, поэтому все, что вам нужно, - это простое соединение с запрошенной таблицей.

Вид выглядит так:

create or replace view in_list
as
select
    trim( substr (txt,
          instr (txt, ',', 1, level  ) + 1,
          instr (txt, ',', 1, level+1)
             - instr (txt, ',', 1, level) -1 ) ) as token
    from (select ','||aux_in_list.getpayload||',' txt from dual)
connect by level <= length(aux_in_list.getpayload)-length(replace(aux_in_list.getpayload,',',''))+1

, где aux_in_list.getpayload ссылается на исходную строку ввода.


Возможным подходом было бы передать массивы pl / sql (поддерживаемые только Oracle), однако вы можете ' t использовать их в чистом SQL, поэтому шаг преобразования всегда необходим. Преобразование не может быть выполнено в SQL, поэтому, в конце концов, самым эффективным решением является передача clob со всеми параметрами в строке и преобразование его в представление.

7
ответ дан Gee Bee 16 August 2018 в 01:23
поделиться
0
ответ дан GurV 16 August 2018 в 01:23
поделиться

Spring позволяет передавать java.util.Lists в NamedParameterJdbcTemplate , который автоматизирует генерацию (?,?,?, ...,?), в зависимости от количества аргументов.

Для Oracle в этом блоге сообщение обсуждается использование oracle.sql.ARRAY (Connection.createArrayOf не работает с Oracle). Для этого вам нужно изменить инструкцию SQL:

SELECT my_column FROM my_table where search_column IN (select COLUMN_VALUE from table(?))

Функция таблицы oracle table преобразует переданный массив в таблицу как значение, которое можно использовать в инструкции IN.

1
ответ дан Hans-Peter Störr 16 August 2018 в 01:23
поделиться

Неприятный обход, но, безусловно, возможно использовать вложенный запрос. Создайте временную таблицу MYVALUES со столбцом в ней. Вставьте свой список значений в таблицу MYVALUES. Затем выполните

select my_column from my_table where search_column in ( SELECT value FROM MYVALUES )

Ужасно, но жизнеспособной альтернативой, если ваш список значений очень велик.

Этот метод имеет дополнительное преимущество потенциально лучших планов запросов от оптимизатора (проверьте страница для нескольких значений, таблицы могут быть только один раз вместо одного значения и т. д.) могут сэкономить накладные расходы, если ваша база данных не кэширует подготовленные операторы. Ваши «INSERTS» должны выполняться в пакетном режиме, и таблица MYVALUES может потребоваться изменить, чтобы иметь минимальную блокировку или другие высоконадежные защиты.

10
ответ дан James Schek 16 August 2018 в 01:23
поделиться
  • 1
    Какие преимущества у вас будут за счет запроса my_table за одно значение за раз? – Paul Tomblin 9 October 2008 в 18:43
  • 2
    Оптимизатор запросов может уменьшить нагрузку ввода-вывода, извлекая все возможные совпадения с загруженной страницы. Таблицы или сканирование индексов могут выполняться один раз вместо одного значения. Накладные расходы для вставки значений могут быть уменьшены с помощью пакетных операций и могут быть меньше нескольких запросов. – James Schek 9 October 2008 в 22:34
  • 3
    – David Portabella 4 June 2012 в 12:31

Мое обходное решение:

create or replace type split_tbl as table of varchar(32767);
/

create or replace function split
(
  p_list varchar2,
  p_del varchar2 := ','
) return split_tbl pipelined
is
  l_idx    pls_integer;
  l_list    varchar2(32767) := p_list;
  l_value    varchar2(32767);
begin
  loop
    l_idx := instr(l_list,p_del);
    if l_idx > 0 then
      pipe row(substr(l_list,1,l_idx-1));
      l_list := substr(l_list,l_idx+length(p_del));
    else
      pipe row(l_list);
      exit;
    end if;
  end loop;
  return;
end split;
/

Теперь вы можете использовать одну переменную для получения некоторых значений в таблице:

select * from table(split('one,two,three'))
  one
  two
  three

select * from TABLE1 where COL1 in (select * from table(split('value1,value2')))
  value1 AAA
  value2 BBB

Итак, подготовленный оператор может быть:

  "select * from TABLE where COL in (select * from table(split(?)))"

С уважением,

Хавьер Ибанез

5
ответ дан Javier Ibanez 16 August 2018 в 01:23
поделиться
  • 1
    это Oracle PLSQL? или он работает для других баз данных? – David Portabella 4 June 2012 в 10:54
  • 2
    Это PL / SQL, да. Он не работает в других базах данных. Обратите внимание, что эта реализация имеет ограничение входных параметров - общая длина ограничена 32 тыс. Символов, а также ограничение производительности, поскольку вызов конвейерной функции делает переключение контекста между PL / SQL и SQL-системами Oracle. – Gee Bee 6 February 2018 в 20:40

Sormula поддерживает оператор SQL IN, позволяя вам предоставить объект java.util.Collection в качестве параметра. Он создает подготовленное заявление с? для каждого из элементов коллекции. См. Пример 4 (SQL в примере - комментарий, чтобы уточнить, что создано, но не используется Sormula).

1
ответ дан Jeff Miller 16 August 2018 в 01:23
поделиться

вместо использования

SELECT my_column FROM my_table where search_column IN (?)

использовать Sql Statement как

select id, name from users where id in (?, ?, ?)

и

preparedStatement.setString( 1, 'A');
preparedStatement.setString( 2,'B');
preparedStatement.setString( 3, 'C');

или использовать хранимую процедуру, это было бы лучшее решение, так как операторы sql будут скомпилированы и сохранены на сервере DataBase

1
ответ дан kapil das 16 August 2018 в 01:23
поделиться

Вот как я решил это в своем приложении. В идеале вы должны использовать StringBuilder вместо использования + для строк.

    String inParenthesis = "(?";
    for(int i = 1;i < myList.size();i++) {
      inParenthesis += ", ?";
    }
    inParenthesis += ")";

    try(PreparedStatement statement = SQLite.connection.prepareStatement(
        String.format("UPDATE table SET value='WINNER' WHERE startTime=? AND name=? AND traderIdx=? AND someValue IN %s", inParenthesis))) {
      int x = 1;
      statement.setLong(x++, race.startTime);
      statement.setString(x++, race.name);
      statement.setInt(x++, traderIdx);

      for(String str : race.betFair.winners) {
        statement.setString(x++, str);
      }

      int effected = statement.executeUpdate();
    }

Использование переменной типа x выше вместо конкретных чисел помогает много, если вы решите изменить запрос позже.

5
ответ дан m.sabouri 16 August 2018 в 01:23
поделиться
0
ответ дан neu242 16 August 2018 в 01:23
поделиться

Существуют различные альтернативные подходы, которые мы можем использовать для предложения IN в PreparedStatement.

  1. Использование одиночных запросов - самая медленная производительность и ресурсоемкость
  2. Использование StoredProcedure - самая быстрая, но база данных специфический
  3. Создание динамического запроса для PreparedStatement - Хорошая производительность, но не получает преимущества кэширования, и PreparedStatement перекомпилируется каждый раз.
  4. Использовать NULL в запросах PreparedStatement - Оптимальная производительность, отлично работает, когда вы знаете предел аргументов предложения IN. Если ограничений нет, вы можете выполнять запросы в пакетном режиме. Пример фрагмента кода;
        int i = 1;
        for(; i <=ids.length; i++){
            ps.setInt(i, ids[i-1]);
        }
    
        //set null for remaining ones
        for(; i<=PARAM_SIZE;i++){
            ps.setNull(i, java.sql.Types.INTEGER);
        }
    

Здесь вы можете узнать подробнее об этих альтернативных подходах здесь .

0
ответ дан Pankaj 16 August 2018 в 01:23
поделиться
  • 1
    «Создание динамического запроса для PreparedStatement - хорошая производительность, но не получает преимущества кэширования, и PreparedStatement перекомпилируется каждый раз. & quot; кэширование и исключение перекомпиляции - это то, что делает подготовленный отчет хорошо выполненным. Поэтому я не согласен с вашим заявлением. Это, однако, предотвратит внедрение SQL, поскольку вы ограничиваете конкатенированный / динамический ввод запятой. – Brandon 11 July 2014 в 00:36
  • 2
    Я согласен с вами, однако «Хорошая производительность». здесь для этого конкретного сценария. Это лучше, чем подход 1, однако подход 2 является самым быстрым. – Pankaj 11 July 2014 в 08:12

Я никогда не пробовал, но будет ли .setArray () делать то, что вы ищете?

Обновление: очевидно, нет. Кажется, что setArray работает с java.sql.Array, который исходит из столбца ARRAY, который вы извлекли из предыдущего запроса, или подзапроса с столбцом ARRAY.

5
ответ дан Paul Tomblin 16 August 2018 в 01:23
поделиться
  • 1
    Не работает со всеми базами данных, но это «правильно». подход. – skaffman 7 October 2008 в 14:48
  • 2
    Вы имеете в виду всех водителей. Некоторые драйверы имеют проприетарные эквиваленты этого года (последний век?). Еще один способ - выгрузить пакет значений во временную таблицу, но не все базы данных поддерживают это ... – Tom Hawtin - tackline 7 October 2008 в 15:06
  • 3
    java.sun.com/j2se/1.3/docs/guide/jdbc/getstart/… Согласно Sun, содержимое массива [обычно] остается на стороне сервера и при необходимости потянуто. PreparedStatement.setArray () может отправить обратно массив из предыдущего ResultSet, а не создавать новый массив на стороне клиента. – Chris Mazzola 9 October 2008 в 17:21

PreparedStatement не предоставляет никакого хорошего способа работы с предложением SQL IN. Per http://www.javaranch.com/journal/2005/Journal200510.jsp#a2 «Вы не можете заменить вещи, которые должны стать частью инструкции SQL. Это необходимо, потому что если сам SQL может измениться, драйвер не может предварительно скомпилировать оператор, а также имеет хороший побочный эффект предотвращения атак SQL-инъекций ». В итоге я использовал следующий подход:

String query = "SELECT my_column FROM my_table where search_column IN ($searchColumns)";
query = query.replace("$searchColumns", "'A', 'B', 'C'");
Statement stmt = connection.createStatement();
boolean hasResults = stmt.execute(query);
do {
    if (hasResults)
        return stmt.getResultSet();

    hasResults = stmt.getMoreResults();

} while (hasResults || stmt.getUpdateCount() != -1);
0
ответ дан pedram bashiri 16 August 2018 в 01:23
поделиться

SetArray - лучшее решение, но оно недоступно для многих старых драйверов. Следующий способ обхода может быть использован в java8

String baseQuery ="SELECT my_column FROM my_table where search_column IN (%s)"

String markersString = inputArray.stream().map(e -> "?").collect(joining(","));
String sqlQuery = String.format(baseSQL, markersString);

//Now create Prepared Statement and use loop to Set entries
int index=1;

for (String input : inputArray) {
     preparedStatement.setString(index++, input);
}

. Это решение лучше, чем другие уродливые решения для цикла, где строка запроса построена с помощью ручных итераций

0
ответ дан Raheel 16 August 2018 в 01:23
поделиться

Мое обходное решение (JavaScript)

    var s1 = " SELECT "

 + "FROM   table t "

 + "  where t.field in ";

  var s3 = '(';

  for(var i =0;i<searchTerms.length;i++)
  {
    if(i+1 == searchTerms.length)
    {
     s3  = s3+'?)';
    }
    else
    {
        s3  = s3+'?, ' ;
    }
   }
    var query = s1+s3;

    var pstmt = connection.prepareStatement(query);

     for(var i =0;i<searchTerms.length;i++)
    {
        pstmt.setString(i+1, searchTerms[i]);
    }

SearchTerms - это массив, который содержит ваши входные / ключи / поля и т. д.

-1
ответ дан smooth_smoothie 16 August 2018 в 01:23
поделиться

попробуйте использовать функцию instr?

select my_column from my_table where  instr(?, ','||search_column||',') > 0

, тогда

ps.setString(1, ",A,B,C,"); 

По общему признанию, это немного грязный взлома, но это уменьшает возможности для SQL-инъекции. Все равно работает в oracle.

1
ответ дан stjohnroe 16 August 2018 в 01:23
поделиться
  • 1
    – stjohnroe 7 October 2008 в 17:07
  • 2
    он не будет работать для некоторых строк, например, если строка содержит символ «,». – David Portabella 4 June 2012 в 12:34

Следуя идее Адама. Сделайте свой подготовленный оператор вроде select my_column из my_table, где search_column in (#) Создайте строку x и заполните ее числом «?,?,?» в зависимости от вашего списка значений. Затем просто измените # в запросе на новую строку String x наполнитель

0
ответ дан user 16 August 2018 в 01:23
поделиться

В некоторых ситуациях regexp может помочь. Вот пример, который я проверил в Oracle, и он работает.

select * from my_table where REGEXP_LIKE (search_column, 'value1|value2')

Но с ним существует ряд недостатков:

  1. Любой использованный столбец должен быть преобразован в varchar / char, по крайней мере, неявно.
  2. Нужно быть осторожным со специальными символами.
  3. Это может замедлить производительность - в моем случае версия IN использует сканирование индекса и диапазона, а версия REGEXP выполняет полное сканирование.
0
ответ дан Vasili 16 August 2018 в 01:23
поделиться
18
ответ дан Vladimir Dyuzhev 16 August 2018 в 01:23
поделиться
2
ответ дан Xaerxess 16 August 2018 в 01:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: