如何在运行之前测试SQL Update语句?

sta*_*tti 80 mysql sql database testing myisam

在某些情况下,在生产中运行UPDATE语句可以节省一天.然而,borked更新可能比最初的问题更糟糕.

如果没有使用测试数据库,有什么选项可以告诉更新语句在运行之前会做什么?

Mar*_*nge 62

交易怎么样?他们有ROLLBACK功能.

@see 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
Run Code Online (Sandbox Code Playgroud)

从以下@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;');
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用MySQL变量(请参阅https://dev.mysql.com/doc/refman/5.7/en/user-variables.htm l和 /sf/answers/1294987641/ ):

# 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;
Run Code Online (Sandbox Code Playgroud)

但我建议使用您喜欢的编程语言中提供的语言包装器.


Ima*_*dem 51

自动提交OFF ...

MySQL的

set autocommit=0;
Run Code Online (Sandbox Code Playgroud)

它为当前会话设置自动提交.

您执行您的语句,查看它已更改的内容,然后如果错误则回滚,或者如果它符合您的预期则进行回滚!

编辑:使用事务而不是运行选择查询的好处是,您可以更容易地检查结果集.

  • @dystroy:每个合理的DBMS都支持事务. (4认同)
  • 只需记住快速提交或回滚事务,否则您可能会阻止其他事务 - 并且在最坏的情况下会使您的应用程序停止运行.执行查询不是一个好主意,然后吃午饭,然后回来看看结果!:-) (4认同)
  • @dystroy:不幸的是,MyISAM到处使用,我不是DBA. (4认同)

a_h*_*ame 36

除了使用Imad所说的事务(无论如何应该是强制的)之外,您还可以通过使用与UPDATE相同的WHERE子句运行select来检查哪些行受到影响.

所以,如果你UPDATE是

UPDATE foo
  SET bar = 42
WHERE col1 = 1
  AND col2 = 'foobar';
Run Code Online (Sandbox Code Playgroud)

以下将显示哪些行将更新:

SELECT *
FROM foo
WHERE col1 = 1
  AND col2 = 'foobar';
Run Code Online (Sandbox Code Playgroud)

  • @ImadMoqaddem:我同意,这就是为什么我写"*除了使用Imad所说的交易*" (2认同)

Joh*_*han 11

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

为了测试更新,hash#是你的朋友.

如果您有更新声明,例如:

UPDATE 
wp_history
SET history_by="admin"
WHERE
history_ip LIKE '123%'
Run Code Online (Sandbox Code Playgroud)

您将UPDATE和SET哈希用于测试,然后将它们哈希回来:

SELECT * FROM
#UPDATE
wp_history
#SET history_by="admin"
WHERE
history_ip LIKE '123%'
Run Code Online (Sandbox Code Playgroud)

它适用于简单的陈述.

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


Dav*_*d M 6

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

  • @SystemParadox - 什么都没有,但如果有人在使用不同的 DBMS 时遇到这个问题,`WHERE 1 = 0` 会更便携。例如,SQL Server 不会接受`WHERE FALSE`。 (2认同)

Yaw*_*war 6

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

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

在 MySQL 和大多数 SQL 数据库中,查询计划命令是describe,因此您可以执行以下操作:

describe update ...;
Run Code Online (Sandbox Code Playgroud)


use*_*723 5

只需运行一个EXPLAIN查询即可。因此,只需EXPLAIN在查询之前写下这个词,它就会为您提供有关如何执行更新的信息 - 查找行等。但它不会执行它。但是,如果有任何语法错误,它会让您知道。所以只需使用解释即可!

EXPLAIN UPDATE ... SET ...
Run Code Online (Sandbox Code Playgroud)