J'utilise une procédure stockée récursive dans MySQL pour générer une table temporaire appelée id_list
, mais je dois utiliser les résultats de cette procédure dans une requête de sélection de suivi, donc je ne peux pas DROP
la table temporaire dans la procédure ...
BEGIN;
/* generates the temporary table of ID's */
CALL fetch_inheritance_groups('abc123',0);
/* uses the results of the stored procedure in the WHERE */
SELECT a.User_ID
FROM usr_relationships r
INNER JOIN usr_accts a ON a.User_ID = r.User_ID
WHERE r.Group_ID = 'abc123' OR r.Group_ID IN (SELECT * FROM id_list)
GROUP BY r.User_ID;
COMMIT;
Lors de l'appel de la procédure, la première valeur est l'ID supérieur de la branche que je veux, et la seconde est celle tier
que la procédure utilise lors des récursions. Avant la boucle récursive, il vérifie si tier = 0
et si elle est exécutée:
DROP TEMPORARY TABLE IF EXISTS id_list;
CREATE TEMPORARY TABLE IF NOT EXISTS id_list (iid CHAR(32) NOT NULL) ENGINE=memory;
Ma question est donc la suivante: si je n'utilise pas DROP
la MEMORY
table temporaire à la fin de la procédure ou dans ma transaction, combien de temps cette table persistera-t-elle en mémoire? Est-il automatiquement supprimé une fois la session terminée ou restera-t-il en mémoire tant que la connexion sera ouverte?
** NB La réponse évidente pourrait être de supprimer la table temporaire avant l'instruction commit, mais supposons un instant que je ne peux pas faire ça. *
EDIT : Pour être un peu plus précis, que se passe-t-il si des connexions persistantes sont utilisées, la table persistera-t-elle à travers plusieurs requêtes? Jusqu'à présent, il semble que ce sera le cas et que nous devions supprimer explicitement la table temporaire pour libérer cette ressource.
MISE À JOUR : Sur la base des conseils des commentateurs, j'ai trouvé un moyen d'ajuster ma procédure stockée afin que je puisse utiliser la table TEMP MEMORY, mais pouvoir l'expliciter DROP
à la fin ...
Plutôt que d'appeler simplement la procédure stockée et d'utiliser la table TEMP restante pour rassembler les résultats dans la requête réelle, j'ai changé le CALL
format pour utiliser une troisième OUT
variable comme ceci:
CALL fetch_inheritance_groups('abc123','0',@IDS);
... puis dans la procédure stockée, j'ai ajouté une seconde IF tier = 0
à la fin avec ce qui suit:
IF tier = 0
THEN
SELECT GROUP_CONCAT(DISTINCT iid SEPARATOR ',') FROM id_list INTO inherited_set;
DROP TEMPORARY TABLE IF EXISTS id_list;
END IF;
Ainsi, le résultat de la procédure stockée est maintenant une liste d'ID séparés par des virgules qui est compatible avec FIND_IN_SET
, et donc la requête finale a été modifiée de sorte que:
WHERE r.Group_ID = 'abc123' OR r.Group_ID IN (SELECT * FROM id_list)
... est maintenant ...
WHERE r.Group_ID = 'abc123' OR FIND_IN_SET(r.Group_ID,@IDS)
Voila! Merci aux commentateurs pour votre contribution et pour m'avoir donné la raison pour laquelle je devais essayer un peu plus fort :)
DROP
la MEMORY temporaire table. Dois-je supposer correctement?SELECT
instruction dans les procédures stockées (DECLARE aCursor CURSOR FOR SELECT ...
)? Par exemple.DECLARE theCursor CURSOR FOR CALL aProcedure()
?Dans la plupart des SGBD, les tables temporaires survivent jusqu'à la fin de la connexion actuelle, sauf indication contraire ou à moins qu'il n'y ait une annulation explicite des transactions (dans certains systèmes, une annulation peut uniquement affecter le contenu de la table, laissant l'objet lui-même autour pour être repeuplé si nécessaire) . Le tableau ne sera pas (par défaut) visible pour les autres connexions, quelle que soit la durée de la connexion qui le crée.
Une analyse rapide sur Google semble indiquer que c'est ainsi que fonctionne mySQL.
( http://www.tutorialspoint.com/mysql/mysql-temporary-tables.htm déclare "par défaut, toutes les tables temporaires sont supprimées par MySQL lorsque votre connexion à la base de données prend fin. Par défaut, toutes les tables temporaires sont supprimées par MySQL lorsque votre connexion à la base de données est interrompue ")
Cependant, il existe souvent des moyens de modifier ces comportements. Par exemple, dans MS SQL Server, vous pouvez créer une table temporaire qui est visible pour toutes les connexions au lieu de la seule en cours en lui donnant un nom commençant par ##.
Je laisse toujours tomber les tables temporaires dès qu'elles ne sont plus nécessaires pour éviter toute confusion possible. J'ai déjà été mordu lorsque le regroupement de connexions a entraîné la création d'une table temporaire provoquant des erreurs, car une table temporaire du même nom a été créée mais n'a pas été détruite lors d'une action précédente qui a utilisé la connexion actuelle.
la source
DROP
avant de recréer dans l'IF du niveau initial. Merci pour votre contribution!/ * la requête donnée donne un résultat avec succès ... lorsque vous placez cette requête dans USP, puis affichez l'erreur plz help me..proc est donné ci-dessous * /
CALL usp_GetEngMonthlyChart_Test ('2014-01-01', '2015-07-30')
la source