Tôi có thể cho bạn một câu trả lời và một câu đoán:
Đầu tiên, tôi sử dụng một biến bảng đã khai báo để mô phỏng kịch bản của bạn:
DECLARE @tbl TABLE(s NVARCHAR(MAX));
INSERT INTO @tbl VALUES
(N'<root>
<SomeElement>This is first text of element1
<InnerElement>This is text of inner element1</InnerElement>
This is second text of element1
</SomeElement>
<SomeElement>This is first text of element2
<InnerElement>This is text of inner element2</InnerElement>
This is second text of element2
</SomeElement>
</root>')
,(N'<root>
<SomeElement>This is first text of elementA
<InnerElement>This is text of inner elementA</InnerElement>
This is second text of elementA
</SomeElement>
<SomeElement>This is first text of elementB
<InnerElement>This is text of inner elementB</InnerElement>
This is second text of elementB
</SomeElement>
</root>');
--Truy vấn này sẽ đọc XML bằng cách diễn ra từ một lựa chọn phụ . Bạn có thể sử dụng CTE
thay vào đó, nhưng đây chỉ nên là đường cú pháp ...
SELECT se.value(N'(.)[1]','nvarchar(max)') SomeElementsContent
,se.value(N'(InnerElement)[1]','nvarchar(max)') InnerElementsContent
,se.value(N'(./text())[1]','nvarchar(max)') ElementsFirstText
,se.value(N'(./text())[2]','nvarchar(max)') ElementsSecondText
FROM (SELECT CAST(s AS XML) FROM @tbl) AS tbl(TheXml)
CROSS APPLY TheXml.nodes(N'/root/SomeElement') AS A(se);
- Phần thứ hai sử dụng một bảng để viết bằng XML đã nhập và đọc từ đó:
DECLARE @tbl2 TABLE(x XML)
INSERT INTO @tbl2
SELECT CAST(s AS XML) FROM @tbl;
SELECT se.value(N'(.)[1]','nvarchar(max)') SomeElementsContent
,se.value(N'(InnerElement)[1]','nvarchar(max)') InnerElementsContent
,se.value(N'(./text())[1]','nvarchar(max)') ElementsFirstText
,se.value(N'(./text())[2]','nvarchar(max)') ElementsSecondText
FROM @tbl2 t2
CROSS APPLY t2.x.nodes(N'/root/SomeElement') AS A(se);
Tại sao lại là /text()
nhanh hơn không có /text()
?
Nếu bạn nhìn vào ví dụ của tôi, nội dung của một phần tử là mọi thứ từ thẻ mở đến thẻ đóng . text()
của một phần tử là văn bản nổi giữa các thẻ này. Bạn có thể thấy điều này trong kết quả của lựa chọn ở trên. text()
là một phần được lưu trữ riêng biệt trong cấu trúc cây thực sự (đọc phần tiếp theo). Để tìm nạp nó, là một hành động một bước . Nếu không, một cấu trúc phức tạp phải được phân tích để tìm mọi thứ giữa thẻ mở và thẻ đóng tương ứng của nó - ngay cả khi không có gì khác ngoài text()
.
Tại sao tôi nên lưu trữ XML ở kiểu thích hợp?
XML không chỉ là văn bản với một số ký tự phụ ngớ ngẩn! Nó là một tài liệu có cấu trúc phức tạp. XML không được lưu trữ dưới dạng văn bản bạn thấy . XML được lưu trữ trong cấu trúc cây. Bất cứ khi nào bạn truyền một chuỗi, đại diện cho một XML, thành một XML thực, công việc này rất tốn kém phải được thực hiện. Khi XML được trình bày cho bạn (hoặc bất kỳ đầu ra nào khác), chuỗi đại diện được (lại) xây dựng từ đầu.
Tại sao phương pháp truyền trước lại nhanh hơn
Đây là phỏng đoán ...
Trong ví dụ của tôi, cả hai cách tiếp cận đều khá bình đẳng và dẫn đến (gần như) cùng một kế hoạch thực thi.
SQL Server sẽ không hoạt động mọi thứ theo cách bạn có thể mong đợi. Đây không phải là một hệ thống thủ tục mà bạn nêu rõ làm điều này, hơn là làm điều này và sau đó làm điều này! . Bạn cho động cơ biết bạn muốn gì và động cơ quyết định cách thực hiện điều này tốt nhất. Và động cơ hoạt động khá tốt với điều này!
Trước khi bắt đầu thực thi, động cơ sẽ cố gắng ước tính chi phí của các phương pháp tiếp cận. CONVERT
(hoặc CAST
) là một hoạt động khá rẻ. Có thể là, engine quyết định làm việc với danh sách các cuộc gọi của bạn và thực hiện lặp đi lặp lại từng nhu cầu đơn lẻ, bởi vì nó cho rằng điều này rẻ hơn so với việc tạo ra một bảng dẫn xuất đắt tiền ...