2017-05-19 23 views
0

當前我們導入一個表Import_File,其中有一個具有分隔值的選項列。 我們需要將這些分隔值加載到不同的表格中。將MSSQL批量字符串插入到XML中

目前,我們這樣做,在這往往是由於行數較慢一次一行能100K +

有沒有一種方法,以低於加快代碼?

Declare @InvId uniqueidentifier 
Declare @xml xml 
Declare CurrFeatureList Cursor For 
Select 
    import.InventoryId, 
    N'<root><r><![CDATA[' + replace(import.OPTIONS ,',',']]></r><r><![CDATA[') + ']]></r></root>' 
From    Import_File import with (nolock) 
Where 
    import.options IS NOT NULL 
    And ISNULL(import.IsFeatureProcessed,0) = 0 
    And LEN(ISNULL(import.OPTIONS,''))>10 
    And import.InventoryId Is Not Null 

OPEN CurrFeatureList 

FETCH NEXT FROM CurrFeatureList 
INTO @InvId, @xml 

Print 'Inventory Import #10000' 
Print GetDate() 
WHILE @@FETCH_STATUS = 0 
BEGIN 
    BEGIN TRY 

     Insert Into Import_File_Feature 
     (
      FeatureId, 
      InventoryId, 
      FeatureText, 
      FeatureGroup, 
      FeatureCategory, 
      FeatureIsAvailable, 
      FeatureIsStandard 
     ) 
     Select 
      NEWID(), 
      @InvId, 
      t.value('.','varchar(250)'), 
      '', 
      '', 
      1, 
      1 
     From @xml.nodes('//root/r') as a(t) 

     FETCH NEXT FROM CurrFeatureList 
     INTO @InvId, @xml 
    END TRY 
    BEGIN CATCH 
     Print 'Error ' 
     Print @InvId 
     Print ERROR_NUMBER() 
     Print ERROR_SEVERITY() 
     Print ERROR_STATE() 
     Print ERROR_PROCEDURE() 
     Print ERROR_LINE() 
     Print ERROR_MESSAGE() 

     FETCH NEXT FROM CurrFeatureList 
     INTO @InvId, @xml 
    END CATCH 
END 

Close CurrFeatureList 
Deallocate CurrFeatureList 
GO 
+1

似乎遊標可以替換爲'INSERT INTO SELECT' ... –

+1

同意@Rigerta。你沒有在光標中做任何需要光標的東西。 –

+0

是的,但我無法弄清楚如何在單個語句中執行select/join。理論上是的,這聽起來像是正確的方法,但我沒有玩過很多XML,所以不知道如何製作SQL。關於從哪裏開始的任何建議? – ullfindsmit

回答

2

我見過使用這種事情光標& try/catch塊的唯一原因是爲了識別和分析不良記錄,同時開發新的ETL過程。如果這不是你正在做的事情,那麼光標不是必需的,會減慢你的速度。

讓我們回顧一下你在做什麼:

  1. 你拉數據到光標(CurrFeatureList)和車削Import_File.Options到一個XML字段,以便以後可以使用XML節點的方法來「拆分「你的弦。
  2. 啓動光標
  3. 對於每個InventoryId,您是: a。將Import_File.Options分成多行 b。將InventoryId和關聯的行插入Import_File_Feature c。如果有錯誤,你打印出來並轉移到下一個記錄

你應該做

注意什麼使用XML節點我如何拆分此字符串:

DECLARE @x varchar(100) = 'abc,cde,fff'; 

SELECT item = xxx.value('(text())[1]', 'varchar(100)') 
FROM (VALUES (CAST(('<r>'+REPLACE(@x,',','</r><r>') +'</r>') AS xml))) x(xx) 
CROSS APPLY xx.nodes('r') xxx(xxx); 

結果

item 
----- 
abc 
cde 
fff 

OPTION 1

結合您的初始連接和隨後的XML/XML節點分路器邏輯到一個語句並執行插入:

WITH 
yourData AS 
(
    Select 
     import.InventoryId, 
     x = N'<r><![CDATA[' + replace(import.OPTIONS ,',',']]></r><r><![CDATA[') + ']]></r>' 
    From Import_File import with (nolock) 
    Where 
    import.options IS NOT NULL 
    And ISNULL(import.IsFeatureProcessed,0) = 0 
    And LEN(ISNULL(import.OPTIONS,''))>10 
    And import.InventoryId Is Not Null 
), 
split AS 
(
    SELECT InventoryId, item = i.value('.', 'varchar(8000)') 
    FROM yourData 
    CROSS APPLY x.nodes('r') s(i) 
) 
Insert Into Import_File_Feature 
(
    FeatureId, 
    InventoryId, 
    FeatureText, 
    FeatureGroup, 
    FeatureCategory, 
    FeatureIsAvailable, 
    FeatureIsStandard 
) 
Select 
    newid(), 
    import.InventoryId, 
    item, -- this is the split out item from import.Options 
    '', 
    '', 
    1, 
    1 
FROM split; 

OPTION 2

獲取的DelimitedSplit8K和使用副本它做你的分裂。

WITH split AS 
(
    Select 
     import.InventoryId, 
     import.OPTIONS 
    From Import_File import with (nolock) 
    CROSS APPLY dbo.DelimitedSplit8K(import.OPTIONS, ',') 
    Where 
    import.options IS NOT NULL 
    And ISNULL(import.IsFeatureProcessed,0) = 0 
    And LEN(ISNULL(import.OPTIONS,''))>10 
    And import.InventoryId Is Not Null 
) 
Insert Into Import_File_Feature 
(
    FeatureId, 
    InventoryId, 
    FeatureText, 
    FeatureGroup, 
    FeatureCategory, 
    FeatureIsAvailable, 
    FeatureIsStandard 
) 
Select 
    newid(), 
    import.InventoryId, 
    item, 
    '', 
    '', 
    1, 
    1 
FROM split 

需要注意的是,因爲我沒有任何表定義或樣本數據沒有辦法,我測試上面的代碼。

+1

爲了讓選項2工作,我必須做出兩點小小的改變。 1)我必須將import.OPTIONS轉換爲XML(目前它們是varchar)2)刪除導入。InventoryId並將其保存爲InventoryId。感謝您的幫助,這爲我節省了大量的處理時間並加快了速度。我不能100%確定的一種情況是,當varchar的xml字符(如&或< or >)處理異常時。有什麼建議麼? – ullfindsmit