2017-02-17 25 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。

相关问题