Mô tả BOL của CTE đệ quy mô tả ngữ nghĩa của thực thi đệ quy như sau:
- Chia biểu thức CTE thành neo và các thành viên đệ quy.
- Chạy (các) thành viên neo tạo tập lệnh đầu tiên hoặc kết quả cơ sở (T0).
- Chạy (các) thành viên đệ quy với Ti làm đầu vào và Ti + 1 làm đầu ra.
- Lặp lại bước 3 cho đến khi một bộ trống được trả về.
- Trả về tập kết quả. Đây là ĐOÀN TẤT CẢ T0 đến Tn.
Lưu ý ở trên là một mô tả hợp lý . Thứ tự vật lý của các hoạt động có thể hơi khác nhau như được minh họa ở đây
Áp dụng điều này cho CTE của bạn, tôi sẽ mong đợi một vòng lặp vô hạn với mẫu sau
+-----------+---------+---+---+---+
| Invocation| Results |
+-----------+---------+---+---+---+
| 1 | 1 | 2 | 3 | |
| 2 | 4 | 5 | | |
| 3 | 1 | 2 | 3 | |
| 4 | 4 | 5 | | |
| 5 | 1 | 2 | 3 | |
+-----------+---------+---+---+---+
Bởi vì
select a
from cte
where a in (1,2,3)
là biểu thức Anchor. Điều này rõ ràng trở lại 1,2,3
nhưT0
Sau đó biểu thức đệ quy chạy
select a
from cte
except
select a
from r
Với 1,2,3
như đầu vào đó sẽ mang lại một sản lượng 4,5
như T1
sau đó cắm mà lại cho vòng tiếp theo của đệ quy sẽ trở lại 1,2,3
và vân vân vô thời hạn.
Đây không phải là những gì thực sự xảy ra tuy nhiên. Đây là kết quả của 5 lần đầu tiên
+-----------+---------+---+---+---+
| Invocation| Results |
+-----------+---------+---+---+---+
| 1 | 1 | 2 | 3 | |
| 2 | 1 | 2 | 4 | 5 |
| 3 | 1 | 2 | 3 | 4 |
| 4 | 1 | 2 | 3 | 5 |
| 5 | 1 | 2 | 3 | 4 |
+-----------+---------+---+---+---+
Từ việc sử dụng OPTION (MAXRECURSION 1)
và điều chỉnh tăng dần theo gia số 1
có thể thấy rằng nó bước vào một chu kỳ trong đó mỗi cấp độ liên tiếp sẽ liên tục chuyển đổi giữa đầu ra 1,2,3,4
và 1,2,3,5
.
Như thảo luận của @Quassnoi trong bài đăng trên blog này . Mẫu kết quả quan sát được như thể mỗi lần gọi đang thực hiện (1),(2),(3),(4),(5) EXCEPT (X)
ở đâu X
là hàng cuối cùng từ lần gọi trước.
Chỉnh sửa: Sau khi đọc câu trả lời xuất sắc của SQL Kiwi, rõ ràng cả lý do tại sao điều này xảy ra và đây không phải là toàn bộ câu chuyện trong đó vẫn còn vô số thứ còn lại trên ngăn xếp không bao giờ có thể được xử lý.
Neo phát ra 1,2,3
cho khách hàng Nội dung ngăn xếp3,2,1
3 bật ra ngăn xếp, Nội dung ngăn xếp 2,1
LASJ trả về 1,2,4,5
, Nội dung ngăn xếp5,4,2,1,2,1
5 bật ra ngăn xếp, Nội dung ngăn xếp 4,2,1,2,1
LASJ trả về 1,2,3,4
Nội dung ngăn xếp4,3,2,1,5,4,2,1,2,1
4 popped off stack, Stack Nội dung 3,2,1,5,4,2,1,2,1
LASJ trả về 1,2,3,5
Nội dung ngăn xếp5,3,2,1,3,2,1,5,4,2,1,2,1
5 bật ra ngăn xếp, Nội dung ngăn xếp 3,2,1,3,2,1,5,4,2,1,2,1
LASJ trả về 1,2,3,4
Nội dung ngăn xếp
4,3,2,1,3,2,1,3,2,1,5,4,2,1,2,1
Nếu bạn thử và thay thế thành viên đệ quy bằng biểu thức tương đương logic (trong trường hợp không có trùng lặp / NULL)
select a
from (
select a
from cte
where a not in
(select a
from r)
) x
Điều này không được phép và gây ra lỗi "Tham chiếu đệ quy không được phép trong các truy vấn con." vì vậy có lẽ đó là một sự giám sát EXCEPT
thậm chí được cho phép trong trường hợp này.
Ngoài ra:
Microsoft hiện đã trả lời Kết nối phản hồi của tôi như dưới đây
Dự đoán của Jack là chính xác: đây có thể là một lỗi cú pháp; tài liệu tham khảo đệ quy nên thực sự không được phép trong EXCEPT
các mệnh đề. Chúng tôi dự định sẽ giải quyết lỗi này trong bản phát hành dịch vụ sắp tới. Trong khi đó, tôi sẽ đề nghị tránh các tài liệu tham khảo đệ quy trong EXCEPT
mệnh đề.
Để hạn chế đệ quy trên, EXCEPT
chúng tôi tuân theo tiêu chuẩn SQL ANSI, bao gồm hạn chế này kể từ khi đệ quy được đưa ra (năm 1999 tôi tin). Không có thỏa thuận rộng rãi về những gì ngữ nghĩa nên dành cho đệ quy EXCEPT
(còn gọi là "phủ định không phân loại") trong các ngôn ngữ khai báo như SQL. Ngoài ra, rất khó để thực hiện một cách hiệu quả ngữ nghĩa như vậy (đối với các cơ sở dữ liệu có kích thước hợp lý) trong một hệ thống RDBMS.
Và có vẻ như việc triển khai cuối cùng đã được thực hiện vào năm 2014 cho các cơ sở dữ liệu có mức độ tương thích từ 120 trở lên .
Tham chiếu đệ quy trong mệnh đề EXCEPT tạo ra lỗi tuân thủ tiêu chuẩn SQL ANSI.