如何在SQL Server 2005中对复杂XML使用openXML()

时间:2012-04-17 12:44:29

标签: sql-server-2005 openxml

我有以下复杂的XML

<Collection>
 <VOUCHER>
      <DATE TYPE="Date">20110401</DATE>
      <NARRATION TYPE="String">MUNNA CONVENT ROAD</NARRATION>
      <VOUCHERTYPENAME>RETAIL</VOUCHERTYPENAME>
      <VOUCHERNUMBER>R-2-I2-9-6-27751</VOUCHERNUMBER>
      <ALLLEDGERENTRIES.LIST>            
           <LEDGERNAME>U.S.T. CANTEEN</LEDGERNAME>
           <AMOUNT>-2678.9985</AMOUNT>
      </ALLLEDGERENTRIES.LIST>
      <ALLLEDGERENTRIES.LIST>            
           <LEDGERNAME>U.S.T. CANTEEN</LEDGERNAME>
           <AMOUNT>-2678.9985</AMOUNT>
      </ALLLEDGERENTRIES.LIST>
 </VOUCHER>
 <VOUCHER>
      <DATE TYPE="Date">20110401</DATE>
      <NARRATION TYPE="String">MUNNA CONVENT ROAD</NARRATION>
      <VOUCHERTYPENAME>RETAIL</VOUCHERTYPENAME>
      <VOUCHERNUMBER>R-2-I2-9-6-27751</VOUCHERNUMBER>
      <ALLLEDGERENTRIES.LIST>            
           <LEDGERNAME>U.S.T. CANTEEN</LEDGERNAME>
           <AMOUNT>-2678.9985</AMOUNT>
      </ALLLEDGERENTRIES.LIST>
      <ALLLEDGERENTRIES.LIST>            
           <LEDGERNAME>U.S.T. CANTEEN</LEDGERNAME>
           <AMOUNT>-2678.9985</AMOUNT>
      </ALLLEDGERENTRIES.LIST>
 </VOUCHER>
</Collection>

我将凭证详细信息保存在1个表中,ALLLEDGERENTRIES.LIST详细信息保存在另一个表中。

两个表都与VoucherID有关系。对于特定的VoucherID,应存储相关的x3值。在我的存储过程中,我正在使用openxml()

我的SP:

INSERT INTO SalesVoucher(AbsID,VoucherNumber,VoucherTypeName,Narration,VoucherDate)
    SELECT @AID,VOUCHERNUMBER,VOUCHERTYPENAME,NARRATION,CAST(DATE AS DATETIME)
        FROM OPENXML(@XMLHandle,'ENVELOPE/BODY/DATA/COLLECTION/VOUCHER',3) 
        WITH (    
            VOUCHERNUMBER nVarchar(200),VOUCHERTYPENAME varchar(100),NARRATION varchar(500),DATE DATETIME
            )
    SELECT @VID=@@IDENTITY

INSERT INTO SalesLedger(VoucherID,LedgerName,Amount)
    SELECT @VID,LEDGERNAME,AMOUNT
        FROM OPENXML(@XMLHandle,'ENVELOPE/BODY/DATA/COLLECTION/VOUCHER/ALLLEDGERENTRIES.LIST',3)
        WITH(
            LEDGERNAME varchar(200),AMOUNT decimal(18,0)
            )

所有值都存储在DB中,但VoucherID表中的SalesLedger列对于所有行都是相同的(它不应该......),因为我使用了@@IDENTITY它返回了最后一个标识只有价值。

请有人帮助我如何在voucherID表中使用SalesLedger在sql中存储相关的openxml() ...

1 个答案:

答案 0 :(得分:0)

我可能会使用SQL Server的本机XQuery功能来执行此操作。首先,抓住SalesVoucher表所需的项目并插入它们。

当您来插入详细信息时,您的“父”信息已存储在SalesVoucher表中 - 因此请从那里获取必要的信息。

您的代码将是这样的(假设您的XML数据位于@input类型为XML的SQL变量中:

-- Insert the "parent" info into SalesVoucher
INSERT INTO dbo.SalesVoucher(VoucherNumber, VoucherTypeName, Narration, VoucherDate)
    SELECT
        v.value('(VOUCHERNUMBER)[1]', 'NVARCHAR(200)'),
        v.value('(VOUCHERTYPENAME)[1]', 'VARCHAR(100)'),
        v.value('(NARRATION)[1]', 'VARCHAR(500)'),
        v.value('(DATE)[1]', 'DATETIME')
    FROM 
        @input.nodes('/Collection/VOUCHER') AS Coll(V)

这会在SalesVoucher表格中插入基本信息。

如果要解析详细信息,则需要将引用返回到父级的VoucherNumber - 使用该信息,您可以从AbsID检索SalesVoucher并插入适当的值SalesLedger

INSERT INTO @SalesLedger (VoucherID, LedgerName, Amount)
   SELECT
       sv.AbsID,
       AL.LS.value('(LEDGERNAME)[1]', 'VARCHAR(200)'),
       AL.LS.value('(AMOUNT)[1]', 'DECIMAL(18,4)')
   FROM 
       @input.nodes('/Collection/VOUCHER') AS Coll(V)
   INNER JOIN
       dbo.SalesVoucher sv 
           ON sv.VoucherNumber = v.value('(VOUCHERNUMBER)[1]', 'NVARCHAR(200)')
   CROSS APPLY
       Coll.V.nodes('.//ALLLEDGERENTRIES.LIST') AS AL(LS)

CROSS APPLY获取该特定节点的详细信息,从而将详细信息“连接”到上述XML中VoucherNumber的“父”信息。

与PS一样:DECIMAL(18,0)的数据类型适用于-2678.9985等值。 DECIMAL(18,0)最多会存储18位数,但小数点后 0 - 因此该值将存储为-2679。我已将其更改为更有用的数据类型DECIMAL(18,4) - 最多18位,其中4位小数点后。