Saya menggunakan prosedur tersimpan rekursif di MySQL untuk menghasilkan tabel sementara bernama id_list
, tapi saya harus menggunakan hasil prosedur itu dalam tindak lanjut pilih kueri, jadi saya tidak bisa DROP
tabel sementara dalam prosedur ...
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;
Saat memanggil prosedur, nilai pertama adalah ID teratas dari cabang yang saya inginkan, dan yang kedua adalah tier
yang digunakan prosedur selama rekursi. Sebelum loop rekursif ia memeriksa apakah tier = 0
dan apakah itu berjalan:
DROP TEMPORARY TABLE IF EXISTS id_list;
CREATE TEMPORARY TABLE IF NOT EXISTS id_list (iid CHAR(32) NOT NULL) ENGINE=memory;
Jadi pertanyaan saya adalah: Jika saya tidak tabel DROP
sementara MEMORY
di akhir prosedur, atau dalam transaksi saya, berapa lama tabel itu akan bertahan dalam memori? Apakah itu secara otomatis terjatuh setelah sesi berakhir, atau akankah itu tetap ada dalam memori selama koneksi terbuka?
** NB Jawaban yang jelas mungkin untuk menjatuhkan tabel temp sebelum pernyataan komit, tetapi mari kita asumsikan sejenak bahwa saya tidak bisa melakukan itu. *
EDIT : Untuk menjadi sedikit lebih tepat, bagaimana jika koneksi persisten digunakan, akankah tabel bertahan melalui beberapa permintaan? Sejauh ini tampaknya itu akan dan bahwa kita akan perlu secara eksplisit menghapus tabel temp untuk membebaskan sumber daya itu.
PEMBARUAN : Berdasarkan saran dari para komentator, saya telah menemukan cara untuk menyesuaikan prosedur tersimpan saya sehingga saya dapat memanfaatkan tabel TEMP MEMORY, tetapi dapat secara eksplisit DROP
di akhir ...
Daripada hanya memanggil prosedur tersimpan dan menggunakan tabel TEMP yang tersisa untuk mengumpulkan hasil dalam kueri yang sebenarnya, saya telah mengubah CALL
format untuk menggunakan OUT
variabel ketiga seperti:
CALL fetch_inheritance_groups('abc123','0',@IDS);
... lalu dalam prosedur tersimpan, saya menambahkan sedetik IF tier = 0
di bagian paling akhir dengan yang berikut:
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;
Jadi hasil dari prosedur yang tersimpan sekarang adalah daftar ID yang dipisahkan koma yang kompatibel dengan FIND_IN_SET
, dan permintaan akhir telah dimodifikasi sehingga:
WHERE r.Group_ID = 'abc123' OR r.Group_ID IN (SELECT * FROM id_list)
... sekarang ...
WHERE r.Group_ID = 'abc123' OR FIND_IN_SET(r.Group_ID,@IDS)
Voila! Terima kasih kepada komentator atas masukan Anda, dan untuk memberi saya alasan saya perlu mencoba sedikit lebih keras :)
DROP
MEMORY sementara meja. Apakah saya berasumsi dengan benar?SELECT
pernyataan dalam prosedur tersimpan (DECLARE aCursor CURSOR FOR SELECT ...
)? E. g.DECLARE theCursor CURSOR FOR CALL aProcedure()
?Dalam sebagian besar tabel sementara DBMS bertahan sampai akhir koneksi saat ini kecuali dinyatakan sebaliknya atau kecuali ada rollback transaksi eksplisit (dalam beberapa sistem rollback hanya dapat mempengaruhi konten tabel, meninggalkan objek itu sendiri di sekitar untuk dihuni kembali jika diperlukan) . Tabel tidak akan (secara default) terlihat oleh koneksi lain tidak peduli berapa lama koneksi yang membuatnya berlangsung.
Pemindaian cepat di Google tampaknya mengindikasikan ini adalah cara mySQL beroperasi.
( http://www.tutorialspoint.com/mysql/mysql-temporary-tables.htm menyatakan "secara default, semua tabel sementara dihapus oleh MySQL saat koneksi basis data Anda diakhiri. Secara default, semua tabel sementara dihapus oleh MySQL saat koneksi basis data Anda akan dihentikan ")
Seringkali ada cara untuk mengubah perilaku ini. Misalnya di MS SQL Server Anda bisa membuat tabel sementara yang terlihat oleh semua koneksi, bukan hanya yang sekarang dengan memberinya nama yang dimulai ##.
Saya selalu menjatuhkan tabel sementara segera setelah mereka tidak lagi diperlukan untuk menghindari kemungkinan kebingungan. Saya telah digigit sebelumnya di mana penyatuan koneksi mengakibatkan pembuatan tabel sementara menyebabkan kesalahan karena sebuah tabel sementara dengan nama yang sama telah dibuat tetapi tidak dihancurkan dalam tindakan sebelumnya yang menggunakan koneksi saat ini.
sumber
DROP
sebelum membuat ulang dalam IF tingkat awal. Terima kasih atas masukan Anda!/ * kueri yang diberikan berhasil memberikan hasil ... ketika menempatkan kueri ini di USP kemudian menunjukkan kesalahan tolong bantu..proc diberikan di bawah ini * /
CALL usp_GetEngMonthlyChart_Test ('2014-01-01', '2015-07-30')
sumber