mysql eliminar en modo seguro

Tengo un instructor de table y quiero eliminar los loggings que tienen un salario en un range. Una forma intuitiva es la siguiente:

delete from instructor where salary between 13000 and 15000; 

Sin embargo, en modo seguro, no puedo eliminar un logging sin proporcionar una key principal (ID).

Entonces escribo el siguiente sql:

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

Sin embargo, hay un error:

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

Estoy confundido porque cuando escribo

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

no produce un error

Mi pregunta es:

  1. ¿Qué significa realmente este post de error y por qué mi código es incorrecto?
  2. ¿Cómo reescribir este código para que funcione en modo seguro?

¡Gracias!

Buscando en Google, la respuesta popular parece ser "simplemente apaga el modo seguro" :

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

Si soy sincero, no puedo decir que alguna vez haya adquirido la costumbre de correr en modo seguro. Aún así, no estoy del todo cómodo con esta respuesta, ya que supone que debe cambiar la configuration de la database cada vez que se encuentre con un problema.

Entonces, su segunda consulta está más cerca de la marca, pero golpea otro problema: MySQL aplica algunas restricciones a las subconsultas, y una de ellas es que no puede modificar una tabla mientras selecciona desde una subconsulta.

Citando del manual de MySQL, Restricciones en las subconsultas :

En general, no puede modificar una tabla y seleccionar desde la misma tabla en una subconsulta. Por ejemplo, esta limitación se aplica a las declaraciones de los siguientes formularios:

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

Excepción: la prohibición anterior no se aplica si está utilizando una subconsulta para la tabla modificada en la cláusula FROM. Ejemplo:

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

Aquí, el resultado de la subconsulta en la cláusula FROM se almacena como una tabla temporal, por lo que las filas relevantes en t ya se han seleccionado antes de que tenga lugar la actualización a t.

Ese último bit es tu respuesta. Seleccione los ID de destino en una tabla temporal, luego elimínelos haciendo reference a los ID en esa tabla:

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

Demostración SQLFiddle .

Puede engañar a MySQL para que crea que realmente está especificando una columna de key principal. Esto le permite "anular" el modo seguro.

Suponiendo que tiene una tabla con una key principal numérica de incremento automático, podría hacer lo siguiente:

 DELETE FROM tbl WHERE id <> 0 

Desactivando el modo seguro en Mysql workbench 6.3.4.0

Menú Edición => Preferences => Editor SQL: Otra sección: click "Actualizaciones seguras" … para desmarcar la opción

enter image description here

Parece que su session MySql tiene configurada la opción de actualizaciones seguras. Esto significa que no puede actualizar o eliminar loggings sin especificar una key (por ejemplo, key principal) en la cláusula where.

Tratar

SET SQL_SAFE_UPDATES = 0;