Обновить несколько строк в таблице SQL
Предположим, что существует полностью заполненный массив данных String[n] [3] myData.
Я хочу сделать вот что:
for (String[] row : myData)
{
SQL = "update mytable set col3 = row[2]
where col1 = row[0] and col2=row[1];"
}
Очевидно, я многое упустил, но я хочу выразить эту мысль как можно более кратко.
Есть ли простой способ сделать это в одной команде DB?
Как насчет не столь простого способа?
Правки:
Данные не поступают из другой таблицы (это веб - форма подачи-экзамен множественного выбора)
Учитывая, что приложение работает в интернете, это должно быть доказательство инъекций. Параметризованные запросы-мой предпочтительный путь.
Я использую MS-SQL Server 2005
Редактировать:закрытия и повторного спрашиваю как несколько обновлений БД:
EDIT: повторно открыт, поскольку это, похоже, популярный вопрос
10 ответов:
Если вы используете Sql Server, вы можете использовать SqlBulkCopy. Сначала вы должны поместить свои данные в DataTable, что было бы довольно легко, так как у вас уже есть это в строковом массиве.
Http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.aspx
Это зависит от того, какую базу данных вы используете. Если вы используете SQL Server 2008, Вы можете использовать хранимую процедуру параметры таблицы. Это позволяет передать все ваши значения в хранимую процедуру в одной таблице, после чего вы можете сделать:
update mytable set mytable.col1 = @tbl.col1 from mytable inner join @tbl on mytable.col2 = @tbl.col2Если вы используете SQL Server 2005,вы можете использовать XML. Форматируйте значения в формате XML, а затем используйте операторы XQuery (т. е. "узлы" и "значение") для синтаксического анализа XML. Это также может быть сделано в одной инструкции SQL, и это не требует сохранения процедура.
Можно сделать большую строку, например:
for (String[] row : myData) { SQL += "update mytable set col3 = row[2] where col1 = row[0] and col2=row[1];" } sqlDriver.doInsertQuery(SQL); // change this to your way of inserting into the dbИ просто совершите все это сразу. Я не очень хорошо разбираюсь в SQL, так что именно так я бы это и сделал.
SQL-движок просто разбивает его на ';' и делает отдельные вставки самостоятельно. Это нормально, чтобы добавить все это в строку, хотя. Это похоже на то, как если бы вы скопировали большую строку с несколькими обновлениями / вставками в приглашение sql
Возможно, это не тот ответ, который вам нужен, Но открытие транзакции, выполнение ваших инструкций и последующая фиксация транзакции будут, с точки зрения базы данных, делать то, что вы описываете.
Состояние базы данных не изменяется для других пользователей базы данных до завершения транзакции, и это, вероятно, является предпочтительным эффектом.
Если вы используете корпоративную библиотеку на уровне доступа к данным, Вы можете создать транзакцию в .Net, выполнить итерацию вызовов процедур, а затем зафиксировать / откатить все из .Net.
DbTransaction transaction = connection.BeginTransaction(); try { for (String[] row : myData) { ListDictionary params = new Specialized.ListDictionary(); params.add("@col3", row[2]); params.add("@col1", row[0]); params.add("@col2", row[1]); executeNonQuery("myUpdateProcedure", params); } transaction.commit(); } catch(Exception ex) { transaction.rollback(); throw ex; } finally { connection.close(); }
Если по какой-либо причине вы не можете выполнить обновление, используя один из методов, предложенных выше, очень неэффективный подход, приведенный ниже, вероятно, будет работать для вас.
SQL = "Update myTable Set Col3 = Case " for (String[] row : myData) { SQL += "When Col1 = " + Row[0] + " and Col2 = " + Row[1] + " then " + row[2] + " " } SQL + = "Else Col3 end"
Похоже, что вы хотите сделать обновление A, над строками, которые имеют кодировки B и C. (A, B, C) хранятся как кортежи (строки) в myData. Разве не так?
Возможно (если вы используете Microsoft SQL Server... Я не знаю, существует ли он в Oracle, может быть) вы можете использовать соединение с обновлением. Вы можете объявить обновление над таблицей, соединенной с другой таблицей. Если myData приходит из другой таблицы, то вы можете сделать (это не правильный синтаксис):
UPDATE whatchanges wc INNER JOIN changes c ON <yourcondition> SET wc.col1 = c.newvalue WHERE ....(Если вы хотите применить все изменения в таблица" изменения " вам не нужно использовать, где, конечно, внутреннее соединение уже выбрало правильные строки).
Конечно, существуют ограничения для такого рода обновлений. И это MS SQL proprietary. Поэтому, если это ваш случай, я бы предложил поискать его в MS web (ключевые слова: UPDATE and JOIN)
Не совсем. Вы можете создать строку с тем же циклом, а затем передать свои значения в качестве параметров, но это все равно будет несколько команд базы данных.
for each whatever sql += "UPDATE ... ;" end for execute (sql)
Я подозреваю, что вам потребуется использовать несколько операторов SQL. Вы можете найти оболочку для обработки мелочей, но под ней я бы предположил, что она будет итеративно запускать инструкцию SQL для каждого обновления.
Выдает обновление, которое идет против таблицы значений:
UPDATE myTable SET col3=c FROM myTable JOIN ( SELECT 1 as a, 2 as b, 'value1' as c UNION ALL SELECT 3 as a, 4 as b, 'value2' as c -- etc... ) x ON myTable.col1=x.a AND myTable.col2=x.bТак что вы просто сложите это вот так:
// make one of these for each row String.Format("SELECT {0} as a, {1} as b, '{2}' as c", row[0], row[1], row[2].Replace("'","''")) // put it together string expr = "UPDATE myTable SET col3=c FROM myTable JOIN (" + String.Join(stringformatarray, " UNION ALL ") + ") x ON myTable.col1=x.a AND myTable.col2=x.b"Или вы можете использовать StringBuilder, чтобы собрать это вместе.
И затем, конечно, вы выполняете эту строку.
Comments