2010-12-17 12 views
59

que estoy tratando de hacer una consulta como esta:MySQL CANCELACIÓN de la subconsulta como condición

DELETE FROM term_hierarchy AS th 
WHERE th.parent = 1015 AND th.tid IN (
    SELECT DISTINCT(th1.tid) 
    FROM term_hierarchy AS th1 
    INNER JOIN term_hierarchy AS th2 ON (th1.tid = th2.tid AND th2.parent != 1015) 
    WHERE th1.parent = 1015 
); 

Como usted puede decir probablemente, quiero eliminar la relación de los padres a 1015 si el mismo TID tiene otros padres. Sin embargo, lo que me produce un error de sintaxis:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'AS th 
WHERE th.parent = 1015 AND th.tid IN (
    SELECT DISTINCT(th1.tid) 
    FROM ter' at line 1 

He comprobado la documentación, y ejecutar la sub consulta por sí mismo, y todo se parece a la salida. ¿Alguien puede descubrir lo que está mal aquí?

Actualización: Como se explica a continuación, MySQL no permite que la tabla que está eliminando se use en una subconsulta para la condición.

+1

** Atención **: Buena respuesta en la parte inferior http://stackoverflow.com/a/4471359/956397 simplemente agregue el alias de la tabla después de 'DELETE t FROM table t ...' – PiTheNumber

Respuesta

28

No se puede especificar la tabla de destino para la eliminación.

Una solución

create table term_hierarchy_backup (tid int(10)); <- check data type 

insert into term_hierarchy_backup 
SELECT DISTINCT(th1.tid) 
FROM term_hierarchy AS th1 
INNER JOIN term_hierarchy AS th2 ON (th1.tid = th2.tid AND th2.parent != 1015) 
WHERE th1.parent = 1015; 

DELETE FROM term_hierarchy AS th 
WHERE th.parent = 1015 AND th.tid IN (select tid from term_hierarchy_backup); 
+0

ambos estamos en lo correcto - vea su comentario en mi respuesta a continuación. La sintaxis y la lógica de Alias ​​eran problemas :) – JNK

+0

Sí, parece que eliminar en la subconsulta no es posible actualmente en MySQL. Gracias por echarle un vistazo :) – mikl

+0

no dice "ELIMINAR FROM term_hierarchy AS th" en esa última línea. ¿el mismo problema? Obtengo un error de sintaxis igual que el OP. – malhal

6

necesita hacer referencia al alias de nuevo en la instrucción de eliminación, como:

DELETE th FROM term_hierarchy AS th 
.... 

As outlined here in MySQL docs.

+0

no se trata de alias, por favor revise el OP otra vez – ajreal

+0

@ajreal - Lo hice, y observe por favor que el error comienza en la definición de alias, y la documentación de MySQL establece explícitamente que necesita usar el alias en la instrucción DELETE así como en la cláusula FROM. Gracias por el voto negativo, sin embargo. – JNK

+0

simplemente haga esto 'eliminar de su_tabla como t1 donde t1.id en (seleccione t2.id de su_tabla t2);' ¿qué obtuvo? – ajreal

30

El alias debe incluirse después de la DELETE palabra clave:

DELETE th 
FROM term_hierarchy AS th 
WHERE th.parent = 1015 AND th.tid IN 
(
    SELECT DISTINCT(th1.tid) 
    FROM term_hierarchy AS th1 
    INNER JOIN term_hierarchy AS th2 ON (th1.tid = th2.tid AND th2.parent != 1015) 
    WHERE th1.parent = 1015 
); 
+2

Esta es una buena respuesta. El alias correcto servirá de mucho para resolver problemas similares a la publicación original. (como el mío.) – usumoio

188

Para otros que encuentran esta pregunta mirando a eliminar durante el uso de una subconsulta, os dejo este ejemplo de superando a MySQL (incluso si algunas personas parecen pensar que no se puede hacer):

DELETE e.* 
FROM tableE e 
WHERE id IN (SELECT id 
      FROM tableE 
      WHERE arg = 1 AND foo = 'bar'); 

le dará un error:

ERROR 1093 (HY000): You can't specify target table 'e' for update in FROM clause 

Sin embargo esta consulta:

DELETE e.* 
FROM tableE e 
WHERE id IN (SELECT id 
      FROM (SELECT id 
        FROM tableE 
        WHERE arg = 1 AND foo = 'bar') x); 

funcionará bien:

Query OK, 1 row affected (3.91 sec) 

Envuelva su subconsulta en una subconsulta adicional (aquí llamada x) y MySQL hará felizmente lo que pidas.

+7

Tomó algo de tiempo pero lo hice funcionar. Importante: 1) La primera tabla debe tener un alias como se muestra aquí con "e", 2) la "x" al final no es un marcador de posición, es el alias para la tabla temporal producida por la subconsulta "(SELECT id FROM tableE DONDE arg = 1 AND foo = 'bar') ". –

+3

¿Por qué funciona esto? Esto cambia mucho para mí, pero además, no debería funcionar. * * Funciona, pero no debería. – donatJ

+1

increíble. ¡esto realmente funciona! pero no está obligado a alias de la tabla con e ... puede usar cualquier alias que desee. –

4

Me acerqué a esto de una manera ligeramente diferente y funcionó para mí;

Necesitaba eliminar secure_links de mi tabla que hacía referencia a la tabla conditions donde ya no quedaban filas de condición. Un guión de limpieza básicamente. Esto me dio el error: no puede especificar la tabla de destino para eliminar.

Así que, buscando inspiración aquí, se me ocurrió la siguiente pregunta y funciona muy bien. Esto se debe a que crea una tabla temporal sl1 que se utiliza como referencia para ELIMINAR.

DELETE FROM `secure_links` WHERE `secure_links`.`link_id` IN 
      (
      SELECT 
       `sl1`.`link_id` 
      FROM 
       (
       SELECT 

        `sl2`.`link_id` 

       FROM 
        `secure_links` AS `sl2` 
        LEFT JOIN `conditions` ON `conditions`.`job` = `sl2`.`job` 

       WHERE 

        `sl2`.`action` = 'something' AND 
        `conditions`.`ref` IS NULL 
       ) AS `sl1` 
      ) 

Funciona para mí.

3

No es la cláusula "in" en la eliminación ...donde, extremadamente ineficiente, si va a haber una gran cantidad de valores devueltos de la subconsulta? No estoy seguro de por qué no se uniría interna (o derecha) a la tabla original desde la subconsulta en la ID para eliminar, en lugar de a nosotros el "en (subconsulta)".

DELETE T FROM Target AS T 
RIGHT JOIN (full subquery already listed for the in() clause in answers above) ` AS TT ON (TT.ID = T.ID) 

Y tal vez se responde en el "MySQL no lo permite", bien sin embargo, se está trabajando para mí proporcionado me aseguro de aclarar plenamente qué borrar (DELETE T desde tan objetivo T). Delete with Join in MySQL aclara el problema DELETE/JOIN.

0

Si usted quiere hacer esto con 2 consultas, siempre se puede hacer algo similar a esto:

1) agarrar las identificaciones de la mesa con:

SELECT group_concat(id) as csv_result FROM your_table WHERE whatever = 'test' ... 

luego copiar resultado con el ratón/teclado o lenguaje de programación a continuación XXX:

2) DELETE FROM your_table WHERE id IN (XXX) 

tal vez usted podría hacer esto en una consulta, pero esto es lo que prefiero.