在安全模式下删除mysql

rol*_*luo 76 mysql sql

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

delete from instructor where salary between 13000 and 15000;
Run Code Online (Sandbox Code Playgroud)

但是,在安全模式下,我无法在不提供主键(ID)的情况下删除记录.

所以我写下面的sql:

delete from instructor where ID in (select ID from instructor where salary between 13000 and 15000);
Run Code Online (Sandbox Code Playgroud)

但是,有一个错误:

You can't specify target table 'instructor' for update in FROM clause
Run Code Online (Sandbox Code Playgroud)

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

select * from instructor where ID in (select ID from instructor where salary between 13000 and 15000);
Run Code Online (Sandbox Code Playgroud)

它不会产生错误.

我的问题是:

  1. 这个错误信息真正意味着什么以及为什么我的代码错了?
  2. 如何重写此代码以使其在安全模式下工作?

谢谢!

rut*_*ter 197

谷歌搜索,流行的答案似乎是"只关闭安全模式":

SET SQL_SAFE_UPDATES = 0;
DELETE FROM instructor WHERE salary BETWEEN 13000 AND 15000;
SET SQL_SAFE_UPDATES = 1;
Run Code Online (Sandbox Code Playgroud)

如果我是诚实的,我不能说我曾经养成了以安全模式运行的习惯.尽管如此,我对这个答案并不完全满意,因为它只是假设你每次遇到问题都应该更改数据库配置.

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

引用MySQL手册,子查询限制:

通常,您无法修改表并从子查询中的同一表中进行选择.例如,此限制适用于以下形式的陈述:

DELETE FROM t WHERE ... (SELECT ... FROM t ...);
UPDATE t ... WHERE col = (SELECT ... FROM t ...);
{INSERT|REPLACE} INTO t (SELECT ... FROM t ...);
Run Code Online (Sandbox Code Playgroud)

例外:如果在FROM子句中使用子查询修改表,则前面的禁止不适用.例:

UPDATE t ... WHERE col = (SELECT * FROM (SELECT ... FROM t...) AS _t ...);
Run Code Online (Sandbox Code Playgroud)

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

SQLFiddle演示.

  • 谢谢你的解释!但是,我在mysql workbench中尝试了你的代码,它仍然说"你正在使用安全更新模式,你试图更新没有使用KEY列的WHERE的表". (5认同)

Hug*_*ink 13

你可以诱骗MySQL认为你实际上在指定一个主键列.这允许您"覆盖"安全模式.

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

DELETE FROM tbl WHERE id <> 0
Run Code Online (Sandbox Code Playgroud)


Pet*_*r B 11

在Mysql工作台6.3.4.0中关闭安全模式

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

在此输入图像描述

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