CTE chạy bao nhiêu lần


8

Nếu tôi có một cte như mã dưới đây. Bao nhiêu lần cái bàn Mọi người được truy vấn? Tôi có ấn tượng rằng nó chỉ được gọi 1 lần và được lưu trong bộ nhớ nhưng một số truy vấn của tôi mà tôi đang chạy dường như chạy lâu hơn nhiều so với mức cần thiết. Điều đó khiến tôi tin rằng nó có thể đánh vào Bảng người 3 lần.

with ctegeneric as (select person from people where person = 'dumb')
Select * from ctegeneric 
UNION ALL
Select * from ctegeneric 
UNION ALL
Select * from ctegeneric 

Câu trả lời:


7

Đặt cú pháp sang một bên là không chính xác (trước khi chỉnh sửa).

KHÔNG nó không được đưa vào bộ nhớ.

Một ví dụ thích hợp là tham gia. Nó sẽ nhận được cuộc gọi nhiều lần trong một vòng lặp tham gia. Trên một CTE đắt tiền được gọi nhiều lần, sau đó cụ thể hóa thành #temp là cách để đi.


Cảm ơn bạn đã không bị bắt về ví dụ chung được viết nhanh chóng của tôi. Đó chính xác là câu trả lời đi kèm với câu hỏi. Cám ơn rất nhiều vì cái đó.
scripter78

4

Trong SQL, CTE chỉ có thể được sử dụng / được tham chiếu trong câu lệnh (một), trong đó nó được định nghĩa. Và chúng ta biết nơi các câu lệnh kết thúc bằng cách sử dụng các dấu kết thúc câu lệnh ( ;).

SQL Server đang tha thứ và cho phép các nhà phát triển không đặt các thiết bị đầu cuối này (trừ trường hợp đặc biệt có khiếu nại) nhưng thực sự tốt (và Microsoft khuyến nghị) nên sử dụng chúng sau mỗi câu lệnh. Nếu bạn đã đặt chúng, rõ ràng mã của bạn sẽ phân tích thành 3 câu lệnh:

--- 1st statement starts ---
with ctegeneric as (select person from people where person = 'dumb') 
Select * from ctegeneric ;    -- and ends here

--- 2nd statement starts ---
Select * from ctegeneric ;    -- and ends here

--- 3rd statement starts ---
Select * from ctegeneric ;    -- and ends here

Vì vậy, báo cáo thứ hai và thứ ba của bạn hoàn toàn không hoạt động và sẽ trả về lỗi:

INVALID OBJECT NAME: ctegeneric

Ngay khi tuyên bố nơi CTE được thực hiện kết thúc, bạn sẽ mất khả năng tham chiếu lại.

Nó giống như (đây cũng không phải là cú pháp hợp lệ, chỉ là một cách khác để suy nghĩ về CTE):

WITH ctegeneric AS (SELECT person 
                    FROM people 
                    WHERE person = 'dumb')

BEGIN
Select * from ctegeneric ;
END

Tuy nhiên, bạn có thể chạy ba lựa chọn với một UNION/UNION ALL:

WITH ctegeneric AS (SELECT person 
                    FROM people 
                    WHERE person = 'dumb')   
Select * from ctegeneric
UNION
Select * from ctegeneric
UNION
Select * from ctegeneric ;

Có, tôi đã nhanh chóng viết truy vấn chỉ như một ví dụ chung chung, tôi đã cập nhật nó với các hiệp hội để làm rõ ví dụ. Bây giờ với tất cả 3 lựa chọn, bảng People bên trong CTE có được gọi 1 lần hay 3 lần không?
scripter78

Tôi không tin rằng nó được lưu trữ như kết quả của bảng tạm thời hoặc biến của bảng. Nó được gọi mỗi khi bạn sử dụng nó trong một truy vấn. Ngoài ra, cảm ơn bạn đã chỉnh sửa câu hỏi ban đầu của bạn. Xin hãy hiểu rằng tôi đã chú ý đến nó bởi vì những người khác sẽ xem xét câu hỏi này trong tương lai và có thể gặp phải vấn đề này.
MguerraTorres

4

Trình tối ưu hóa lấy SQL đã gửi và chuyển nó thành một tập hợp các hành động được gọi là kế hoạch truy vấn. Khi thực hiện điều này, có thể tự do sắp xếp các hành động đó theo bất kỳ chuỗi nào tương đương logic với SQL. Điều này có thể dẫn đến một đối tượng được đề cập trong SQL được truy cập một lần, nhiều lần hoặc hoàn toàn không. Điều này áp dụng cho các đối tượng trong CTE.

Vì vậy, mặc dù người ta thường quan sát thấy rằng các đối tượng được đề cập trong CTE chỉ được truy cập một lần khi không có gì đảm bảo rằng điều này sẽ xảy ra.

Giống như bất kỳ câu lệnh SQL nào khác, dữ liệu được xử lý thông qua phần CTE chỉ nằm trong phạm vi cho thời lượng của câu lệnh đó. Nếu cùng một dữ liệu được tham chiếu trong một tuyên bố tiếp theo, nó sẽ được truy cập lại.


3

Mã đó sẽ không thực sự hoạt động. (op kịch bản cập nhật sau khi câu trả lời này được đăng)

CTE là các truy vấn con hiệu quả (hỗ trợ đệ quy). Chúng chỉ có thể được tham chiếu trong phạm vi của lệnh cụ thể đó. Do đó, câu lệnh select * đầu tiên của bạn sẽ hoạt động, hai câu lệnh tiếp theo sẽ báo lỗi không thể tìm thấy CTE. Để những thứ đó hoạt động, bạn sẽ cần tạo một CTE khác cho mỗi cái để tham khảo. Và trong tình huống đó, bạn sẽ nhấn vào bảng mọi người 3 lần, một lần cho mỗi truy vấn.

Để cải thiện điều này, bạn có thể đặt kết quả của mình vào bảng tạm thời hoặc biến bảng và sau đó chỉ cần truy vấn đó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.