Ошибка 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 – Вы не можете указать целевую таблицу «story_category» для обновления в предложении FROM

Как я могу это преодолеть?

    14 Solutions collect form web for “Ошибка MySQL 1093 – Невозможно указать целевую таблицу для обновления в предложении FROM”

    Обновление: этот ответ охватывает общую classификацию ошибок. Для более конкретного ответа о том, как лучше всего обрабатывать точный запрос 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. Mørch за этот совет в комментариях.

    Примерный метод был от барона Шварца, первоначально опубликованного в Наббл , перефразированного и расширенного здесь.

    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 ) 

    это будет правильно!

    Объяснение: Оптимизатор запросов выполняет определенную оптимизацию слияния для первого запроса (что приводит к сбою с ошибкой), но второй запрос не подходит для оптимизации производного слияния, поэтому оптимизатор вынужден сначала выполнить подзапрос.

    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) 

    [обновить или удалить или что-то еще]

    Это то, что я сделал для обновления значения столбца Priority на 1, если это = = 1 в таблице и в его предложении WHERE, используя подзапрос в той же таблице, чтобы удостовериться, что хотя бы одна строка содержит 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); 

    Я знаю, что это немного уродливо, но все работает отлично.

    Вы можете вставить идентификаторы требуемых строк в временную таблицу, а затем удалить все строки, найденные в этой таблице.

    что может быть тем, что @Cheekysoft означало, делая это за два шага.

    В соответствии с синтаксисом Mysql UPDATE, связанным с @CheekySoft, он говорит прямо внизу.

    В настоящее время вы не можете обновить таблицу и выбрать из той же таблицы в подзапросе.

    Я думаю, что вы удаляете из 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; 

    Это быстро. Чем больше данных, тем лучше.

    Попытайтесь сохранить результат оператора Select в отдельной переменной, а затем используйте это для запроса на удаление.

    как насчет этого запроса надеюсь, что это поможет

     DELETE FROM story_category LEFT JOIN (SELECT category.id FROM category) cat ON story_category.id = cat.id WHERE cat.id IS NULL 

    Самый простой способ сделать это – использовать псевдоним таблицы, когда вы ссылаетесь на родительскую таблицу запросов внутри подзапроса.

    Пример :

     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; 
    Interesting Posts

    django orm, как просмотреть (или зарегистрировать) выполненный запрос?

    Есть ли программное обеспечение, которое может сканировать веб-страницу, обнаруживать все файлы с заданным расширением и загружать их все?

    Динамик Thinkpad отключается – проблема с Linux Codec?

    Что происходит, когда ядро ​​Windows сталкивается с ошибкой, которую он не может решить

    Как получить доступ к сайту, который вы используете в своей сети?

    Почему вы не должны расширять JFrame и другие компоненты?

    В чем разница между CSV (MS-Dos), CSV (Macintosh), CSV (с разделителями-запятыми)

    Разрешения для обычного общего веб-хоста Linux

    dcast error: «Отсутствует функция агрегирования: по умолчанию – длина»

    Установите Windows XP / 7 без дисковода компакт-дисков, когда BIOS не поддерживает загрузку с USB-устройств

    Разница между ApiController и controllerом в ASP.NET MVC

    Можно ли объявить dispatch_once_t предикат как переменную-член вместо статического?

    Заставить JSON.NET включать миллисекунды при сериализации DateTime (даже если компонент ms равен нулю)

    Как импортировать API javax.servlet в проект Eclipse?

    Что ДЕЙСТВИТЕЛЬНО происходит, когда вы не свободны после malloc?

    Давайте будем гением компьютера.