2017-02-17 20 views
1

我想更新多行:如何自動更新多行並選擇它們?

UPDATE tbl SET x = x + 5 WHERE x < 7; 

然後,我想選擇同一行作爲一個結果:

SELECT * FROM tbl WHERE (row fulfilled previous condition); 

我會怎麼做呢?

+0

關閉仙女的注意事項:請確保您關閉或合併這與一個不是10歲的實際相同的問題。 – mafu

+1

首先將Where Condition中的鍵值選擇到臨時表中,然後從更新的表上加入臨時表中進行選擇。 –

+0

究竟哪個DBMS? –

回答

0

這個答案適用於mySQL,但它應該足夠普遍適用於其他DBMS。它避免了額外的行,限制或醜陋的黑客攻擊,很容易擴展,並且沒有需要就不會失去性能。

START TRANSACTION; 
DROP TEMPORARY TABLE IF EXISTS temp; 
CREATE TEMPORARY TABLE temp AS (
    SELECT * FROM tbl WHERE x < 7 
); 
UPDATE temp SET x = x + 5; 
REPLACE INTO tbl SELECT * FROM temp; 
SELECT * FROM temp; 
COMMIT; 

如果您在PHP/PDO中使用此功能,則可能需要先選擇正確的結果集。錯誤HY000是一個指示。

$stmt = db -> prepare ($sql); 
$stmt->execute(); 
for ($i=0; $i<5; $i++) 
    $stmt->nextRowset(); 
$result = $stmt->fetchAll(); 
-1

對於MS SQL Server,您需要使用OUTPUT命令MSDN

UPDATE tbl SET x = x + 5 
OUTPUT DELETED.* 
WHERE x < 7 

這將列出所有先前值

0

Postgres的版本

UPDATE tbl t1 
SET x = t1.x + 5 
FROM (SELECT * FROM tbl WHERE x < 7 FOR UPDATE) t2 
WHERE t1.x = t2.x 
RETURNING t2.* 
0

在MySQL中,如果你想在更新它們之前讀取行,您可以在事務中執行鎖定讀取:

START TRANSACTION; 

SELECT ... FROM tbl WHERE x < 7 FOR UPDATE; 

這會在匹配行上獲取鎖,就像您完成更新一樣。因此,除非您的交易完成,否則沒有其他人可以鎖定這些行。

然後,您可以在解決該問題時更新行 - 但仍然在同一個事務中。

UPDATE tbl SET x = x + 5 WHERE x < 7; 

COMMIT; 

如果你想先更新行,然後閱讀它們,你可以在其他命令做到這一點:

START TRANSACTION; 

UPDATE tbl SET x = x + 5 WHERE x < 7; 

SELECT ... FROM tbl WHERE x < 7; 

COMMIT; 

當然,可以選擇不同的行集,但是,由於X已經改變。在UPDATE之前x> = 2或更大的任何行在UDPATE之後將具有x> = 7,因此不會在隨後的SELECT結果中。

所有這些語法都是標準的SQL-99,所以它應該在任何兼容的SQL實現中工作。但並非所有數據庫都以相同的方式實施該標準,因此請參閱所用品牌的文檔。

E.g. https://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html

就我所知,其他語法如RETURNINGOUTPUT不是標準SQL。

相關問題