2013-03-20 3 views
1

Я пытаюсь сделать немного другое SELECT в SQL Server 2008. Мне нужно импортировать XML-файл в таблицу, но сначала я должен выполнить некоторую проверку.IF Внутри SELECT From XML

Когда я делаю SELECT по XML, мне нужно проверить, существует ли строка XML в таблице, используя столбцы и Data из таблицы как ПК. Если существует, мне нужно обновить строку с информацией, прочитанной из 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, но мне нужно прочитать весь XML, это остановит выполнение. Впоследствии мне нужно будет добавить несколько инструкций IFs.

Примечание 1: Я новичок в SQL, извините, если о какой-либо дерьме.

Примечание 2: Меня тоже беспокоит производительность, потому что я не уверен, является ли этот код лучшей практикой программы, а мой стол будет расти.

+0

Это SQL как вывешено не действует - это даже не пройти проверку синтаксиса ... первый выключен: не так ** объявить ** все эти переменные SQL? Также: не следует ли 'SELECT' и' FROM .... 'быть вместе - перед целым' IF EXIST (...) 'block ?? –

+0

Я просто удалил объявление переменных. И часть XML работает. Если я использую IF EXIST после предложения FROM, он получает последнюю строку XML. – Juliano

+0

Это действительно не совсем понятно, что вы пытаетесь сделать - также: можете ли вы предоставить образец XML и объяснить **, что ** вы хотите извлечь из этого XML в ваши таблицы SQL Server? –

ответ

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) 
; 
+0

Это работает. Но могу ли я использовать, например, еще один вариант внутри «Согласованного» предложения? Потому что мне нужно сделать еще одну проверку, если она соответствует, а другая - для «Не согласована». Я ищу в Google, но я хочу спросить здесь тоже. – Juliano

+0

@Juliano: no - внутри 'WHEN MATCHED' вы можете ** только ** иметь инструкцию' UPDATE' или 'INSERT' (или' DELETE') - ничего больше. [Подробнее о заявлении 'MERGE' здесь] (https: //www.simple-talk.com/sql/learn-sql-server/the-merge-statement-in-sql-server-2008 /) - вы * можете * добавить второе предложение WHEN MATCHED, которое имеет дополнительное условие - см. статью I связанный с подробностями –

Смежные вопросы