从XML插入/更新数据库的存储过程

时间:2014-05-27 21:02:33

标签: sql-server xml stored-procedures sql-server-2012 database-cursor

我在SQL Server 2012中有一个存储过程,它从XML文件中获取数据并将其插入/更新到数据库表中。

存储过程:

ALTER PROCEDURE [dbo].[ProcItem]
   (@cItemID nvarchar(50) = NULL,
    @XMLdata XML)
AS
BEGIN
DECLARE
    item_cursor cursor for 
    SELECT TempTable.i.value('ItemID[1]','nvarchar(50)')
    FROM @XMLdata.nodes('/Garage/WareHouse/ItemGroup/Item')AS TempTable(i)
open item_cursor;
fetch next from item_cursor into @cItemID
while @@FETCH_STATUS=0
BEGIN
IF EXISTS (SELECT ItemID FROM WareHouse WHERE ItemID = @cItemID)
    BEGIN
    UPDATE WareHouse
    SET 
    ItemGroupID = TempTable.a.value('ItemGroupID[1]','nvarchar(50)'),
    Color = TempTable.a.value('Color[1]','nvarchar(50)'),
    Location = TempTable.a.value('Location[1]','nvarchar(50)'),
    Price = TempTable.a.value('Price[1]','nvarchar(50)'),
    Manufacture = TempTable.a.value('Manufacture[1]','nvarchar(100)'),
    Supplier = TempTable.a.value('Supplier[1]','nvarchar(100)'),
    SerialNumber = TempTable.a.value('SerialNumber[1]','nvarchar(100)')
    FROM
    @XMLdata.nodes('/Garage/WareHouse/ItemGroup/Item')AS TempTable(a)
    WHERE  ItemID = TempTable.a.value('ItemID[1]','nvarchar(100)')
    END

ELSE 
    BEGIN
    INSERT INTO WareHouse (ItemID, ItemGoupID, Color, Location, Price, Manufacture, Supplier, SerialNumber)

    SELECT
    ItemID = TempTable.b.value('ItemID[1]','nvarchar(50)'),
    ItemGroupID = TempTable.b.value('ItemGroupID[1]','nvarchar(50)'),
    Color = TempTable.b.value('Color[1]','nvarchar(50)'),
    Location = TempTable.b.value('Location[1]','nvarchar(50)'),
    Price = TempTable.b.value('Price[1]','nvarchar(50)'),
    Manufacture = TempTable.b.value('Manufacture[1]','nvarchar(100)'),
    Supplier = TempTable.b.value('Supplier[1]','nvarchar(100)'),
    SerialNumber = TempTable.b.value('SerialNumber[1]','nvarchar(100)')
    FROM
    @XMLdata.nodes('/Garage/WareHouse/ItemGroup/Item')AS TempTable(b)
    END
fetch next from item_cursor into @cItemID
END
close item_cursor
deallocate item_cursor
END

我的XML文件:

<?xml version="1.0" encoding="UTF-8"?>
<Garage>
<WareHouse>
<WareHouseID>195</HallID>
<Name>CC Cuts</Name>
<Location>Boston</Location>
<ItemGroup>
<WareHouseID>195</WareHouseID>
<ItemGroupID>235</ItemGroupID>
<Name>C Parts</Name>
<Item>
<ItemID>645</ItemID>
<ItemGroupID>235</ItemGroupID>
<Color>Red</Color>
<Location>B Wing</Location>
<Price>165.00</Price>
<Manufacture>Danish igc</Manufacture>
<Supplier>TransEuro</Supplier>
<SerialNumber>1645570683</SerialNumber>
</Item>
<Item>
<ItemID>646</ItemID>
<ItemGroupID>235</ItemGroupID>
<Color>Red</Color>
<Location>B Wing</Location>
<Price>165.00</Price>
<Manufacture>Danish igc</Manufacture>
<Supplier>TransEuro</Supplier>
<SerialNumber>1645570684</SerialNumber>
</Item>
...
</ItemGroup>
</WareHouse>
</Garage>

