1

SQLServer2008で少し異なるSELECTを実行しようとしています。XMLファイルをテーブルにインポートする必要がありますが、最初にいくつかのチェックを行う必要があります。

XMLで実行するときは、列とテーブルからのPKSELECTを使用して、XML行がテーブルにすでに存在するかどうかを確認する必要があります。存在する場合は、XMLから読み取った情報で行を更新する必要があります。存在しない場合は、テーブルに挿入するだけです。ViagemIDData

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ステートメントを使用することもできますが、すべての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 に答える