Как вы пишете SQL для PreparedStatement, используя предложение WHERE x IN? - PullRequest
3 голосов
/ 08 декабря 2010

У меня есть запрос, который выглядит так:

SELECT last_name,
       first_name,
       middle_initial
FROM   names
WHERE  last_name IN ('smith', 'jones', 'brown')

Мне нужно иметь возможность параметризовать список в предложении IN, чтобы записать его как JDBC PreparedStatement. Этот список может содержать любое количество имен.

Это правильный способ сделать это:

SELECT last_name,
       first_name,
       middle_initial
FROM   names
WHERE  last_name IN (?)

а потом построить список параметров? Или есть лучший (более правильный) способ сделать это?

Ответы [ 5 ]

2 голосов
/ 08 декабря 2010

Короче говоря, вы не можете из коробки. Однако с Spring вы можете делать то, что хотите. См. Как создать динамический список "in (...)" через Spring JdbcTemplate?

0 голосов
/ 08 декабря 2010

Если вы используете MS SQL Server, попробуйте изменить свой TSQL, чтобы использовать UDF, возможно этот мой пост может помочь вам

0 голосов
/ 08 декабря 2010

Вы также можете создать свой запрос как хранимую процедуру, которая принимает параметризованный список как varchar. Например, на сервере sql:

  CREATE PROCEDURE dbo.[procedure_name]

        @IN_LIST VARCHAR(MAX)
    AS
    BEGIN

        DECLARE @SQL VARCHAR(MAX)
        SET @SQL = '
            SELECT last_name,
                first_name,
                middle_initial
            FROM names
            WHERE  last_name IN (' + @IN_LIST + ')'

        EXECUTE(@SQL)
    END

Просто убедитесь, что ваш @IN_LIST отформатирован как строка, включающая одинарные кавычки и запятые. Например в Java:

String inList = "'smith','jones','brown'";
0 голосов
/ 08 декабря 2010

Я тоже собираюсь исследовать эту тему. Я был виновен в написании подобного кода и никогда не чувствовал себя на 100% комфортно с ним. Я полагаю, я хотел бы найти что-то в «списках переменных параметров SQL».

В коде, используя hibernate и заданную строку идентификаторов порядка, разделенного запятыми, я использовал:

Session s = getSession();
Criteria crit = s.createCriteria(this.getOrderListingClass());
crit.add(Expression.sql(String.format("{alias}.orderId in (%s)", orderIds)));
crit.add(Expression.eq("status", OrderInfo.Order_STATUS_UNFILLED));
orders = crit.list();

В то время как orderId действительно является частью «SELECT x From y WHERE IN (% s)».

  1. Я пропустил строку orderIds String через валидатор, прежде чем передать его в спящий режим - боясь инъекций и т. Д.

  2. Что-то еще, что я хотел сделать, это проверить ограничение на параметры SQL и количество символов в запросе. Кажется, я вспоминаю о достижении лимита где-то около 2000+ (с MS SQL). Это то, что нужно учитывать, если вы идете с этим подходом.

Я думаю, что это глупо ... выдавать столько идентификаторов в предложении Where, но это часть кода, требующая рефакторинга. К счастью, в этом случае за один раз было запрошено всего несколько идентификаторов.

0 голосов
/ 08 декабря 2010

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

...