[mysql] MySQL 오류 1093-FROM 절에서 업데이트 대상 테이블을 지정할 수 없습니다

story_category데이터베이스에 손상된 항목 이있는 테이블 이 있습니다. 다음 쿼리는 손상된 항목을 반환합니다.

SELECT *
FROM  story_category
WHERE category_id NOT IN (
    SELECT DISTINCT category.id
    FROM category INNER JOIN
       story_category ON category_id=category.id);

나는 실행을 삭제하려고 시도했다.

DELETE FROM story_category
WHERE category_id NOT IN (
    SELECT DISTINCT category.id
    FROM category
      INNER JOIN story_category ON category_id=category.id);

그러나 다음 오류가 발생합니다.

# 1093-FROM 절에서 업데이트 대상 테이블 ‘story_category’를 지정할 수 없습니다

이걸 어떻게 극복 할 수 있습니까?



답변

업데이트 :이 답변은 일반적인 오류 분류를 다룹니다. OP의 정확한 쿼리를 가장 잘 처리하는 방법에 대한 자세한 답변은이 질문에 대한 다른 답변을 참조하십시오.

MySQL에서는 SELECT 파트에서 사용하는 것과 동일한 테이블을 수정할 수 없습니다.
이 동작은 http://dev.mysql.com/doc/refman/5.6/en/update.html에 설명되어 있습니다.

어쩌면 당신은 테이블 자체를 조인 할 수 있습니다

논리가 쿼리를 재구성 할 수있을 정도로 단순하면 적절한 선택 기준을 사용하여 하위 쿼리를 잃고 테이블을 조인합니다. 이로 인해 MySQL은 테이블을 두 가지로 간주하여 파괴적인 변화를 진행할 수 있습니다.

UPDATE tbl AS a
INNER JOIN tbl AS b ON ....
SET a.col = b.col

또는 부속 쿼리를 from 절에 더 깊이 중첩시켜보십시오 …

하위 쿼리가 절대적으로 필요한 경우 해결 방법이 있지만 성능을 포함하여 몇 가지 이유로 추한 것입니다.

UPDATE tbl SET col = (
  SELECT ... FROM (SELECT.... FROM) AS x);

FROM 절의 중첩 된 하위 쿼리는 암시 적 임시 테이블을 생성 하므로 업데이트하는 동일한 테이블로 계산되지 않습니다.

…하지만 쿼리 최적화 프로그램을 조심하십시오

그러나 MySQL 5.7.6 부터 옵티마이 저는 하위 쿼리를 최적화하고 여전히 오류를 줄 수 있습니다. 다행히 optimizer_switch변수를 사용하여이 동작을 끌 수 있습니다. 단기 수정 또는 소규모 일회성 작업 이외의 다른 작업으로는 권장하지 않습니다.

SET optimizer_switch = 'derived_merge=off';

의견 에이 조언을 준 Peter V. Mørch 에게 감사드립니다 .

예시 기술은 원래 Nabble에 출판 된 Baron Schwartz의 기술 입니다.


답변

NexusRex 는 동일한 테이블에서 조인을 사용하여 삭제 하는 데 매우 유용한 솔루션 을 제공했습니다 .

이렇게하면 :

DELETE FROM story_category
WHERE category_id NOT IN (
        SELECT DISTINCT category.id AS cid FROM category
        INNER JOIN story_category ON category_id=category.id
)

오류가 발생합니다.

그러나 조건을 한 번 더 선택하면 다음을 선택하십시오.

DELETE FROM story_category
WHERE category_id NOT IN (
    SELECT cid FROM (
        SELECT DISTINCT category.id AS cid FROM category
        INNER JOIN story_category ON category_id=category.id
    ) AS c
)

그것은 옳은 일을 할 것입니다 !!

Explanation : 쿼리 최적화 프로그램이 첫 번째 쿼리에 대해 파생 된 병합 최적화 를 수행하지만 (오류로 인해 실패 함) 두 번째 쿼리는 파생 된 병합 최적화에 적합하지 않습니다 . 따라서 옵티마이 저는 먼저 서브 쿼리를 실행해야합니다.


답변

inner join귀하의 하위 쿼리는 불필요하다. 가 표에 없는 story_category곳의 항목을 삭제하려는 것 같습니다 .category_idcategory

이 작업을 수행:

DELETE FROM story_category
WHERE category_id NOT IN (
    SELECT DISTINCT category.id
    FROM category);

그것 대신에:

DELETE FROM story_category
WHERE category_id NOT IN (
    SELECT DISTINCT category.id
    FROM category INNER JOIN
         story_category ON category_id=category.id);


답변

최근에 같은 테이블에서 레코드를 업데이트해야했습니다. 아래와 같이했습니다.

UPDATE skills AS s, (SELECT id  FROM skills WHERE type = 'Programming') AS p
SET s.type = 'Development'
WHERE s.id = p.id;


답변

DELETE FROM story_category
WHERE category_id NOT IN (
    SELECT cid FROM (
        SELECT DISTINCT category.id AS cid FROM category INNER JOIN story_category ON category_id=category.id
    ) AS c
)


답변

할 수 없다면

UPDATE table SET a=value WHERE x IN
    (SELECT x FROM table WHERE condition);

같은 테이블이기 때문에 속임수를 쓸 수 있습니다.

UPDATE table SET a=value WHERE x IN
    (SELECT * FROM (SELECT x FROM table WHERE condition) as t)

[업데이트 또는 삭제 또는 무엇이든]


답변

이것은 하나 이상의 행에 Priority = 1이 포함되도록 테이블의 하위 쿼리를 사용하여 WHERE 절과 테이블에서> = 1 인 경우 Priority 열 값을 1로 업데이트하기 위해 수행 한 작업입니다. 업데이트를 수행하는 동안 확인할 조건) :


UPDATE My_Table
SET Priority=Priority + 1
WHERE Priority >= 1
AND (SELECT TRUE FROM (SELECT * FROM My_Table WHERE Priority=1 LIMIT 1) as t);

나는 그것이 못생긴다는 ​​것을 알고 있지만 잘 작동합니다.