> I have an xml document stored in a table column that has inaccurate
> times in the date fields
>
> I 'd like to update all LineStartTime and LineEndTime values in the
> document by 15 seconds so, for instance, 2012-02-01T00:07:00 becomes
> 2012-02-01T00:07:15 (long story as to why it needs to be this way; it's
> out of my hands).. There can be 1 to many transactions and each
> transaction can have 1 or more line entries.
>
> I have tried OPENXML, modify method, etc and I can't get it right. I am
> at my wits end. Any help is appreciated. Thanks in advance!!
I first tried .modify, but the first roadblock is that there are no
datetime operations in XQuery in SQL Server. I decided to cheat with
concat, assuming that the seconds are always 00. After some battling,
I consulted my MVP mates, and I leart that replace value of only handles
singleton values. You could write a loop where you use sqlvariable, but
I could not get that to work.
I gave up XQuery, and instead wrote the boring solution: extract to a
table, and then write back with FOR XML. If you have many rows in the table,
you will to take a cursor.
DECLARE @t TABLE (SaleID int NOT NULL,
SaleDateTime datetime2(0) NOT NULL,
Line int NOT NULL,
LineStartTime datetime2(0) NOT NULL,
LineEndTime datetime2(0) NOT NULL,
Amount decimal(10, 2) NOT NULL,
PRIMARY KEY (SaleID, Line))
INSERT @t (SaleID, SaleDateTime, Line, LineStartTime, LineEndTime, Amount)
SELECT T.c.value('(SaleID/text())[1]', 'int'),
S.c.value('(SaleDateTime/text())[1]', 'datetime2(0)'),
L.c.value('(Line/text())[1]', 'int'),
L.c.value('(LineStartTime/text())[1]', 'datetime2(0)'),
L.c.value('(LineEndTime/text())[1]', 'datetime2(0)'),
L.c.value('(Amount/text())[1]', 'decimal(10,2)')
FROM XMLTable
CROSS APPLY doc.nodes('/Root/Transaction') AS T(c)
CROSS APPLY T.c.nodes('Sale') AS S(c)
CROSS APPLY S.c.nodes('LineItem') AS L(c)
UPDATE @t
SET LineStartTime = dateadd(second, 15, LineStartTime),
LineEndTime = dateadd(second, 15, LineEndTime)
UPDATE XMLTable
SET doc = (
SELECT s.SaleID AS [SaleID],
s.SaleDateTime AS [Sale/SaleDateTime],
(SELECT t.Line,
t.LineStartTime,
t.LineEndTime,
t.Amount
FROM @t t
WHERE s.SaleID = t.SaleID
FOR XML PATH('LineItem'), TYPE) AS [Sale]
FROM (SELECT DISTINCT SaleID, SaleDateTime FROM @t) AS s
FOR XML PATH('Transaction'), ROOT('Root')
)
SELECT * FROM XMLTable
go
DROP TABLE XMLTable
--
Erland Sommarskog, SQL Server MVP,
esq...@sommarskog.se
Links for SQL Server Books Online:
SQL 2008:
http://msdn.microsoft.com/en-us/sqlserver/cc514207.aspx
SQL 2005:
http://msdn.microsoft.com/en-us/sqlserver/bb895970.aspx