在安全模式下删除mysql

时间:2014-02-17 23:25:57

标签: mysql sql

我有一个表教师,我想删除范围内有薪水的记录 一种直观的方式是这样的:

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);

它不会产生错误。

我的问题是:

  1. 此错误消息的真正含义以及我的代码错误的原因是什么?
  2. 如何重写此代码以使其在安全模式下工作?
  3. 谢谢!

5 个答案:

答案 0 :(得分:185)

谷歌搜索,流行的答案似乎是"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

答案 1 :(得分:12)

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

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

DELETE FROM tbl WHERE id <> 0

答案 2 :(得分:11)

关闭Mysql workbench 6.3.4.0中的安全模式

修改菜单=&gt;首选项=&gt; SQL编辑器:其他部分:点击&#34;安全更新&#34; ...取消选中选项

enter image description here

答案 3 :(得分:0)

看起来你的MySql会话设置了safe-updates选项。这意味着您无法在where子句中指定密钥(例如主键)来更新或删除记录。

尝试

SET SQL_SAFE_UPDATES = 0;

答案 4 :(得分:0)

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

从MyTable删除,其中MyField IS_NOT_EQUAL AnyValueNoItemOnMyFieldWillEverHave

我也不太喜欢这种解决方案,这就是为什么我在这里,但是它有效,而且似乎比已经解决的要好