Обновить несколько строк в таблице 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: повторно открыт, поскольку это, похоже, популярный вопрос

950   10  

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

    Ничего не найдено.