115

在某些情况下,在生产环境中运行 UPDATE 语句可以节省时间。然而,一个无聊的更新可能比最初的问题更糟糕。

除了使用测试数据库之外,还有哪些选项可以告诉更新语句在运行之前会做什么?

4

9 回答 9

103

交易呢?它们具有回滚功能。

@参见https://dev.mysql.com/doc/refman/5.0/en/commit.html

例如:

START TRANSACTION;
SELECT * FROM nicetable WHERE somthing=1;
UPDATE nicetable SET nicefield='VALUE' WHERE somthing=1;
SELECT * FROM nicetable WHERE somthing=1; #check

COMMIT;
# or if you want to reset changes 
ROLLBACK;

SELECT * FROM nicetable WHERE somthing=1; #should be the old value

回答以下@rickozoe 的问题:

一般来说,这些行不会被执行一次。在 PHP fe 中,您会编写类似的东西(也许更简洁一些,但想快速回答 ;-)):

$MysqlConnection->query('START TRANSACTION;');
$erg = $MysqlConnection->query('UPDATE MyGuests SET lastname='Doe' WHERE id=2;');
if($erg)
    $MysqlConnection->query('COMMIT;');
else
    $MysqlConnection->query('ROLLBACK;');

另一种方法是使用 MySQL 变量(参见https://dev.mysql.com/doc/refman/5.7/en/user-variables.htm l 和 https://stackoverflow.com/a/18499823/1416909 ):

# do some stuff that should be conditionally rollbacked later on

SET @v1 := UPDATE MyGuests SET lastname='Doe' WHERE id=2;
IF(v1 < 1) THEN
    ROLLBACK;
ELSE
    COMMIT;
END IF;

但我建议使用您最喜欢的编程语言中可用的语言包装器。

于 2015-07-15T21:46:47.430 回答
65

除了使用 Imad 所说的事务(无论如何这应该是强制性的)之外,您还可以通过使用与 UPDATE 相同的 WHERE 子句运行选择来执行完整性检查。

所以如果你 UPDATE 是

UPDATE foo
  SET bar = 42
WHERE col1 = 1
  AND col2 = 'foobar';

下面将显示哪些行将被更新:

SELECT *
FROM foo
WHERE col1 = 1
  AND col2 = 'foobar';
于 2012-06-13T08:59:26.103 回答
62

自动提交关闭...

MySQL

set autocommit=0;

它为当前会话设置自动提交关闭。

你执行你的语句,看看它发生了什么变化,然后如果它是错误的就回滚,或者如果它是你所期望的就提交!

编辑:使用事务而不是运行选择查询的好处是您可以轻松检查结果集。

于 2012-06-13T08:57:28.017 回答
11

我知道这是其他答案的重复,但它有一些情感支持来采取额外的步骤来测试更新:D

对于测试更新,哈希 # 是你的朋友。

如果您有如下更新语句:

UPDATE 
wp_history
SET history_by="admin"
WHERE
history_ip LIKE '123%'

您散列 UPDATE 和 SET 进行测试,然后将它们散列回:

SELECT * FROM
#UPDATE
wp_history
#SET history_by="admin"
WHERE
history_ip LIKE '123%'

它适用于简单的陈述。

另一个实际强制性的解决方案是,每当在生产表上使用更新时获取副本(备份副本)。Phpmyadmin > 操作 > 复制:table_yearmonthday。<=100M 的表只需要几秒钟。

于 2013-02-26T13:51:01.277 回答
6

不是一个直接的答案,但我已经看到了许多可以通过首先输入WHERE子句来避免的糟糕的 prod 数据情况!有时 aWHERE 1 = 0也可以帮助将工作声明安全地放在一起。并且查看估计的执行计划,这将估计受影响的行,可能很有用。除此之外,在您回滚的事务中,正如其他人所说。

于 2012-06-13T09:08:23.973 回答
4

做一个SELECT

就像你有

UPDATE users SET id=0 WHERE name='jan'

将其转换为

SELECT * FROM users WHERE name='jan'

于 2012-06-13T09:00:14.387 回答
4

另一种选择是向 MySQL 询问查询计划。这告诉你两件事:

  • 查询中是否有语法错误,如果有则查询计划命令本身会失败
  • MySQL 计划如何执行查询,例如它将使用哪些索引

在 MySQL 和大多数 SQL 数据库中,查询计划命令是describe,所以你会这样做:

describe update ...;
于 2020-10-17T23:26:32.267 回答
3

在您要测试的这些情况下,最好只关注当前列值和即将更新的列值。

请查看我为更新 WHMCS 价格而编写的以下代码:

# UPDATE tblinvoiceitems AS ii

SELECT                        ###  JUST
    ii.amount AS old_value,   ###  FOR
    h.amount AS new_value     ###  TESTING
FROM tblinvoiceitems AS ii    ###  PURPOSES.

JOIN tblhosting AS h ON ii.relid = h.id
JOIN tblinvoices AS i ON ii.invoiceid = i.id

WHERE ii.amount <> h.amount   ### Show only updatable rows

# SET ii.amount = h.amount

通过这种方式,我们可以清楚地将现有值与新值进行比较。

于 2018-10-13T18:01:20.500 回答
1

where使用您在更新查询中应用的所有条件在同一张表上运行选择查询。

于 2012-06-13T08:59:18.250 回答