J’ai une table story_category
dans ma firebase database avec des entrées corrompues. La requête suivante renvoie les entrées corrompues:
SELECT * FROM story_category WHERE category_id NOT IN ( SELECT DISTINCT category.id FROM category INNER JOIN story_category ON category_id=category.id);
J’ai essayé de les supprimer en cours d’exécution:
DELETE FROM story_category WHERE category_id NOT IN ( SELECT DISTINCT category.id FROM category INNER JOIN story_category ON category_id=category.id);
Mais je reçois la prochaine erreur:
# 1093 – Vous ne pouvez pas spécifier la table cible ‘story_category’ pour la mise à jour dans la clause FROM
- L’hôte ‘xxx.xx.xxx.xxx’ n’est pas autorisé à se connecter à ce serveur MySQL
- Quand utiliser MongoDB ou d’autres systèmes de firebase database orientés document?
- Chaîne MySQL remplacer
- Comment réduire / purger le fichier ibdata1 dans MySQL
- Comment désactiver temporairement une contrainte de clé étrangère dans MySQL?
Comment puis-je surmonter cela?
Mise à jour: cette réponse couvre la classification d’erreur générale. Pour une réponse plus précise sur la meilleure façon de traiter la requête exacte de l’OP, veuillez consulter les autres réponses à cette question.
Dans MySQL, vous ne pouvez pas modifier la même table que celle utilisée dans la partie SELECT.
Ce comportement est documenté à l’ adresse suivante : http://dev.mysql.com/doc/refman/5.6/en/update.html
Peut-être que vous pouvez simplement joindre la table à elle-même
Si la logique est suffisamment simple pour redéfinir la requête, perdez la sous-requête et joignez la table à elle-même, en utilisant les critères de sélection appropriés. Cela amènera MySQL à voir la table comme deux choses différentes, permettant des modifications destructives.
UPDATE tbl AS a INNER JOIN tbl AS b ON .... SET a.col = b.col
Sinon, essayez d’imbriquer la sous-requête plus profondément dans une clause from …
Si vous avez absolument besoin de la sous-requête, il y a une solution de contournement, mais c’est moche pour plusieurs raisons, y compris la performance:
UPDATE tbl SET col = ( SELECT ... FROM (SELECT.... FROM) AS x);
La sous-requête nestede dans la clause FROM crée une table temporaire implicite , elle ne compte donc pas comme la même table que celle mise à jour.
… mais attention à l’optimiseur de requêtes
Cependant, méfiez-vous de MySQL 5.7.6 et versions ultérieures, l’optimiseur peut optimiser la sous-requête, tout en vous donnant l’erreur. Heureusement, la variable optimizer_switch
peut être utilisée pour désactiver ce comportement. Bien que je ne puisse pas recommander de le faire autrement que comme une solution à court terme ou pour de petites tâches ponctuelles.
SET optimizer_switch = 'derived_merge=off';
Merci à Peter V. Mørch pour ces conseils dans les commentaires.
Exemple de technique de Baron Schwartz, initialement publié à Nabble , paraphrasé et étendu ici.
NexusRex a fourni une très bonne solution pour supprimer avec la jointure de la même table.
Si tu fais ça:
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 )
vous allez obtenir une erreur.
Mais si vous enveloppez la condition dans une autre sélection
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 )
ça ferait la bonne chose !!
Explication: L’optimiseur de requête effectue une optimisation de fusion dérivée pour la première requête (ce qui entraîne son échec avec l’erreur), mais la deuxième requête n’est pas qualifiée pour l’ optimisation de fusion dérivée. Par conséquent, l’optimiseur doit d’abord exécuter la sous-requête.
La inner join
de votre sous-requête est inutile. Il semblerait que vous souhaitiez supprimer les entrées de story_category
où le story_category
category_id
ne figure pas dans la table category
.
Faites ceci:
DELETE FROM story_category WHERE category_id NOT IN ( SELECT DISTINCT category.id FROM category);
Au lieu de:
DELETE FROM story_category WHERE category_id NOT IN ( SELECT DISTINCT category.id FROM category INNER JOIN story_category ON category_id=category.id);
Récemment, j’ai dû mettre à jour des enregistrements dans la même table que je l’ai fait comme ci-dessous:
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 )
Si tu ne peux pas faire
UPDATE table SET a=value WHERE x IN (SELECT x FROM table WHERE condition);
parce que c’est la même table, vous pouvez tromper et faire:
UPDATE table SET a=value WHERE x IN (SELECT * FROM (SELECT x FROM table WHERE condition) as t)
[mettre à jour ou supprimer ou autre]
C’est ce que j’ai fait pour mettre à jour une valeur de colonne Priorité de 1 si elle est> = 1 dans une table et de sa clause WHERE en utilisant une sous-requête sur la même table pour vérifier qu’au moins une ligne contient Priorité = 1 condition à vérifier lors de la mise à jour):
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);
Je sais que c’est un peu moche mais ça marche très bien.
Vous pouvez insérer les identifiants de lignes souhaités dans une table temporaire, puis supprimer toutes les lignes de cette table.
C’est peut-être ce que @Cheekysoft a voulu faire en deux étapes.
Selon la syntaxe Mysql UPDATE liée par @CheekySoft, il est indiqué tout en bas.
Actuellement, vous ne pouvez pas mettre à jour une table et la sélectionner dans la même table dans une sous-requête.
Je suppose que vous supprimez de store_category tout en le sélectionnant dans l’union.
Si quelque chose ne fonctionne pas, en passant par la porte d’entrée, prenez la porte arrière:
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;
C’est rapide. Plus les données sont grandes, mieux c’est.
Essayez d’enregistrer le résultat de l’instruction Select dans une variable distincte, puis utilisez-la pour la requête de suppression.
que diriez-vous de cette requête espère que cela aide
DELETE FROM story_category LEFT JOIN (SELECT category.id FROM category) cat ON story_category.id = cat.id WHERE cat.id IS NULL
La méthode la plus simple consiste à utiliser un alias de table lorsque vous faites référence à une table de requête parent dans la sous-requête.
Exemple :
insert into xxx_tab (trans_id) values ((select max(trans_id)+1 from xxx_tab));
Changez le pour:
insert into xxx_tab (trans_id) values ((select max(P.trans_id)+1 from xxx_tab P));
essaye ça
DELETE FROM story_category WHERE category_id NOT IN ( SELECT DISTINCT category.id FROM (SELECT * FROM STORY_CATEGORY) sc;