Я создаю метод обновления строки в базе данных SQL Server 2008. SQL String выглядит примерно так:

private static final String UPDATE_ROW = 
    "UPDATE MyTable SET FieldOne = ?, FieldTwo = ? " +
    "WHERE IDField = ?";

Конечно, упрощенно. Но проблема в том, что не все поля обязательно изменятся. Я знаю, что с прямым SQL вы можете просто указать имя поля вместо значения, и ничего не изменится; однако я не знаю, как это сделать с помощью Java PreparedStatement.

Я мог бы обойти это, вызвав одно обновление для каждого поля, которое нужно изменить (их до десяти) для каждой строки, но это просто бессмысленно, и мне бы очень хотелось этого избежать. Может ли кто-нибудь сказать мне, как указать имя поля в качестве значения параметра или, по крайней мере, дать мне чистое решение?

2
iandisme 29 Авг 2011 в 22:59

3 ответа

Лучший ответ

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

1
iandisme 10 Сен 2011 в 18:46

Будет намного эффективнее, если вы создадите специализированные операторы UPDATE, которые только указывают столбцы, которые были изменены.

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

Это произойдет, даже если вы укажете UPDATE foo SET bar = bar, если я не ошибаюсь. Я не думаю, что SQL Server оптимизирует такие обновления.

0
a_horse_with_no_name 29 Авг 2011 в 20:39

Хорошо, что вы пытаетесь избежать создания специального оператора для каждого обновления.

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

Если они действительно совершенно не связаны друг с другом, сделайте серию обновлений одновременно.

Обычно один оказывается где-то посередине - есть кластеры взаимосвязанных полей. Например, запись Person, содержащая несколько полей, связанных с BillingAddress. В таких случаях подготовьте отчет для каждой группы связанных полей.

Если вы пытаетесь избежать затрат на чтение (чтобы получить текущие значения), рассмотрите хранимую процедуру, в которой неизменные значения полей кодируются с помощью NULL.

Если вы не используете ORM, вы также можете рассмотреть возможность использования ResultSet с курсором и обновить поля одно за другим, а затем зафиксировать изменения с помощью updateRow(). См. java.sql.ResultSet. Чтобы сделать то же самое, что и Javadoc с использованием PreparedStatement, вам нужно будет использовать вариант Connection.prepareStatement(...).

0
Dilum Ranatunga 29 Авг 2011 в 21:41