2012-07-19 64 views
14

我有一個帶有表myTable和列id,posX,posY的SQLite數據庫。行數不斷變化(可能增加或減少)。如果我知道每行的id值和行數,是否可以執行單個SQL查詢以根據id更新所有posX,posY字段的不同值?在單個SQL查詢中更新具有不同值的多行

例如:

--------------------- 
myTable: 

id posX posY 

1  35  565 
3  89  224 
6  11  456 
14  87  475 
--------------------- 

爲SQL查詢的僞代碼:

" UPDATE myTable SET posX[id] = @arrayX[id], posY[id] = @arrayY[id] " 

@arrayX,其存儲用於POSX和POSY字段的新值被arrayY陣列。

,例如如果arrayX和arrayY包含以下值:

arrayX = { 20, 30, 40, 50 } 
arrayY = { 100, 200, 300, 400 } 

查詢後,數據庫應該是這樣的:

--------------------- 
myTable: 

id posX posY 

1  20  100 
3  30  200 
6  40  300 
14  50  400 
--------------------- 

這可能嗎?我現在正在每個查詢更新一行。但隨着行數的增加,需要數百個查詢。順便說一下,我在AIR中完成了所有這些工作。

+0

或許這能夠幫助http://dba.stackexchange.com/questions/17590/find-last-max-value-according-to-timestamp-using-update-method – adopilot 2012-07-19 15:35:40

回答

18

有幾種方法可以高效地完成體面

首先 -
如果可能,您可以對臨時表進行某種批量插入。這在一定程度上取決於您的RDBMS /主機語言,但最糟糕的情況是,可以使用簡單的動態SQL(使用VALUES()子句),然後使用標準的從另一個表更新來完成。大多數系統提供用於批量加載的實用程序,儘管

第二 -
而且這也有些依賴於RDBMS,您可以構建動態更新語句。在這種情況下,這裏的CTE內VALUES(...)條款已經在即時創建:

WITH Tmp(id, px, py) AS (VALUES(id1, newsPosX1, newPosY1), 
           (id2, newsPosX2, newPosY2), 
           ......................... , 
           (idN, newsPosXN, newPosYN)) 

UPDATE TableToUpdate SET posX = (SELECT px 
           FROM Tmp 
           WHERE TableToUpdate.id = Tmp.id), 
         posY = (SELECT py 
           FROM Tmp 
           WHERE TableToUpdate.id = Tmp.id) 


WHERE id IN (SELECT id 
      FROM Tmp) 

(根據文檔,這應該有效SQLite的語法,但我不能得到它在小提琴作品)

+0

謝謝,我想我會給一個動態的聲明。 – astralmaster 2012-07-19 15:53:44

+0

你可以把你的代碼放入答案本身嗎?現在,如果該鏈接死亡,你的答案就變得無用了。 – 2014-08-12 13:47:22

+0

@GeorgeStocker - 啊,謝謝。不知何故,我錯過了原始標籤,而我的示例語句在目標RDBMS中無效。希望它現在能工作... – 2014-08-12 22:27:54

4

這樣的事情可能會爲你工作:

"UPDATE myTable SET ... ; 
UPDATE myTable SET ... ; 
UPDATE myTable SET ... ; 
UPDATE myTable SET ... ;" 

如果任何POSX或波西值是相同的,那麼它們可以合併成一個查詢

UPDATE myTable SET posX='39' WHERE id IN('2','3','40'); 
+0

你可以在文本編輯器中準備這樣的語句並將它們直接粘貼到命令行中。如果你沒有太多的更新,效果會很好。 – pavitran 2017-04-08 05:38:03

14

是的,你可以這樣做,但我懷疑它會提高性能,除非你的查詢有一個真正的大延遲。

你可以這樣做:

UPDATE table SET posX=CASE 
     WHEN id=id[1] THEN posX[1] 
     WHEN id=id[2] THEN posX[2] 
     ... 
     ELSE posX END, posY = CASE ... END 
WHERE id IN (id[1], id[2], id[3]...); 

總費用給予或多或少:NUM_QUERIES *(COST_QUERY_SETUP + COST_QUERY_PERFORMANCE)。通過這種方式,您可以在NUM_QUERIES上減少一些成本,但COST_QUERY_PERFORMANCE會在bigtime上升。如果COST_QUERY_SETUP真的很大(例如,你打電話給一些真正很慢的網絡服務),那麼,是的,你可能仍然處於頂峯。

否則,我會嘗試索引id或修改架構。

在MySQL中,我認爲你可以通過多重INSERT ON DUPLICATE KEY UPDATE更輕鬆地做到這一點(但我不確定,從未嘗試過)。

+0

不錯的例子!不幸的是,正如我所說的那樣,行數會發生變化,因此「WHEN」操作符的數量需要不斷更改。 – astralmaster 2012-07-19 15:39:10

+0

如果你真的熱衷於這樣做,你可以動態構建查詢。該查詢被重新組合爲五個或六個片斷,其中三個(第一個和第二個CASE以及IN子句)構建在單個WHILE循環中。無論如何,你應該做這樣的事情,如果價值觀發生變化...... – LSerni 2012-07-19 15:49:43

+0

幾乎我所想的。謝謝。 – astralmaster 2012-07-19 15:53:12

-9

與「更新平板嘗試集(行= '值' 其中id = 0001 '),(行=' 值' 其中id = 0002' ),...

+1

這是行不通的。 – 2013-11-04 13:05:30

+0

這是什麼!!! – Mafujul 2018-03-10 05:56:29

相關問題