安全模式下mysql删除

Posted

技术标签:

【中文标题】安全模式下mysql删除【英文标题】:mysql delete under safe mode 【发布时间】:2014-03-17 11:21:48 【问题描述】:

我有一个表讲师,我想删除工资在某个范围内的记录 一个直观的方式是这样的:

delete from instructor where salary between 13000 and 15000;

但是,在安全模式下,如果不提供主键 (ID),我无法删除记录。

所以我写了下面的sql:

delete from instructor where ID in (select ID from instructor where salary between 13000 and 15000);

但是,有一个错误:

You can't specify target table 'instructor' for update in FROM clause

我很困惑,因为当我写的时候

select * from instructor where ID in (select ID from instructor where salary between 13000 and 15000);

它不会产生错误。

我的问题是:

    此错误消息的真正含义是什么?为什么我的代码有误? 如何重写这段代码以使其在安全模式下工作?

谢谢!

【问题讨论】:

您要保持安全模式吗?你在使用 mysql 工作台吗? 您的两个问题的答案都是肯定的。而且令我惊讶的是,当我使用jdbc在没有PK的情况下删除mysql数据库中的记录时,它不会产生错误。那么安全模式只针对mysql workbench? 不——我问是因为如果你想在 mySQL 工作台中关闭它,我可以告诉你怎么做。就我个人而言,我将其关闭...必须拥有 ID 非常安全 - 但在开发方面,我发现这很痛苦 【参考方案1】:

谷歌搜索,流行的答案似乎是"just turn off safe mode":

SET SQL_SAFE_UPDATES = 0;
DELETE FROM instructor WHERE salary BETWEEN 13000 AND 15000;
SET SQL_SAFE_UPDATES = 1;

老实说,我不能说我曾经养成在安全模式下运行的习惯。不过,我对这个答案并不完全满意,因为它只是假设您每次遇到问题时都应该更改数据库配置。

因此,您的第二个查询更接近标记,但遇到了另一个问题:MySQL 对子查询应用了一些限制,其中之一是您在子查询中选择表时不能修改表。

引自 MySQL 手册,Restrictions on Subqueries:

一般来说,您不能修改一个表并从同一个表中进行选择 在子查询中。例如,此限制适用于 以下形式:

DELETE FROM t WHERE ... (SELECT ... FROM t ...);
UPDATE t ... WHERE col = (SELECT ... FROM t ...);
INSERT|REPLACE INTO t (SELECT ... FROM t ...);

例外:如果您在 FROM 子句中对修改后的表使用子查询,则上述禁令不适用。示例:

UPDATE t ... WHERE col = (SELECT * FROM (SELECT ... FROM t...) AS _t ...);

这里 FROM 子句中子查询的结果存储为临时表,因此在更新 t 时已经选择了 t 中的相关行。

最后一点是你的答案。在临时表中选择目标 ID,然后通过引用该表中的 ID 进行删除:

DELETE FROM instructor WHERE id IN (
  SELECT temp.id FROM (
    SELECT id FROM instructor WHERE salary BETWEEN 13000 AND 15000
  ) AS temp
);

SQLFiddle demo.

【讨论】:

感谢您的解释!但是,我在 mysql 工作台中尝试了您的代码,它仍然说“您正在使用安全更新模式,并且您尝试更新没有使用 KEY 列的 WHERE 的表”。 这出乎意料。您的主键是否使用不同的名称?我注意到你的问题似乎表明它被命名为ID,而我的答案使用id 是的,我把它改成ID,它不起作用。我尝试从 ID = '1' 的教练中删除,它可以工作,所以 ID 是主键 @rolandluo 我知道这已经很长时间了,但我很好奇你是否找到了解决方法。显然这种方法在其他情况下也有效,所以我想知道为什么你的情况不同。也许是特定于您的服务器或版本的东西?【参考方案2】:

你可以欺骗 MySQL 认为你实际上是在指定一个主键列。这允许您“覆盖”安全模式。

假设您有一个带有自动递增数字主键的表,您可以执行以下操作:

DELETE FROM tbl WHERE id <> 0

【讨论】:

这是最好的。将 ID 与实际查询一起使用是有效的。 "从教练中删除工资在 13000 和 15000 之间且 id 0"【参考方案3】:

在 Mysql Workbench 6.3.4.0 中关闭安全模式

编辑菜单 => 首选项 => SQL 编辑器:其他部分:点击“安全更新”...取消选中选项

【讨论】:

"如何重写此代码以使其在安全模式下工作?" ==>您的回答告诉了如何禁用安全模式;) 对不起,我完全误解了这个问题。当我无法使用 Mysql 工作台从表中删除时,我发现了这个主题,并且在使用 mysql 工作台的评论中有类似的问题,但我无法创建 cmets。我想,这将是一个写在这里以供将来参考的好地方......【参考方案4】:

我有一个更简单的解决方案,它对我有用;这也是一种解决方法,但可能可用,您不必更改设置。我假设您可以使用永远不会存在的值,然后在 WHERE 子句中使用它

从 MyTable 中删除 MyField IS_NOT_EQUAL AnyValueNoItemOnMyFieldWillEverHave

我也不太喜欢那个解决方案,这就是我在这里的原因,但它确实有效,而且似乎比已经回答的要好

【讨论】:

以上是关于安全模式下mysql删除的主要内容,如果未能解决你的问题,请参考以下文章

MYSQL的安全模式:sql_safe_updates介绍

如何在mysql安全模式下更改mysql的root密码

禁用安全模式

HDFS安全模式

HDFS安全模式

mysql安全模式下改的root密码,不启动mysql服务的时候可以用改的密码,启动之后就不能用该的root密码登陆