1

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

当我SELECT在 XML 上执行时,我需要检查 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 附近的语法不正确)。

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

注 1:我是 SQL 新手,如果有任何废话,我很抱歉。

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

4

1 回答 1

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)
;
于 2013-03-20T20:14:55.460 回答