2008-10-08 185 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命令中執行此操作? 怎麼樣一個不那麼簡單的方法?

EDITS: 數據不從另一個表(這是一個網頁表單提交 - 選擇題考試)來
看到,因爲應用程序是面向網,它一定是注射證明。參數化查詢是我首選的方式。
我使用MS-SQL Server 2005的

編輯:關閉,並重新要求爲Multiple DB Updates:

編輯:重開,因爲這似乎是一個受歡迎的問題

回答

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語句。你可能會發現一個包裝來處理細節,但在下面,我想它會迭代地爲每個UPDATE運行一條SQL語句。

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 .... 

(如果你想申請的「變化」表中的所有更改,您不必當然,其中使用INNER JOIN已經選擇了正確的行)。

當然這種更新存在限制。它是MS SQL專有的。因此,如果是你的情況,我建議在MS網上尋找它(關鍵字:UPDATE和JOIN)

+0

第一段是正確的,除了C被更新,條件A和B,但這是微不足道的。 – 2008-11-28 15:38:26

1

如果你在你的數據訪問層使用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

如果因爲某種原因無法使用上述建議的方法之一執行更新,下面的低效率方法可能適用於您。

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放在了一起。

然後,當然,你執行這一個字符串。