2008-10-08 12 views
2

Предположим, что имеется полностью заполненный массив данных String [n] [3] myData.Обновление нескольких строк в таблице SQL

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

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: закрытие и вновь просить, как Multiple DB Updates:

EDIT: Re открыт, так как это, кажется, популярный вопрос

ответ

1

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

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.

+3

Теперь, как его параметризовать? – 2008-10-08 18:28:39

0

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

for each whatever 
    sql += "UPDATE ... ;" 
end for 
execute (sql) 
+0

Да, этого я и стараюсь избегать. Я хочу массовое обновление с параметризованными запросами в одной транзакции. – 2008-10-08 18:26:01

1

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

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

0

Я подозреваю, что вам нужно будет использовать несколько операторов SQL. Вы можете найти оболочку для обработки мелочей, но под ней я бы предположил, что она итеративно запускает инструкцию SQL для каждого UPDATE.

7

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

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

+0

Мне нравится первый вариант, мне придется дождаться обновления в первую очередь. Это довольно сладкая особенность. – 2008-10-08 19:26:06

+0

Любой пример использования подхода внутреннего соединения с XQuery для обновления в одном заявлении? – Cannon 2012-02-08 16:57:34

1

Похоже, что вы хотите сделать обновление 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 .... 

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

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

+0

Первый пара является правильным, за исключением того, что C обновляется с условиями A и B, но это тривиально. – 2008-11-28 15:38:26

1

Если вы используете Enterprise Library на вашем уровне доступа к данным, вы можете создать транзакцию в .Net, выполнить итерацию через вызовы процедур, затем commit/rollback из .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

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

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" 
0

испускают обновление, которое идет вразрез с таблицей значений:

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, чтобы положить это вместе.

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

Смежные вопросы