Обновить несколько строк в таблицу SQL - PullRequest
2 голосов
/ 08 октября 2008

Предположим, существует полностью заполненный массив данных String [n] [3] myData.

Я хочу сделать это:

for (String[] row : myData)
{
   SQL = "update mytable set col3 = row[2]
   where col1 = row[0] and col2=row[1];" 
}

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

Есть ли простой способ сделать это в одной команде БД? Как насчет не такого простого способа?

редактирует: Данные не поступают из другой таблицы (это отправка веб-формы - экзамен с несколькими вариантами ответов)
Поскольку приложение работает в Интернете, оно должно быть защищенным от инъекций. Параметризованные запросы - мой предпочтительный способ.
Я использую MS-SQL Server 2005

РЕДАКТИРОВАТЬ: Закрытие и повторный запрос как Несколько обновлений БД:

РЕДАКТИРОВАТЬ: вновь открыт, так как это кажется популярным вопросом

Ответы [ 10 ]

7 голосов
/ 08 октября 2008

Это зависит от того, какую базу данных вы используете. Если вы используете SQL Server 2008, вы можете использовать хранимую процедуру TABLE параметров . Это позволяет вам передавать все ваши значения в хранимую процедуру в одной таблице, тогда вы можете сделать:

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, и для этого не требуется хранимая процедура.

3 голосов
/ 08 октября 2008

Если вы используете Sql Server, вы можете использовать SqlBulkCopy. Сначала вам нужно будет поместить ваши данные в DataTable, что будет довольно просто, поскольку у вас уже есть их в массиве строк.

http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlbulkcopy.aspx

1 голос
/ 08 октября 2008

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

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"  
1 голос
/ 08 октября 2008

Если вы используете Enterprise Library на своем уровне доступа к данным, вы можете создать транзакцию в .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();
}
1 голос
/ 08 октября 2008

Похоже, что вы хотите обновить A, над строками с кодировками B и C. (A, B, C) хранятся в виде кортежей (строк) в myData. Не так ли?

Возможно (если вы используете Microsoft SQL Server ... Я не знаю, существует ли он в Oracle, может быть), вы можете использовать JOIN с UPDATE. Вы можете объявить обновление по таблице, объединенной с другой. Если myData поступает из другой таблицы, вы можете сделать это (неправильный синтаксис):

UPDATE whatchanges wc INNER JOIN changes c ON <yourcondition>
SET wc.col1 = c.newvalue
WHERE ....

(если вы хотите применить все изменения в таблице «изменений», вам не нужно использовать ГДЕ, конечно, INNER JOIN уже выбрал правильные строки).

Конечно, существуют ограничения для такого рода обновлений. И это собственность MS SQL. Поэтому, если это ваш случай, я бы посоветовал поискать его в MS Web (ключевые слова: UPDATE и JOIN)

1 голос
/ 08 октября 2008

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

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

1 голос
/ 08 октября 2008

Вы можете сделать большую строку, как:

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

0 голосов
/ 08 октября 2008

выдает обновление, соответствующее таблице значений:

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, чтобы собрать это вместе.

и затем, конечно, вы выполните эту строку.

0 голосов
/ 08 октября 2008

Я подозреваю, что вам нужно будет использовать несколько операторов SQL. Вы можете найти оболочку для обработки мелочей, но я бы подумал, что она будет итеративно выполнять оператор SQL для каждого ОБНОВЛЕНИЯ.

0 голосов
/ 08 октября 2008

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

for each whatever
    sql += "UPDATE ... ;"
end for
execute (sql)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...