MySQL 오류 1093 - FROM 절에서 업데이트할 대상 테이블을 지정할 수 없습니다.
-
09-06-2019 - |
문제
테이블이 있어요 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