Reputation: 587
I want to update an node of an xml document in an sql server XML column with a value from a normal NVARCHAR column. When I use the value directly I can just use "sql:column("SAPersoon.ACHTERNAAM")". But what if I want to apply a function first like trim? Or as in the example below a substring. For now I'm using a cross apply.
Can this be done in a better way without requiring a cross apply? Is there a way to feed the result of the sql function directly to the XML modify? I cannot find syntax for this.
UPDATE [vault].[Objects] SET
[Content].modify('replace value of (/Object/Achternaam/text())[1] with (sql:column("x.waarde"))')
FROM [vault].[Objects]
INNER JOIN SAPersoon ON Objects.Id = SAPersoon.Id
CROSS APPLY (VALUES(SUBSTRING(SAPersoon.ACHTERNAAM, 1, 1))) x(waarde)
WHERE [Objects].[Content].exist('/Object/Achternaam') = 1
AND [Objects].[Content].value('(/Object/Achternaam/text())[1]', 'nvarchar(255)') <> x.waarde
Edit:
Yithzak's answer is already usefull to me as I selected substring function because I thought the equivalent XQuery function was not supported in SQL. My mistake. So I need to supplement with a extra criteria :). Is the cross apply be avoided in the case of a random sql user defined function.
Upvotes: 0
Views: 705
Reputation: 22187
The with (...)
clause holds an expression that belongs to the XML/XQuery context. It accepts any legit XQuery function calls. So there is no need to use CROSS APPLY for your particular case.
Please check the following conceptual example.
SQL
-- DDL and sample data population, start
DECLARE @tbl TABLE (ID INT IDENTITY PRIMARY KEY, city VARCHAR(30), xmldata XML);
INSERT INTO @tbl (city, xmldata) VALUES
('Miami', N'<root>
<city>Hollywood</city>
</root>');
-- DDL and sample data population, end
-- before
SELECT * FROM @tbl;
UPDATE @tbl
SET xmldata.modify('replace value of (/root/city/text())[1]
with (fn:substring(sql:column("@tbl.city"),1,3))');
-- after
SELECT * FROM @tbl;
Output
<root>
<city>Mia</city>
</root>
Edit
Unfortunately, MS SQL Server's XQuery doesn't support UDFs written in XQuery. So if you need to apply any T-SQL udf you would need use CROSS/OUTER APPLY
.
Upvotes: 2