在某些情况下,在生产环境中运行 UPDATE 语句可以节省时间。然而,一个无聊的更新可能比最初的问题更糟糕。
除了使用测试数据库之外,还有哪些选项可以告诉更新语句在运行之前会做什么?
交易呢?它们具有回滚功能。
@参见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
一般来说,这些行不会被执行一次。在 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;
但我建议使用您最喜欢的编程语言中可用的语言包装器。
除了使用 Imad 所说的事务(无论如何这应该是强制性的)之外,您还可以通过使用与 UPDATE 相同的 WHERE 子句运行选择来执行完整性检查。
所以如果你 UPDATE 是
UPDATE foo
SET bar = 42
WHERE col1 = 1
AND col2 = 'foobar';
下面将显示哪些行将被更新:
SELECT *
FROM foo
WHERE col1 = 1
AND col2 = 'foobar';
自动提交关闭...
MySQL
set autocommit=0;
它为当前会话设置自动提交关闭。
你执行你的语句,看看它发生了什么变化,然后如果它是错误的就回滚,或者如果它是你所期望的就提交!
编辑:使用事务而不是运行选择查询的好处是您可以轻松检查结果集。
我知道这是其他答案的重复,但它有一些情感支持来采取额外的步骤来测试更新: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 的表只需要几秒钟。
不是一个直接的答案,但我已经看到了许多可以通过首先输入WHERE
子句来避免的糟糕的 prod 数据情况!有时 aWHERE 1 = 0
也可以帮助将工作声明安全地放在一起。并且查看估计的执行计划,这将估计受影响的行,可能很有用。除此之外,在您回滚的事务中,正如其他人所说。
做一个SELECT
,
就像你有
UPDATE users SET id=0 WHERE name='jan'
将其转换为
SELECT * FROM users WHERE name='jan'
另一种选择是向 MySQL 询问查询计划。这告诉你两件事:
在 MySQL 和大多数 SQL 数据库中,查询计划命令是describe
,所以你会这样做:
describe update ...;
在您要测试的这些情况下,最好只关注当前列值和即将更新的列值。
请查看我为更新 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
通过这种方式,我们可以清楚地将现有值与新值进行比较。
where
使用您在更新查询中应用的所有条件在同一张表上运行选择查询。