由于“安全更新模式”,查询失败

时间:2016-04-28 16:51:57

标签: mysql

我有下表:

CREATE TABLE `number_locks` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `number` varchar(255) NOT NULL,
  `timeout` datetime NOT NULL,
  PRIMARY KEY (`id`),
  KEY `number` (`number`),
  KEY `timeout` (`timeout`)
) ENGINE=InnoDB AUTO_INCREMENT=69146 DEFAULT CHARSET=latin1

现在我想在其中运行这个准备好的删除语句:

> SET @number="123123";
Query OK, 0 rows affected (0.17 sec)  

> PREPARE delete_number_lock FROM 'DELETE FROM number_locks WHERE number=? OR timeout<NOW()';
Query OK, 0 rows affected (0.17 sec)
Statement prepared  

> EXECUTE delete_number_lock USING @number;
ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column

我无法理解为什么它认为使用KEY列没有where条件。

2 个答案:

答案 0 :(得分:1)

默认情况下,mysql以安全更新模式运行,可帮助用户在数据库中进行任何意外修改。正如您在MYSQL REFERENCE MANUAL中所看到的那样,

  

对于您可能已发出DELETE FROM tbl_name语句但忘记了WHERE子句的情况很有用。通常,这样的语句会删除表中的所有行。使用--safe-updates,您只能通过指定标识它们的键值来删除行。这有助于防止事故。

安全模式也拒绝where子句不使用键列或约束的语句,如手册进一步说明

  

除非在WHERE子句中指定键约束或提供LIMIT子句(或两者),否则不允许执行UPDATE或DELETE语句

在您的情况下,删除查询不使用键约束,因此不会执行。

因此,要禁用安全模式,请尝试以下操作:

SET SQL_SAFE_UPDATES=0;

更新

查看您的查询DELETE FROM number_locks WHERE number=? OR timeout<NOW()

此处列number不是键列,因此错误。如果您使用id代替number,则不会发生此类错误,因为id是主键。

更多更新

OR将您的WHERE子句分为两个逻辑部分。让我解释一下number="12345" OR timeout<NOW()成为(数字||超时)不是关键。但是使用AND的条件将起作用,因为它将两列共同考虑在内。另外有趣的是,OR如果您使用相同的列名称,例如number="12345" OR number='564789'

,则会有效

答案 1 :(得分:0)

我发现通过使用始终为真的主键添加条件来避免这种情况的最快方法就是这样:

DELETE 
FROM number_locks 
WHERE id > 0 AND (number=? OR timeout<NOW())
;