我正在使用SQL Server 2008的XML解析功能来遍历XML文档并对每个元素执行INSERT。
但是,我的存储过程似乎是按照与文档中顺序不同的顺序将每个元素插入表中。
此外,我尝试的次数越多,INSERT顺序似乎会发生变化。
这是XML文档的示例-这里没什么花哨的事情。
<ts> <t id="36a3c8c1-b958-42f0-82d1-dfa6bf9b99a1" encryptedAccountId="fQ/XF8lpeR9wEDUV3yMzvQ==" uploaded="2012-04-03T15:49:19.9615097Z" visible="1"> <tv fieldId="301" officialValue="0, 0" friendlyValue="0, 0" /> <tv fieldId="302" officialValue="0, 1" friendlyValue="0, 1" /> <tv fieldId="303" officialValue="0, 2" friendlyValue="0, 2" /> <tv fieldId="304" officialValue="0, 3" friendlyValue="0, 3" /> <tv fieldId="305" officialValue="0, 4" friendlyValue="0, 4" /> <tv fieldId="306" officialValue="0, 5" friendlyValue="0, 5" /> </t> <t id="9d56d082-4b6a-4bdf-a7a2-f5c6af88344e" encryptedAccountId="fQ/XF8lpeR9wEDUV3yMzvQ==" uploaded="2012-04-03T15:49:19.9615097Z" visible="1"> <tv fieldId="301" officialValue="1, 0" friendlyValue="1, 0" /> <tv fieldId="302" officialValue="1, 1" friendlyValue="1, 1" /> <tv fieldId="303" officialValue="1, 2" friendlyValue="1, 2" /> <tv fieldId="304" officialValue="1, 3" friendlyValue="1, 3" /> <tv fieldId="305" officialValue="1, 4" friendlyValue="1, 4" /> <tv fieldId="306" officialValue="1, 5" friendlyValue="1, 5" /> </t> <t id="27db47a3-ad3f-4279-8f4f-0a8944ce32d4" encryptedAccountId="fQ/XF8lpeR9wEDUV3yMzvQ==" uploaded="2012-04-03T15:49:19.9615097Z" visible="1"> <tv fieldId="301" officialValue="2, 0" friendlyValue="2, 0" /> <tv fieldId="302" officialValue="2, 1" friendlyValue="2, 1" /> <tv fieldId="303" officialValue="2, 2" friendlyValue="2, 2" /> <tv fieldId="304" officialValue="2, 3" friendlyValue="2, 3" /> <tv fieldId="305" officialValue="2, 4" friendlyValue="2, 4" /> <tv fieldId="306" officialValue="2, 5" friendlyValue="2, 5" /> </t> <t id="867ea26b-0341-4d60-ac48-f305492a60f0" encryptedAccountId="fQ/XF8lpeR9wEDUV3yMzvQ==" uploaded="2012-04-03T15:49:19.9615097Z" visible="1"> <tv fieldId="301" officialValue="3, 0" friendlyValue="3, 0" /> <tv fieldId="302" officialValue="3, 1" friendlyValue="3, 1" /> <tv fieldId="303" officialValue="3, 2" friendlyValue="3, 2" /> <tv fieldId="304" officialValue="3, 3" friendlyValue="3, 3" /> <tv fieldId="305" officialValue="3, 4" friendlyValue="3, 4" /> <tv fieldId="306" officialValue="3, 5" friendlyValue="3, 5" /> </t> </ts>
存储过程发生了一些操作,但是我注释掉了其他部分,只剩下了先插入<t/>元素然后再<tv/>元素的SQL 。
<t/>
<tv/>
存储过程中的SQL如下。
(@xmlTransaction是NVARCHAR (MAX)包含上述XML的输入参数)
@xmlTransaction
NVARCHAR (MAX)
BEGIN SET NOCOUNT ON; DECLARE @encryptedAccountID AS VARCHAR(200) BEGIN TRANSACTION BEGIN TRY DECLARE @Handle AS INT DECLARE @TransactionCount AS INT EXEC sp_xml_preparedocument @Handle OUTPUT, @xmlTransaction /* encryptedAccountId is always the same for each @xmlTransaction param */ /* Just take the value from the first <t/> element */ SET @encryptedAccountID = (SELECT eID FROM OPENXML (@Handle, '/ts/t[1]', 2) WITH ( eID VARCHAR '@encryptedAccountId' )) /* Go through each <t/> element in the XML document and INSERT */ INSERT INTO [Transactions] ( [ID], [EncryptedAccountID] ) SELECT * FROM OPENXML (@Handle, '/ts/t', 2) WITH ( rID UNIQUEIDENTIFIER '@id', rEncryptedAccountID VARCHAR (200) '@encryptedAccountId' ) /* Loop through each TransactionValue in the XML document and INSERT */ INSERT INTO [TransactionValues] ( FieldID, TransactionID, OfficialValue, FriendlyValue ) SELECT * FROM OPENXML (@Handle, '/ts/t/tv', 2) WITH ( rFieldID INT '@fieldId', rTransactionID UNIQUEIDENTIFIER '../@id', rOfficialValue NVARCHAR (500) '@officialValue', rFriendlyValue NVARCHAR (500) '@friendlyValue' ) /* Dispose of the XML document */ EXEC sp_xml_removedocument @Handle COMMIT TRANSACTION END TRY BEGIN CATCH RETURN @@ERROR ROLLBACK TRANSACTION END CATCH END
应该相当简单。但是,如果我查询结果,它们的顺序与XML文档的顺序不同。<tv/>元素的第二个INSERT语句 确实 以正确的顺序将元素存储到第二个表中,但是 <t/>元素 没有 以正确的顺序存储在它们的表中。
谁能向我解释为什么 <t/>元素没有以与XML文档中出现的顺序相同的顺序插入表中?
如果我在SQL Server中使用本机XQuery支持而不是“旧式” OPENXML东西,那么看来<t>节点确实按照它们在XML文档中出现的顺序插入到了表中。
<t>
我使用了类似以下的代码:
INSERT INTO dbo.[Transactions]([ID], [EncryptedAccountID]) SELECT XT.value('@id', 'uniqueidentifier'), XT.value('@encryptedAccountId', 'varchar(200)') FROM @xmlTransaction.nodes('/ts/t') AS Nodes(XT)
<tv>子节点也可以这样做。
<tv>