Datang ke SQL dari bahasa pemrograman lain, struktur kueri rekursif terlihat agak aneh. Berjalan melaluinya langkah demi langkah, dan tampaknya berantakan.
Perhatikan contoh sederhana berikut ini:
CREATE TABLE #NUMS
(N BIGINT);
INSERT INTO #NUMS
VALUES (3), (5), (7);
WITH R AS
(
SELECT N FROM #NUMS
UNION ALL
SELECT N*N AS N FROM R WHERE N*N < 10000000
)
SELECT N FROM R ORDER BY N;
Mari kita jalani saja.
Pertama, anggota anchor dieksekusi dan set hasil dimasukkan ke dalam R. Jadi R diinisialisasi ke {3, 5, 7}.
Kemudian, eksekusi turun di bawah UNION ALL dan anggota rekursif dieksekusi untuk pertama kalinya. Ini dijalankan pada R (yaitu, pada R yang saat ini kami miliki: {3, 5, 7}). Ini menghasilkan {9, 25, 49}.
Apa hubungannya dengan hasil baru ini? Apakah itu menambahkan {9, 25, 49} ke {3, 5, 7} yang ada, melabelkan gabungan R yang dihasilkan, dan kemudian melanjutkan dengan rekursi dari sana? Atau apakah itu mendefinisikan ulang R menjadi hanya hasil baru ini {9, 25, 49} dan melakukan semua penyatuan nanti?
Tidak ada pilihan yang masuk akal.
Jika R sekarang {3, 5, 7, 9, 25, 49} dan kami menjalankan iterasi rekursi berikutnya, maka kami akan berakhir dengan {9, 25, 49, 81, 625, 2401} dan kami telah hilang {3, 5, 7}.
Jika R sekarang hanya {9, 25, 49}, maka kami memiliki masalah pemberian label yang salah. R dipahami sebagai gabungan dari himpunan hasil anggota jangkar dan semua set hasil anggota rekursif berikutnya. Sedangkan {9, 25, 49} hanya komponen R. Ini bukan R penuh yang telah kami dapatkan sejauh ini. Oleh karena itu, menulis anggota rekursif sebagai memilih dari R tidak masuk akal.
Saya tentu menghargai apa yang telah dijelaskan oleh @Max Vernon dan @Michael S. Yaitu, bahwa (1) semua komponen dibuat hingga batas rekursi atau set nol, dan kemudian (2) semua komponen disatukan. Ini adalah bagaimana saya memahami rekursi SQL untuk benar-benar berfungsi.
Jika kami mendesain ulang SQL, mungkin kami akan menerapkan sintaks yang lebih jelas dan eksplisit, seperti ini:
WITH R AS
(
SELECT N
INTO R[0]
FROM #NUMS
UNION ALL
SELECT N*N AS N
INTO R[K+1]
FROM R[K]
WHERE N*N < 10000000
)
SELECT N FROM R ORDER BY N;
Semacam bukti induktif dalam matematika.
Masalah dengan rekursi SQL seperti saat ini adalah bahwa itu ditulis dengan cara yang membingungkan. Cara itu ditulis mengatakan bahwa setiap komponen dibentuk dengan memilih dari R, tetapi itu tidak berarti R penuh yang telah (atau, tampaknya telah) dibangun sejauh ini. Itu hanya berarti komponen sebelumnya.