Как я могу получить SQL PreparedStatement?

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

#\A(?:(?:(?:(?:0?[13578])|(1[02]))/31/(19|20)?\d\d)|(?:(?:(?:0?[13-9])|(?:1[0-2]))/(?:29|30)/(?:19|20)?\d\d)|(?:0?2/29/(?:19|20)(?:(?:[02468][048])|(?:[13579][26])))|(?:(?:(?:0?[1-9])|(?:1[0-2]))/(?:(?:0?[1-9])|(?:1\d)|(?:2[0-8]))/(?:19|20)?\d\d))\Z#

Объяснение:

\A           # start of string
 (?:         # group without capture
             # that match 31st of month 1,3,5,7,8,10,12
   (?:       # group without capture
     (?:     # group without capture
       (?:   # group without capture
         0?  # number 0 optionnal
         [13578] # one digit either 1,3,5,7 or 8
       )     # end group
       |     # alternative
       (1[02]) # 1 followed by 0 or 2
     )       # end group
     /       # slash
     31      # number 31
     /       # slash
     (19|20)? #numbers 19 or 20 optionnal
     \d\d    # 2 digits from 00 to 99 
   )         # end group
|
   (?:(?:(?:0?[13-9])|(?:1[0-2]))/(?:29|30)/(?:19|20)?\d\d)
|
   (?:0?2/29/(?:19|20)(?:(?:[02468][048])|(?:[13579][26])))
|
   (?:(?:(?:0?[1-9])|(?:1[0-2]))/(?:(?:0?[1-9])|(?:1\d)|(?:2[0-8]))/(?:19|20)?\d\d)
 )
\Z

Я объяснил первую часть, оставив остальное как упражнение.

Это соответствует одной недействительной дате: 02/29/1900, но подходит для любых других дат между 01/01/1900 и 12/31/2099

141
задан BalusC 4 March 2010 в 20:53
поделиться

4 ответа

Используя подготовленные операторы, нет «запроса SQL»:

  • У вас есть оператор, содержащий заполнители
    • он отправляется на сервер БД
    • и готовится там
    • , что означает, что оператор SQL «анализируется», анализируется, некоторая структура данных, представляющая его, подготавливается в памяти
  • И затем у вас есть связанные переменные
    • , которые отправляются на сервер
    • , и подготовленный оператор выполняется - работа с этими данными

Но нет никакого воссоздания реального реального SQL-запрос - ни на стороне Java, ни на стороне базы данных.

Таким образом, получить SQL подготовленного оператора невозможно - такого SQL нет.


Для целей отладки решения следующие:

  • Вывести код оператора с заполнителями и списком данных
  • Или «создать» некоторый SQL-запрос «вручную».
164
ответ дан 23 November 2019 в 22:26
поделиться

Для этого вам потребуется соединение JDBC и / или драйвер, который поддерживает ведение журнала sql на низком уровне.

Взгляните на log4jdbc

-4
ответ дан 23 November 2019 в 22:26
поделиться

Если вы используете MySQL, вы можете регистрировать запросы с помощью MySQL's query log. Я не знаю, предоставляют ли другие производители такую возможность, но есть вероятность, что да.

0
ответ дан 23 November 2019 в 22:26
поделиться

Это нигде не определено в контракте JDBC API, но если вам повезет, то данный JDBC драйвер может вернуть полный SQL, просто вызвав PreparedStatement#toString(). Т.е.

System.out.println(preparedStatement);

По крайней мере, драйверы MySQL 5.x и PostgreSQL 8.x JDBC поддерживают это. Однако большинство других JDBC драйверов не поддерживают его. Если у вас есть такой, то лучшим вариантом будет использование Log4jdbc или P6Spy.

В качестве альтернативы можно также написать общую функцию, которая принимает Connection, строку SQL и значения оператора и возвращает PreparedStatement после регистрации строки SQL и значений. Начальный пример:

public static PreparedStatement prepareStatement(Connection connection, String sql, Object... values) throws SQLException {
    PreparedStatement preparedStatement = connection.prepareStatement(sql);
    for (int i = 0; i < values.length; i++) {
        preparedStatement.setObject(i + 1, values[i]);
    }
    logger.debug(sql + " " + Arrays.asList(values));
    return preparedStatement;
}

и использовать его как

try {
    connection = database.getConnection();
    preparedStatement = prepareStatement(connection, SQL, values);
    resultSet = preparedStatement.executeQuery();
    // ...

Другой альтернативой является реализация пользовательского PreparedStatement, который обертывает (декорирует) real PreparedStatement при построении и переопределяет все методы так, чтобы он вызывал методы real PreparedStatement и собирает значения во всех методах setXXX() и лениво строит "фактическую" строку SQL каждый раз, когда вызывается один из методов executeXXX() (довольно сложная работа, но большинство IDE предоставляют автогенераторы для методов декораторов, Eclipse тоже). Наконец, просто используйте его вместо этого. Это также практически то, что P6Spy и консоль уже делают под капотом.

54
ответ дан 23 November 2019 в 22:26
поделиться
Другие вопросы по тегам:

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