Ich benutze eine rekursive gespeicherte Prozedur in MySQL, um eine temporäre Tabelle mit dem Namen zu generieren id_list
, aber ich muss die Ergebnisse dieser Prozedur in einer nachfolgenden Auswahlabfrage verwenden, damit ich DROP
die temporäre Tabelle in der Prozedur nicht verwenden kann ...
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;
Beim Aufrufen der Prozedur ist der erste Wert die oberste ID des gewünschten Zweigs und der zweite Wert die, tier
die die Prozedur bei Rekursionen verwendet. Vor der rekursiven Schleife wird geprüft, ob tier = 0
und ob sie ausgeführt wird:
DROP TEMPORARY TABLE IF EXISTS id_list;
CREATE TEMPORARY TABLE IF NOT EXISTS id_list (iid CHAR(32) NOT NULL) ENGINE=memory;
Meine Frage lautet also: Wenn ich DROP
die temporäre MEMORY
Tabelle am Ende des Vorgangs oder innerhalb meiner Transaktion nicht erhalte, wie lange bleibt diese Tabelle im Speicher? Wird es nach Beendigung der Sitzung automatisch gelöscht oder verbleibt es im Speicher, solange die Verbindung geöffnet ist?
** NB Die naheliegende Antwort könnte darin bestehen, die temporäre Tabelle vor der Festschreibungsanweisung zu löschen, aber nehmen wir für einen Moment an, dass ich das nicht kann. *
EDIT : Genauer gesagt, was passiert, wenn dauerhafte Verbindungen verwendet werden, bleibt die Tabelle bei mehreren Anforderungen bestehen? Bisher scheint es so zu sein und wir müssten die temporäre Tabelle explizit entfernen, um diese Ressource freizugeben.
UPDATE : Basierend auf den Ratschlägen der Kommentatoren habe ich eine Möglichkeit gefunden, meine gespeicherte Prozedur so anzupassen, dass ich die TEMP MEMORY-Tabelle verwenden kann, sie aber DROP
am Ende explizit verwenden kann ...
Anstatt nur die gespeicherte Prozedur aufzurufen und die verbleibende TEMP-Tabelle zu verwenden, um die Ergebnisse in der tatsächlichen Abfrage zu erfassen, habe ich das CALL
Format geändert , um eine dritte OUT
Variable wie die folgende zu verwenden :
CALL fetch_inheritance_groups('abc123','0',@IDS);
... dann habe ich innerhalb der gespeicherten Prozedur IF tier = 0
ganz am Ende eine Sekunde mit folgendem hinzugefügt :
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;
Das Ergebnis der gespeicherten Prozedur ist nun eine durch Kommas getrennte Liste von IDs, mit denen kompatibel FIND_IN_SET
ist. Die endgültige Abfrage wurde folgendermaßen geändert:
WHERE r.Group_ID = 'abc123' OR r.Group_ID IN (SELECT * FROM id_list)
... ist jetzt ...
WHERE r.Group_ID = 'abc123' OR FIND_IN_SET(r.Group_ID,@IDS)
Voila! Vielen Dank an die Kommentatoren für deinen Beitrag und dafür, dass du mir den Grund gegeben hast, warum ich mich ein bisschen mehr anstrengen musste :)
DROP
den temporären MEMORY explizit benötigen Tabelle. Gehe ich richtig ausSELECT
Anweisung in gespeicherten Prozeduren (DECLARE aCursor CURSOR FOR SELECT ...
) verwenden können? Z.B.DECLARE theCursor CURSOR FOR CALL aProcedure()
?In den meisten DBMSs bleiben temporäre Tabellen bis zum Ende der aktuellen Verbindung erhalten, sofern nichts anderes angegeben ist oder es kein explizites Transaktionsrollback gibt (in einigen Systemen wirkt sich ein Rollback möglicherweise nur auf den Inhalt der Tabelle aus, sodass das Objekt selbst bei Bedarf neu aufgefüllt werden muss). . Die Tabelle ist (standardmäßig) für andere Verbindungen nicht sichtbar, unabhängig davon, wie lange die Verbindung, die sie erstellt, dauert.
Ein schneller Scan bei Google scheint zu zeigen, wie mySQL funktioniert.
( http://www.tutorialspoint.com/mysql/mysql-temporary-tables.htm besagt, dass standardmäßig alle temporären Tabellen von MySQL gelöscht werden, wenn Ihre Datenbankverbindung beendet wird. Standardmäßig werden alle temporären Tabellen von MySQL gelöscht, wenn Ihre Datenbankverbindung wird beendet ")
Es gibt jedoch oft Möglichkeiten, diese Verhaltensweisen zu ändern. Beispielsweise können Sie in MS SQL Server eine temporäre Tabelle erstellen, die für alle Verbindungen sichtbar ist, anstatt nur für die aktuelle, indem Sie ihr einen Namen geben, der mit ## beginnt.
Ich lösche temporäre Tabellen immer, sobald sie nicht mehr benötigt werden, um mögliche Verwirrung zu vermeiden. Ich bin schon gebissen worden, als das Zusammenlegen von Verbindungen zu Fehlern bei der temporären Tabellenerstellung führte, da in einer früheren Aktion, in der die aktuelle Verbindung verwendet wurde, eine temporäre Tabelle mit demselben Namen erstellt, aber nicht zerstört wurde.
quelle
DROP
vor der Neuerstellung in der IF der ersten Ebene verwenden. Danke für deinen Beitrag!/ * gegebene Abfrage liefert erfolgreiches Ergebnis ... wenn diese Abfrage in USP gestellt wird, wird der Fehler angezeigt. Bitte helfen Sie mir.
CALL usp_GetEngMonthlyChart_Test ('2014-01-01', '2015-07-30')
quelle