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

StackOverflow https://stackoverflow.com/questions/45494

문제

테이블이 있어요 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';

덕분에 피터 V.뫼르치 의견에 대한 조언을 얻으십시오.

예시 기술은 Baron Schwartz의 것이었습니다. Nabble에서 처음 출판됨, 여기에서 의역하고 확장했습니다.

다른 팁

넥서스렉스 제공 아주 좋은 솔루션 동일한 테이블에서 조인으로 삭제합니다.

이렇게 하면:

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
)

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

설명: 쿼리 최적화 프로그램은 다음을 수행합니다. 파생 병합 최적화 첫 번째 쿼리의 경우(오류로 인해 실패함) 두 번째 쿼리는 파생 병합 최적화.따라서 최적화 프로그램은 하위 쿼리를 먼저 실행해야 합니다.

그만큼 inner join 하위 쿼리에는 필요하지 않습니다.다음 항목을 삭제하려는 것 같습니다. story_category 어디에 category_id 에 없습니다 category 테이블.

이 작업을 수행:

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)

[업데이트, 삭제 등]

이것은 테이블에서 >=1인 경우 우선순위 열 값을 1씩 업데이트하고 동일한 테이블의 하위 쿼리를 사용하여 WHERE 절에서 적어도 하나의 행에 우선순위=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);

나는 그것이 약간 추악하다는 것을 알고 있지만 잘 작동합니다.

원하는 행의 ID를 임시 테이블에 삽입한 다음 해당 테이블에서 발견된 모든 행을 삭제할 수 있습니다.

이는 @Cheekysoft가 두 단계로 수행한다는 의미일 수 있습니다.

에 따르면 MySQL 업데이트 구문 @CheekySoft에 의해 연결되었으며 하단에 바로 표시되어 있습니다.

현재는 테이블을 업데이트하고 하위 쿼리의 동일한 테이블에서 선택할 수 없습니다.

Union에서 여전히 선택하는 동안 store_category에서 삭제하는 것 같습니다.

문제가 해결되지 않으면 앞문으로 들어올 때 뒷문을 이용하세요.

drop table if exists apples;
create table if not exists apples(variety char(10) primary key, price int);

insert into apples values('fuji', 5), ('gala', 6);

drop table if exists apples_new;
create table if not exists apples_new like apples;
insert into apples_new select * from apples;

update apples_new
    set price = (select price from apples where variety = 'gala')
    where variety = 'fuji';
rename table apples to apples_orig;
rename table apples_new to apples;
drop table apples_orig;

빠르다.데이터가 클수록 좋습니다.

이를 수행하는 가장 간단한 방법은 하위 쿼리 내에서 상위 쿼리 테이블을 참조할 때 테이블 별칭을 사용하는 것입니다.

예 :

insert into xxx_tab (trans_id) values ((select max(trans_id)+1 from xxx_tab));

다음으로 변경하세요.

insert into xxx_tab (trans_id) values ((select max(P.trans_id)+1 from xxx_tab P));

이 시도

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

Select 문의 결과를 별도의 변수에 저장한 후 삭제 쿼리에 사용해 보세요.

이 쿼리는 어떻습니까 도움이 되었기를 바랍니다

DELETE FROM story_category LEFT JOIN (SELECT category.id FROM category) cat ON story_category.id = cat.id WHERE cat.id IS NULL
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top