I'm using the modify()
and query()
methods to interact with XML data.
Here is an example of how I'm using modify()
:
DECLARE @i int = 1
DECLARE @x xml = N'<?xml version="1.0" encoding="utf-16"?><Table></Table>'
SET @x.modify('insert <Row><Column>{sql:variable("@i")}</Column></Row> as last into (//Table)[1]');
SELECT @x
Here is an example of how I'm using query()
:
DECLARE @i int = 2
DECLARE @x xml = N'<?xml version="1.0" encoding="utf-16"?>
<Table>
<Row>
<Column>1</Column>
</Row>
<Row>
<Column>2</Column>
</Row>
<Row>
<Column>3</Column>
</Row>
<Row>
<Column>4</Column>
</Row>
</Table>'
DECLARE @xt xml
SET @xt = @x.query('//Table/Row[{sql:variable("@i")}]')
SELECT @xt
I thought curly brackets were required when used in an XQuery, as described at SQLServerCentral here.
However, the curly brackets in the query()
method are causing a syntax error that is only resolved by removing them. Alternatively, the curly brackets are just fine when used with modify()
.
So, could someone clarify the purpose of the curly brackets when used with the sql:variable()
function in an XQuery and when they are required?
sql:variable()
is a function expression, which means it can only be used in positions where expressions are expected. {}
denotes XML construction, this can only be used in places where XML construction is expected.
In the case of .modify
, the syntax insert SomeNewXml as last into /SomeNode
expects constructed XML in the place of SomeNewXml
. In your case, you have used:
<Row><Column>{sql:variable("@i")}</Column></Row>
You cannot remove the braces here because otherwise it would try to interpret sql:variable("@i")
as raw XML text. The {}
escapes it so you can use a dynamic expression to construct the XML.
In the .query
case, you are using it as a predicate filter. If the value is statically known as an xs:integer
(which it is here), then it's interpreted as a position predicate.
Predicate values can only be
xs:integer
,xs:Boolean
, ornode*
So using braces makes no sense:
//Table/Row[{sql:variable("@i")}]
now it thinks you are trying to pass constructed XML instead of an xs:integer
, which is unexpected.
Note that none of this is specific to sql:variable
, it applies any time you use an XQuery expression in such positions.