代码有效,但如果我尝试添加更大的XML文件,则需要花费大量时间才能完成。我相信这是因为我使用光标。是否有另一种更有效的方法从xml文件插入/更新数据?也许有人可以给我一个例子。

1 个答案:

答案 0 :(得分:1)

  1. 创建@variable或#temp表。
  2. &#34;撕碎&#34;将xml放入@variable或#temp表。
  3. 从@variable或#temp表更新/插入。
  4. 这样的事情:

    declare @XMLdata xml
    select @XMLdata = 
    '
    <Garage>
    <WareHouse>
    <WareHouseID>195</WareHouseID>
    <Name>CC Cuts</Name>
    <Location>Boston</Location>
    <ItemGroup>
    <WareHouseID>195</WareHouseID>
    <ItemGroupID>235</ItemGroupID>
    <Name>C Parts</Name>
    <Item>
    <ItemID>645</ItemID>
    <ItemGroupID>235</ItemGroupID>
    <Color>Red</Color>
    <Location>B Wing</Location>
    <Price>165.00</Price>
    <Manufacture>Danish igc</Manufacture>
    <Supplier>TransEuro</Supplier>
    <SerialNumber>1645570683</SerialNumber>
    </Item>
    <Item>
    <ItemID>646</ItemID>
    <ItemGroupID>235</ItemGroupID>
    <Color>Red</Color>
    <Location>B Wing</Location>
    <Price>165.00</Price>
    <Manufacture>Danish igc</Manufacture>
    <Supplier>TransEuro</Supplier>
    <SerialNumber>1645570684</SerialNumber>
    </Item>
    </ItemGroup>
    </WareHouse>
    </Garage>
    '
    
    
    
    
        IF OBJECT_ID('tempdb..#HolderOne') IS NOT NULL
        begin
                drop table #HolderOne
        end
    
    
        CREATE TABLE #HolderOne
        ( 
        SurrogateKeyIDENTITY int not null IDENTITY (1,1)
        ,  ItemGroupID nvarchar(50)
        , Color nvarchar(50)
        , Location nvarchar(50)
        , Price nvarchar(50)
        , Manufacture nvarchar(100)
        , Supplier nvarchar(100)
        , SerialNumber nvarchar(100)
        )
    
        INSERT INTO #HolderOne ( 
              ItemGroupID
            , Color
            , Location
            , Price
            , Manufacture
            , Supplier
            , SerialNumber
        )
    
        Select 
         xmlAlias.a.value('ItemGroupID[1]','nvarchar(50)'),
            Color = xmlAlias.a.value('Color[1]','nvarchar(50)'),
            Location = xmlAlias.a.value('Location[1]','nvarchar(50)'),
            Price = xmlAlias.a.value('Price[1]','nvarchar(50)'),
            Manufacture = xmlAlias.a.value('Manufacture[1]','nvarchar(100)'),
            Supplier = xmlAlias.a.value('Supplier[1]','nvarchar(100)'),
            SerialNumber = xmlAlias.a.value('SerialNumber[1]','nvarchar(100)')
            FROM
            @XMLdata.nodes('/Garage/WareHouse/ItemGroup/Item')AS xmlAlias(a)
    
    
        Select * from #HolderOne
    
        INSERT INTO WareHouse (ItemID, ItemGroupID, Color, Location, Price, Manufacture, Supplier, SerialNumber)
        Select
            0
            ,  ItemGroupID
            , Color
            , Location
            , Price
            , Manufacture
            , Supplier
            , SerialNumber  
        from #HolderOne holder
            where not exists ( select null from dbo.WareHouse innerRealTable where innerRealTable.ItemGroupID = holder.ItemGroupID )
    
        Update WareHouse
        Set 
                ItemGroupID = holder.ItemGroupID
            , Color = holder.Color
            , Location = holder.Location
            , Price = holder.Price
            , Manufacture = holder.Manufacture
            , Supplier = holder.Supplier
            , SerialNumber = holder.SerialNumber
        from #HolderOne holder , dbo.WareHouse  ware
        Where
            holder.ItemGroupID = ware.ItemGroupID
    
    
    
    
        IF OBJECT_ID('tempdb..#HolderOne') IS NOT NULL
        begin
                drop table #HolderOne
        end
    

    这是稍微改进的@variableTable代码......

    declare @XMLdata xml
    select @XMLdata = 
    '
    <Garage>
    <WareHouse>
    <WareHouseID>195</WareHouseID>
    <Name>CC Cuts</Name>
    <Location>Boston</Location>
    <ItemGroup>
    <WareHouseID>195</WareHouseID>
    <ItemGroupID>235</ItemGroupID>
    <Name>C Parts</Name>
    <Item>
    <ItemID>645</ItemID>
    <ItemGroupID>235</ItemGroupID>
    <Color>Red</Color>
    <Location>B Wing</Location>
    <Price>165.00</Price>
    <Manufacture>Danish igc</Manufacture>
    <Supplier>TransEuro</Supplier>
    <SerialNumber>1645570683</SerialNumber>
    </Item>
    <Item>
    <ItemID>646</ItemID>
    <ItemGroupID>235</ItemGroupID>
    <Color>Red</Color>
    <Location>B Wing</Location>
    <Price>165.00</Price>
    <Manufacture>Danish igc</Manufacture>
    <Supplier>TransEuro</Supplier>
    <SerialNumber>1645570684</SerialNumber>
    </Item>
    </ItemGroup>
    </WareHouse>
    </Garage>
    '
    
    
    
        /* changed to use @variable table
        IF OBJECT_ID('tempdb..#HolderOne') IS NOT NULL
        begin
                drop table #HolderOne
        end
        */
    
    
        /*CREATE TABLE #HolderOne*/
        Declare @HolderOne Table
        ( 
        SurrogateKeyIDENTITY int not null IDENTITY (1,1)
        , ItemID int
        , ItemGroupID int
        , Color nvarchar(50)
        , Location nvarchar(50)
        , Price nvarchar(50)
        , Manufacture nvarchar(100)
        , Supplier nvarchar(100)
        , SerialNumber nvarchar(100)
        )
    
        INSERT INTO @HolderOne ( 
              ItemID
            , ItemGroupID
            , Color
            , Location
            , Price
            , Manufacture
            , Supplier
            , SerialNumber
        )
    
        Select 
            xmlAlias.a.value('ItemID[1]','int'),
            xmlAlias.a.value('ItemGroupID[1]','int'),
            xmlAlias.a.value('Color[1]','nvarchar(50)'),
            xmlAlias.a.value('Location[1]','nvarchar(50)'),
            xmlAlias.a.value('Price[1]','nvarchar(50)'),
            xmlAlias.a.value('Manufacture[1]','nvarchar(100)'),
            xmlAlias.a.value('Supplier[1]','nvarchar(100)'),
            xmlAlias.a.value('SerialNumber[1]','nvarchar(100)')
            FROM
            @XMLdata.nodes('/Garage/WareHouse/ItemGroup/Item')AS xmlAlias(a)
    
    
        Select * from @HolderOne
    
    
        INSERT INTO WareHouse (/* ItemID, */ ItemGroupID, Color, Location, Price, Manufacture, Supplier, SerialNumber)
        Select
              /*holder.ItemId  , */
              holder.ItemGroupID
            , holder.Color
            , holder.Location
            , holder.Price
            , holder.Manufacture
            , holder.Supplier
            , holder.SerialNumber  
        from @HolderOne holder
            where not exists ( select null from dbo.WareHouse innerRealTable where innerRealTable.ItemId = holder.ItemId )
    
        Update WareHouse
        Set 
              ItemGroupID = holder.ItemGroupID
            , Color = holder.Color
            , Location = holder.Location
            , Price = holder.Price
            , Manufacture = holder.Manufacture
            , Supplier = holder.Supplier
            , SerialNumber = holder.SerialNumber
        from @HolderOne holder , dbo.WareHouse  ware
        Where
            holder.ItemId = ware.ItemId
    
    
    
            /* Changed to use variable table
        IF OBJECT_ID('tempdb..#HolderOne') IS NOT NULL
        begin
                drop table #HolderOne
        end
        */