2012-06-01 8 views
6

Tôi có một câu hỏi xảy ra khi tôi đang sử dụng mệnh đề WITH trong một tập lệnh của tôi. Câu hỏi là dễ dàng để chỉ ra tôi muốn sử dụng bí danh CTE nhiều lần thay vì chỉ trong truy vấn bên ngoài và có mấu chốt.T-SQL: sử dụng nhiều bí danh CTE - không chỉ trong truy vấn bên ngoài

Ví dụ:

-- Define the CTE expression 
WITH cte_test (domain1, domain2, [...]) 
AS 
-- CTE query 
(
    SELECT domain1, domain2, [...] 
    FROM table 
) 
-- Outer query 
SELECT * FROM cte_test 
-- Now I wanna use the CTE expression another time 
INSERT INTO sometable ([...]) SELECT [...] FROM cte_test 

Hàng cuối cùng sẽ dẫn đến các lỗi sau vì nó bên ngoài truy vấn bên ngoài:

Msg 208, Level 16, State 1, Line 12 tên đối tượng không hợp lệ 'cte_test'.

Có cách nào để sử dụng CTE nhiều lần không. làm cho nó liên tục? Giải pháp hiện tại của tôi là tạo một bảng tạm thời nơi tôi lưu trữ kết quả của CTE và sử dụng bảng tạm thời này cho bất kỳ câu lệnh nào khác.

-- CTE 
[...] 
-- Create a temp table after the CTE block 
DECLARE @tmp TABLE (domain1 DATATYPE, domain2 DATATYPE, [...]) 
INSERT INTO @tmp (domain1, domain2, [...]) SELECT domain1, domain2, [...] FROM cte_test 
-- Any further DML statements 
SELECT * FROM @tmp 
INSERT INTO sometable ([...]) SELECT [...] FROM @tmp 
[...] 

Thành thật mà nói, tôi không thích giải pháp này. Có ai khác có thực hành tốt nhất cho vấn đề này không?

Cảm ơn trước!

+0

Bạn có thể hoàn thành mục tiêu của mình bằng cách sử dụng câu lệnh 'MERGE', có lẽ với mệnh đề' OUTPUT', thay vì 'SELECT' làm người tiêu dùng CTE của bạn? – HABO

+0

Tại sao bạn muốn 'DELETE' từ một cte? – Johan

+1

@Johan: câu lệnh tiếp theo không phải là điểm, có thể là bất kỳ câu lệnh DML nào khác như 'INSERT' & c. – Neil

Trả lời

17

Một CommonTableExpression không lưu giữ dữ liệu theo bất kỳ cách nào. Về cơ bản, đó chỉ là cách tạo truy vấn phụ trước chính truy vấn chính.

Điều này làm cho nó giống với chế độ xem trực tuyến hơn so với truy vấn phụ bình thường. Bởi vì bạn có thể tham chiếu nó nhiều lần trong một truy vấn, thay vì phải nhập nó một lần nữa và một lần nữa.

Nhưng nó vẫn được coi là một chế độ xem, được mở rộng thành các truy vấn tham chiếu đến nó, như macro. Không có sự bền bỉ của dữ liệu nào cả.


này, không may cho bạn, có nghĩa là bạn phải thực hiện kiên trì chính mình.

  • Nếu bạn muốn logic của CTE được duy trì, bạn không muốn chế độ xem trực tuyến, bạn chỉ muốn xem.

  • Nếu bạn muốn thiết lập kết quả CTE được duy trì, bạn cần một loại bảng tạm thời của giải pháp, chẳng hạn như loại bạn không thích.

9

CTE chỉ nằm trong phạm vi cho câu lệnh SQL thuộc về. Nếu bạn cần sử dụng lại dữ liệu của nó trong một câu lệnh tiếp theo, bạn cần một bảng hoặc bảng biến tạm thời để lưu trữ dữ liệu. Trong ví dụ của bạn, trừ khi bạn đang thực hiện CTE đệ quy, tôi không thấy rằng CTE là cần thiết - bạn có thể lưu trữ nội dung của nó trực tiếp trong một biến bảng/bảng tạm thời và tái sử dụng nó nhiều như bạn muốn.

Cũng lưu ý rằng câu lệnh DELETE của bạn sẽ cố gắng xóa khỏi bảng bên dưới, không giống như nếu bạn đặt kết quả vào biến bảng/bảng tạm thời.