Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Pernyataan yang Disiapkan MySQL - Cara Melakukan Loop Through

Seperti yang telah disarankan orang lain, kami biasanya menghindari mengulang melalui kumpulan hasil RBAR (baris demi baris yang menyiksa) terutama untuk alasan kinerja. Kami hanya tidak ingin membiasakan diri mengulang-ulang hasil. Tapi itu tidak menjawab pertanyaan yang Anda ajukan.

Untuk menjawab pertanyaan yang Anda ajukan, berikut adalah contoh dasar dari program tersimpan MySQL yang menggunakan CURSOR untuk memproses baris yang dikembalikan oleh kueri satu per satu. MySQL tidak mendukung blok anonim, jadi satu-satunya cara untuk melakukannya adalah dalam program tersimpan MySQL, seperti PROSEDUR

DELIMITER $$

CREATE PROCEDURE loop_through_var_list
BEGIN
   DECLARE done INT DEFAULT 0;
   DECLARE v_id INT DEFAULT NULL;  
   DECLARE csr_var_list CURSOR FOR SELECT id FROM var_list ORDER BY id;
   DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
   OPEN csr_var_list;
   get_id: LOOP
      FETCH csr_var_list INTO v_id; 
      IF done = 1 THEN
         LEAVE get_id;
      END IF;

      -- at this point, we have an id value in v_id, so we can do whatever
      SET @s1 = CONCAT('SELECT ... WHERE id =''', v_id, ''' ...');


   END LOOP get_id;
   CLOSE csr_var_list;
END$$

DELIMITER ;

Untuk menjalankan prosedur:

CALL loop_through_var_list();

CATATAN:Sintaks untuk memproses CURSOR di MySQL sedikit berbeda dari database lain.

Untuk mendapatkan "perulangan", kita perlu menggunakan LOOP ... END LOOP konstruksi.

Namun untuk mencegah loop tersebut berjalan selamanya, kita memerlukan pernyataan LEAVE yang memungkinkan kita untuk keluar dari loop.

Kami menggunakan tes bersyarat untuk menentukan kapan harus pergi. Dalam contoh ini, kita ingin keluar setelah kita selesai memproses baris terakhir.

FETCH akan mengeluarkan pengecualian ketika tidak ada lagi baris yang akan diambil.

Kami "menangkap" pengecualian itu dalam CONTINUE HANDLER (untuk beberapa alasan misterius, "penangan" harus mendeklarasikan hal-hal terakhir; MySQL membuat kesalahan jika kami mencoba mendeklarasikan sesuatu setelah HANDLER (selain HANDLER lain.)

Ketika MySQL melempar pengecualian "tidak ada lagi baris", itu akan mengaktifkan kode handler. Dalam contoh ini, kami hanya mengatur variabel (bernama done ) ke suatu nilai.

Karena ini adalah handler "lanjutkan", pemrosesan dimulai kembali pada pernyataan di mana pengecualian dilemparkan, dalam hal ini, itu akan menjadi pernyataan setelah FETCH. Jadi, hal pertama yang kita lakukan adalah memeriksa apakah kita sudah "selesai" atau belum. Jika kita "selesai", maka kita keluar dari loop, dan menutup kursor.

Jika tidak, kami tahu bahwa kami memiliki id nilai dari var_list disimpan dalam variabel prosedur bernama v_id . Jadi sekarang kita bisa melakukan apapun yang kita mau. Sepertinya Anda ingin memasukkan beberapa teks SQL ke dalam variabel yang ditentukan pengguna (termasuk nilai v_id ke dalam teks SQL, lalu PREPARE, EXECUTE, dan DEALLOCATE PREPARE.

Pastikan untuk mendeklarasikan v_id variabel dengan tipe data yang sesuai, yang cocok dengan tipe data id kolom di var_list , saya baru saja berasumsi bahwa itu adalah INT.

Saat kita mencapai akhir loop, MySQL "mengulang" kembali ke awal loop, dan kita mulai lagi.

Di badan loop, kemungkinan Anda ingin CONCAT v_id ke dalam teks SQL yang ingin Anda jalankan. Sepertinya Anda sudah memiliki pegangan pada PREPARE, DEALLOCATE mempersiapkan. Untuk pengujian, Anda mungkin ingin menambahkan klausa LIMIT pada SELECT dalam deklarasi kursor, dan kemudian melakukan v_id SELECT sederhana; di isi, hanya untuk memverifikasi loop berfungsi, sebelum Anda menambahkan lebih banyak kode.

TINDAK LANJUT

Saya ingin menyebutkan pendekatan alternatif lain untuk tugas tersebut, yaitu menjalankan serangkaian pernyataan berdasarkan template, menggantikan nilai yang diberikan dari satu pernyataan pilih SQL...

Misalnya, jika saya memiliki template ini:

SELECT * 
  INTO OUTFILE '/tmp/[email protected]'
  FIELDS TERMINATED BY ',' ENCLOSED BY '"'
  LINES TERMINATED BY '\n'
FROM data 
WHERE id = @ID
ORDER BY 1 

dan saya perlu mengganti kemunculan @ID dengan nilai id tertentu dari daftar yang dikembalikan dari pernyataan SELECT, mis.

SELECT id
  FROM var_list
 WHERE id IS NOT NULL
 GROUP BY id

Saya mungkin tidak akan menggunakan program tersimpan MySQL dengan loop CURSOR, saya akan menggunakan pendekatan yang berbeda.

Saya akan menggunakan pernyataan SELECT untuk menghasilkan satu set pernyataan SQL yang dapat dieksekusi. Dengan asumsi id adalah tipe integer, saya mungkin akan melakukan sesuatu seperti ini:

SELECT CONCAT(' SELECT * 
                   INTO OUTFILE ''/tmp/orders_',s.id,'.csv''
                   FIELDS TERMINATED BY '','' ENCLOSED BY ''"''
                   LINES TERMINATED BY ''\n''
                FROM data
               WHERE id = ',s.id,'
               ORDER BY 1;') AS `stmt`
 FROM ( SELECT v.id
          FROM var_list v
         WHERE v.id IS NOT NULL
         GROUP BY v.id
      ) s
ORDER BY s.id

Untuk setiap nilai id dikembalikan dari s , pernyataan mengembalikan teks pernyataan SQL SELECT yang dapat (dan perlu) dijalankan. Menangkapnya ke dalam file teks akan memberi saya skrip SQL yang bisa saya jalankan.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Menggunakan indeks pencarian Solr sebagai database - apakah ini salah?

  2. Cara membuat Pemicu untuk menambahkan peristiwa perubahan ke dalam tabel Log Audit

  3. Cara Mengimpor Database Menggunakan phpMyAdmin

  4. Perbedaan TimeZone di mysql dan java

  5. MySQL Query ORDER BY nilai-nilai tertentu sebelum yang lain