Ошибка 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

    Каков наилучший способ фильтрации коллекции Java?

    Сортировка коллекций (список , метод сравнения )

    C ++ Возвращаемая ссылка на локальную переменную

    Как решить «не удалось лениво инициализировать сборку роли» Исключение Hibernate

    Как просмотреть данные в файле sqlite, запущенном в приложении iphone?

    Компиляция с помощью g ++ с использованием нескольких ядер

    Как автоматически вставить пустую строку после группы данных

    Что такое таблица стилей пользовательского агента

    использование статических библиотек вместо динамических библиотек в opencv

    Ядро Linux – не могу получить доступ к sda16 & sda17

    Поддержание и синхронизация зеркального удаленного репозитория Git

    Какие зависимости maven включать весной 3.0?

    «Ошибка раздувания fragmentа classа» с помощью google map

    Определите, работает ли на корневом устройстве

    Показывать только числовые кнопки на Soft Keyboard в Android?

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