T-Sql XML节点基于节点名称条件

时间:2014-07-08 21:07:58

标签: sql-server xml tsql

我需要解析一些XML以插入表中,但我的中级节点名称可以是两个值<Image><Video>之一。插入后我有一个&#39;触发这样做,这是我的尝试,但它不起作用。感兴趣的领域是底部的CASE陈述。

USE [cims]
GO
/****** Object:  Trigger [dbo].[tr_XML_Insert]    Script Date: 07/08/2014 16:52:01 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER TRIGGER [dbo].[tr_XML_Insert]
ON [dbo].[ContainerXML]
AFTER INSERT
AS
BEGIN
    IF @@ROWCOUNT = 0
    RETURN
    SET NOCOUNT ON

    IF EXISTS(SELECT [XMLData] FROM INSERTED)
    BEGIN
        DECLARE @XML XML
        SELECT @XML = XMLData FROM [inserted]

        INSERT INTO [dbo].[ContainerImage]
        (
            CaptureDeviceCDIFID, CaptureDeviceName, Lat, Lon, DodAAC, OCR_Equipment, MOD_Equipment,
            TypeCode, SideImageComments, BackImageComments, SideImageCaptureDate, SideImage, 
            BackImageCaptureDate, BackImage, 
            RecordCreateDate
        )
        SELECT
            col.value('PCMU[1]/@cdifid[1]', 'NVARCHAR(15)'),
            col.value('PCMU[1]/@Name[1]', 'NVARCHAR(100)'),
            col.value('Location[1]/@lat[1]', '[DECIMAL](18,9)'),
            col.value('Location[1]/@lon[1]', '[DECIMAL](18,9)'),
            col.value('Location[1]/@DoDAAC[1]', 'NVARCHAR(10)'),
            REPLACE(col.value('BIC[1]/@ISOCode[1]', 'NVARCHAR(12)'), ' ', ''),
            REPLACE(col.value('BIC[1]/@ISOCode[1]', 'NVARCHAR(12)'), ' ', ''),
            col.value('BIC[1]/@TypeCode[1]', 'NVARCHAR(10)'),
            col.value('BIC[1]/@UserText1[1]', 'NVARCHAR(255)'),
            col.value('BIC[1]/@UserText2[1]', 'NVARCHAR(255)'),
            CASE xmldata.col.value('local-name(/*[1])','varchar(20)')
                WHEN 'Image' THEN col.value('Image[1]/@imagetime[1]', 'DATETIME')
                WHEN 'Video' THEN col.value('Video[1]/@time[1]', 'DATETIME')
            END,
            CASE xmldata.col.value('local-name(/*[1])','varchar(20)')
                WHEN 'Image' THEN col.value('Image[1]/@imageData[1]', 'VARBINARY(MAX)')
                WHEN 'Video' THEN col.value('Video[1]/@videoData[1]', 'VARBINARY(MAX)')
            END,
            CASE xmldata.col.value('local-name(/*[1])','varchar(20)')
                WHEN 'Image' THEN col.value('Image[2]/@imagetime[1]', 'DATETIME')
                WHEN 'Video' THEN col.value('Video[2]/@time[1]', 'DATETIME')
            END,
            CASE xmldata.col.value('local-name(/*[1])','varchar(20)')
                WHEN 'Image' THEN col.value('Image[2]/@imageData[1]', 'VARBINARY(MAX)')
                WHEN 'Video' THEN col.value('Video[2]/@videoData[1]', 'VARBINARY(MAX)')
            END,
            GETDATE()
            FROM @XML.nodes('//Containers/Container') as xmldata(col)                   
    END
END

以下是XML文件的2种格式 - 我可以很容易地做其中一种,我正在寻找一种在同一代码中完成它的方法。我本质上想要XML中的所有内容,我只是不知道怎么说&#34;如果节点名称==图像,请获取这些字段,否则如果节点名称==视频,则获取这些字段

<Containers>
    <Container>
        <PCMU  cdifid="81.135.189.71" Name="Test PCMU1" />
        <Location  lat="38.35688" lon="-77.45752" 
                DoDAAC="TODO??" />
        <BIC    time="2014-06-20T15:11:07"
            idStatus="OK"
            ISOCode="(null)"
            TypeCode="0x0"
            UserText1="??"
            UserText2="??" />
        <Video  view="Container Side" 
            time="2014-06-20T15:11:07" 
            videoData="big chunk of base64 data"/>
        <Video  view="Container Rear" 
            time="2014-06-20T15:11:07" 
            videoData="big chunk of base64 data" />
    </Container>
</Containers>


<Containers>
    <Container>
        <PCMU  cdifid="81.135.189.71" Name="Test PCMU1" />
        <Location  lat="38.35688" lon="-77.45752" 
                DoDAAC="TODO??" />
        <BIC    time="2014-06-20T15:11:07"
            idStatus="OK"
            ISOCode="(null)"
            TypeCode="0x0"
            UserText1="??"
            UserText2="??" />
        <Image  view="Container Side" 
            imageTime="2014-06-20T15:11:07" 
            imageData="big chunk of base64 data"/>
        <Image  view="Container Rear" 
            imageTime="2014-06-20T15:11:07" 
            imageData="big chunk of base64 data" />
    </Container>
</Containers>

1 个答案:

答案 0 :(得分:1)

您需要使用insert表,因为您可以一次插入多行,并且可以重写case语句以在一个value子句中使用两个xPath表达式。

CREATE TRIGGER [dbo].[tr_XML_Insert]
ON [dbo].[ContainerXML]
AFTER INSERT
AS
BEGIN
  INSERT INTO [dbo].[ContainerImage]
  (
      CaptureDeviceCDIFID, CaptureDeviceName, Lat, Lon, DodAAC, OCR_Equipment, MOD_Equipment,
      TypeCode, SideImageComments, BackImageComments, SideImageCaptureDate, SideImage, 
      BackImageCaptureDate, BackImage, 
      RecordCreateDate
  )
  SELECT
      col.value('(PCMU/@cdifid)[1]', 'NVARCHAR(15)'),
      col.value('(PCMU/@Name)[1]', 'NVARCHAR(100)'),
      col.value('(Location/@lat)[1]', '[DECIMAL](18,9)'),
      col.value('(Location/@lon)[1]', '[DECIMAL](18,9)'),
      col.value('(Location/@DoDAAC)[1]', 'NVARCHAR(10)'),
      REPLACE(col.value('(BIC/@ISOCode)[1]', 'NVARCHAR(12)'), ' ', ''),
      REPLACE(col.value('(BIC/@ISOCode)[1]', 'NVARCHAR(12)'), ' ', ''),
      col.value('(BIC/@TypeCode)[1]', 'NVARCHAR(10)'),
      col.value('(BIC/@UserText1)[1]', 'NVARCHAR(255)'),
      col.value('(BIC/@UserText2)[1]', 'NVARCHAR(255)'),
      xmldata.col.value('(Image/@imageTime, Video/@time)[1]','DATETIME'),
      xmldata.col.value('(Image/@imageData, Video/@videoData)[1]','VARBINARY(MAX)'),
      xmldata.col.value('(Image/@imageTime, Video/@time)[2]','DATETIME'),
      xmldata.col.value('(Image/@imageData, Video/@videoData)[2]','VARBINARY(MAX)'),
      GETDATE()
      FROM inserted AS I
        CROSS APPLY I.XMLData.nodes('/Containers/Container') as xmldata(col)                   
END