Oracle
 sql >> Teknologi Basis Data >  >> RDS >> Oracle

Deteksi siklus dengan anjak subquery rekursif

Dari dokumentasi di CONNECT_BY_ISCYCLE :

CONNECT_BY_ISCYCLE pseudocolumn mengembalikan 1 jika baris saat ini memiliki anak yang juga merupakan leluhurnya

dan pada CYCLE :

Sebuah baris dianggap membentuk siklus jika salah satu baris leluhurnya memiliki nilai yang sama untuk kolom siklus.

Dalam contoh Anda, baris 2 memang memiliki anak yang juga nenek moyangnya, tetapi id belum dikembalikan.

Dengan kata lain, CONNECT_BY_ISCYCLE memeriksa anak-anak (yang belum dikembalikan), sedangkan CYCLE memeriksa baris saat ini (yang sudah dikembalikan).

CONNECT BY berbasis baris, sedangkan CTE rekursif 's berbasis set.

Perhatikan bahwa dokumentasi Oracle pada CYCLE menyebutkan "baris leluhur". Namun, secara umum, tidak ada konsep "baris leluhur" dalam CTE rekursif . Ini adalah operasi berbasis set yang dapat menghasilkan hasil sepenuhnya di luar pohon. Secara umum, bagian jangkar dan bagian rekursif bahkan dapat menggunakan tabel yang berbeda.

Sejak CTE rekursif 's adalah biasanya digunakan untuk membangun pohon hierarki, Oracle memutuskan untuk menambahkan cek siklus. Tetapi karena cara berbasis set rekursif CTE beroperasi, umumnya tidak mungkin untuk mengetahui apakah langkah berikutnya akan menghasilkan siklus atau tidak, karena tanpa definisi yang jelas tentang kondisi siklus "baris leluhur" juga tidak dapat ditentukan.

Untuk melakukan langkah "berikutnya", seluruh rangkaian "saat ini" harus tersedia, tetapi untuk menghasilkan setiap baris dari rangkaian saat ini (yang mencakup kolom siklus) kita hanya perlu memiliki hasil dari operasi "berikutnya".

Tidak masalah jika set saat ini selalu terdiri dari satu baris (seperti di CONNECT BY ), tetapi menjadi masalah jika operasi rekursif didefinisikan pada himpunan secara keseluruhan.

Tidak melihat ke Oracle 11 belum, tapi SQL Server mengimplementasikan CTE rekursif hanya dengan menyembunyikan CONNECT BY di belakang mereka, yang membutuhkan penempatan banyak batasan (semuanya secara efektif melarang semua operasi berbasis set).

PostgreSQL implementasi , di sisi lain, benar-benar berbasis set:Anda dapat melakukan operasi apa pun dengan bagian jangkar di bagian rekursif. Namun, tidak ada cara untuk mendeteksi siklus, karena siklus tidak didefinisikan sejak awal.

Seperti yang telah disebutkan sebelumnya, MySQL tidak menerapkan CTE sama sekali (tidak mengimplementasikan HASH JOIN 's atau MERGE JOIN s juga, hanya loop bersarang, jadi jangan kaget terlalu banyak).

Ironisnya, saya menerima surat hari ini tentang hal ini, yang akan saya bahas di blog saya.

Pembaruan:

CTE rekursif ada di SQL Server tidak lebih dari CONNECT BY menyamar. Lihat artikel ini di blog saya untuk detail yang mengejutkan:

  • SQL Server:apakah CTE rekursif benar-benar berbasis set?


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Skrip admin di R12.2 Ebuisness Suite

  2. Oracle:Menggabungkan beberapa hasil dalam subquery menjadi satu nilai yang dipisahkan koma

  3. Java SQLData - Transmisikan ke objek pengguna dengan daftar/array?

  4. MySQL setara dengan peringkat ORACLES ()

  5. ORA-01882:wilayah zona waktu tidak ditemukan