如果在SELECT中从XML

时间:2013-03-20 19:24:48

标签: sql xml sql-server-2008

我试图在 SQL Server 2008 中做一些不同的SELECT。我需要将XML文件导入到表中,但首先我必须进行一些检查。

当我对XML执行SELECT时,我需要检查表中是否已存在XML行,并使用表中的ViagemIDData列作为PK。如果存在,我需要使用从XML读取的信息更新该行,如果没有,我只需要在表中插入。

XML行示例:

<viagem id="0000EPN" date="2013-01-01T00:00:00" type="EXTRA" 
        status="NORMAL" modalid="IPANEM" fleetid="B200" 
        departuretime="2013-04-01T00:00:00" arrivaltime="2013-01-01T00:20:00" 
        maxpasg="2000" locationid="XX" codredlinha="0007" />

代码:

SELECT @ViagemID = r.value('(@id)[1]', 'VARCHAR(30)'), @Data =   CAST(CONVERT(datetime,r.value('(@date)[1]', 'datetime')) as float),    
        @Extra = CASE (r.value('(@type)[1]', 'VARCHAR(15)')) WHEN 'EXTRA' THEN 1 ELSE 0 END, @FleetID = r.value('(@fleetid)[1]', 'VARCHAR(15)'),
        @Partida = r.value('(@departuretime)[1]', 'datetime'),  @Chegada = r.value('(@arrivaltime)[1]', 'datetime'), @Capacidade = r.value('(@maxpasg)[1]', 'int'),
        @LocationID = r.value('(@locationid)[1]', 'VARCHAR(10)'), @CodLinha = r.value('(@codredlinha)[1]', 'int')       

    IF EXISTS (SELECT * FROM dbo.ImportacaoXML WHERE ViagemID = @ViagemID AND Data = @Data)
    BEGIN
        UPDATE dbo.ImportacaoXML SET ViagemID = @ViagemID, Data = @Data, Extra = @Extra, FleetID = @FleetID, Partida = @Partida, 
            Chegada = @Chegada, Capacidade = @Capacidade, LocationID = @LocationID, CodLinha = @CodLinha
            WHERE ViagemID = @ViagemID AND Data = @Data
    END
    ELSE
    BEGIN
        INSERT INTO dbo.ImportacaoXML VALUES(@ViagemID, @Data, @Extra, @FleetID, @Partida, @Chegada, @Capacidade, @LocationID, @CodLinha)       
    END

FROM (SELECT CAST(x AS XML) FROM OPENROWSET (BULK '\\10.16.68.253\XXXXx\Xxxx.xml', SINGLE_BLOB) AS T(x)) AS T(x)    
CROSS APPLY x.nodes('/root/viagem') AS X(r);

但是我在上一行FROM行中遇到错误(AS附近的语法不正确)。

我可以在if语句中使用SELECT,但我需要读取所有XML,这将停止执行。之后,我需要添加更多的IF语句。

注1:我是SQL的新手,对不起,如果有任何废话。

注意2:我也关注性能,因为我不确定这段代码是否是最好的程序实践,而且我的表格会增长很多。

1 个答案:

答案 0 :(得分:1)

由于您使用的是SQL Server 2008,我可能会使用MERGE语句:

  • 将XML行解析为子查询中的列
  • MERGE使用以下规则进入目标表:
    • 如果目标表中不存在匹配项 - 则将新行插入目标
    • 当一行已经存在时 - 只需更新它

为此,我在这里使用这样的东西:

MERGE INTO dbo.ImportacaoXML AS Tgt    
USING (SELECT 
          ViagemID = r.value('(@id)[1]', 'VARCHAR(30)'), 
          Data = CAST(r.value('(@date)[1]', 'datetime') as float),    
          Extra = CASE r.value('(@type)[1]', 'VARCHAR(15)') WHEN 'EXTRA' THEN 1 ELSE 0 END, 
          FleetID = r.value('(@fleetid)[1]', 'VARCHAR(15)'),
          Partida = r.value('(@departuretime)[1]', 'datetime'),  
          Chegada = r.value('(@arrivaltime)[1]', 'datetime'), 
          Capacidade = r.value('(@maxpasg)[1]', 'int'),
          LocationID = r.value('(@locationid)[1]', 'VARCHAR(10)'), 
          CodLinha = r.value('(@codredlinha)[1]', 'int') 
        FROM 
           (SELECT CAST(x AS XML) FROM OPENROWSET (BULK 'D:\Temp\Test.xml', SINGLE_BLOB) AS T(X)) AS T(x)    
        CROSS APPLY 
            x.nodes('/root/viagem') AS X(r)) AS Source 
    ON Tgt.ViagemID = Source.ViagemID AND Tgt.Data = Source.Data

WHEN MATCHED THEN
     UPDATE 
        SET Tgt.ViagemID = Source.ViagemID, Tgt.Data = Source.Data, 
            Tgt.Extra = Source.Extra, Tgt.FleetID = Source.FleetID, 
            Tgt.Partida = Source.Partida, Tgt.Chegada = Source.Chegada, 
            Tgt.Capacidade = Source.Capacidade, Tgt.LocationID = Source.LocationID, 
            Tgt.CodLinha = Source.CodLinha

WHEN NOT MATCHED THEN     
    INSERT (ViagemID, Data, Extra, FleetID, Partida, Chegada, Capacidade, LocationID, CodLinha)
    VALUES (Source.ViagemID, Source.Data, Source.Extra, Source.FleetID, Source.Partida, Source.Chegada, Source.Capacidade, Source.LocationID, Source.CodLinha)
;