-
Queries that use parent axis generate extra query plan steps so use multiple CROSS APPLY steps to get nodes at multiple nesting levels rather than using the parent axis.
- Bad
select o.value(‘../@id’, ‘int’) as CustID, o.value(‘@id’, ‘int’) as OrdID from T cross apply x.nodes(‘/doc/customer/orders’) as N(o) - Good
select c.value(‘@id’, ‘int’) as CustID, o.value(‘@id’, ‘int’) as OrdID from T cross apply x.nodes(‘/doc/customer’) as N1(c) cross apply c.nodes(‘orders’) as N2(o)
- Bad
-
Move ordinals to the end of path expressions
- Bad
/book[1]/@isbn
- Good
(/book/@isbn)[1]
- Bad
-
Avoid predicates in the middle of path expressions
- Bad
book[@ISBN = “1-8610-0157-6”]/author[first-name = “Davis”]
- Good
/book[@ISBN = “1-8610-0157-6”] "n" /book/author[first-name = “Davis”]
- Bad
-
Use context item in predicate to lengthen path in exist()
- Bad
SELECT * FROM docs WHERE 1 = xCol.exist(‘/book/subject[text() = “security”]’)
- Good
SELECT * FROM docs WHERE 1 = xCol.exist(‘/book/subject/text()[. = “security”]’)
- Bad
-
Casting from XML to SQL
- Bad
CAST( CAST(xmldoc.query(‘/a/b/text()’) as nvarchar(500)) as int)
- Good
xmldoc.value(‘(/a/b/text())[1]’, ‘int’)
- Bad
node.query(‘.’).value(‘@attr’, ‘nvarchar(50)’)
- Good
node.value(‘@attr’, ‘nvarchar(50)’)
- Bad
-
Use temp table (insert into #temp select … from nodes()) or Table-valued parameter instead of XML
-
Specify a single root node in query as the optimizer assumes that XML can be a fragment.