[mysql] 하위 쿼리를 조건으로 사용하는 MySQL DELETE FROM

다음과 같은 쿼리를 시도하고 있습니다.

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

알 수 있듯이 동일한 tid에 다른 부모가있는 경우 1015에 대한 부모 관계를 삭제하고 싶습니다. 그러나 구문 오류가 발생합니다.

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

문서를 확인하고 하위 쿼리를 자체적으로 실행했는데 모두 확인한 것 같습니다. 아무도 여기서 무엇이 잘못되었는지 알아낼 수 있습니까?

업데이트 : 아래에 대답했듯이 MySQL은 삭제하려는 테이블을 조건에 대한 하위 쿼리에 사용하는 것을 허용하지 않습니다.



답변

삭제할 대상 테이블을 지정할 수 없습니다.

해결 방법

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


답변

하위 쿼리를 사용하는 동안 삭제하려는이 질문을 찾는 다른 사람들을 위해 MySQL을 능가하는이 예제를 남깁니다 (일부 사람들이 수행 할 수 없다고 생각하더라도).

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

오류가 발생합니다.

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

그러나이 쿼리 :

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

잘 작동합니다.

Query OK, 1 row affected (3.91 sec)

추가 하위 쿼리 (여기서는 x)로 하위 쿼리를 래핑하면 MySQL은 사용자가 요청한대로 기꺼이 처리합니다.


답변

별칭은 DELETE키워드 뒤에 포함되어야합니다 .

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


답변

다음과 같이 delete 문에서 별칭을 다시 참조해야합니다.

DELETE th FROM term_hierarchy AS th
....

여기 MySQL 문서에 설명되어 있습니다.


답변

나는 이것에 약간 다른 방식으로 접근했고 그것은 나를 위해 일했습니다.

더 이상 조건 행이 더 이상 남아 있지 않은 secure_links테이블을 참조하는 conditions테이블에서 제거해야했습니다 . 기본적으로 하우스 키핑 스크립트입니다. 이로 인해 오류가 발생했습니다. 삭제할 대상 테이블을 지정할 수 없습니다.

그래서 영감을 얻기 위해 여기에서 아래 쿼리를 생각 해냈고 잘 작동합니다. 이는 sl1DELETE에 대한 참조로 사용되는 임시 테이블 을 생성하기 때문 입니다.

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

나를 위해 작동합니다.


답변

삭제의 “in”절이 아닙니까? 하위 쿼리에서 많은 수의 값이 반환되는 경우 극히 비효율적 인 곳은 어디입니까? 삭제할 ID의 하위 쿼리에서 원래 테이블에 대해 “in (subquery)”대신 내부 (또는 오른쪽) 조인을하지 않는 이유가 확실하지 않습니다.?

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)

그리고 아마도 “MySQL이 그것을 허용하지 않습니다”라고 대답했을 수도 있지만, 그것은 나에게 잘 작동합니다. MySQL에서 조인으로 삭제 하면 DELETE / JOIN 문제가 명확 해집니다.


답변

2 개의 쿼리로이를 수행하려면 항상 다음과 유사한 작업을 수행 할 수 있습니다.

1) 다음을 사용하여 테이블에서 ID를 가져옵니다.

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

그런 다음 마우스 / 키보드 또는 프로그래밍 언어로 결과를 아래 XXX에 복사합니다.

2) DELETE FROM your_table WHERE id IN ( XXX )

하나의 쿼리로이 작업을 수행 할 수 있지만 이것이 제가 선호하는 것입니다.