使用XML数据更新数据库中的行

时间:2013-03-19 18:31:20

标签: c# sql-server sql-server-2005 datagridview

这是我第一次使用XML将数据插入表中。我将数据从前端(所有Datagridview行)保存到xml文件中并将其发送到数据库以插入表SD_ShippingDetails.Below是查询读取XML数据和保存数据。您可以从查询中看到我删除相关的ShippingID详细信息并再次插入。(DELETE FROM SD_ShippingDetails WHERE ShippingID = @ ShippingID)。我们可以更新SD_ShippingDetails中现有的行通过从XML获取数据。如果是,请帮我查询。

CREATE PROCEDURE SD_Insert_ShippingDetails    
@PBMXML as varchar(Max),      
@ShippingID as INT      

AS      
BEGIn      


declare @i int      

exec sp_xml_preparedocument @i output,@PBMXML      



DELETE FROM SD_ShippingDetails WHERE ShippingID=@ShippingID      


INSERT INTO  SD_ShippingDetails(ShippingID,Weight,Height,TotalBoxes,Price)      
SELECT ShippingID,Weight,Height,TotalBoxes,Price FROM OPENXML(@i,'Root/ShippingBox',2)      
WITH (      
ShippingID int,Weight varchar(20),Height varchar(20),TotalBoxes varchar(20),Price numeric(18,2))    



exec sp_xml_removedocument @i      

END 

感谢。

3 个答案:

答案 0 :(得分:1)

您使用的是SQL Server 2005,因此您可以使用XML数据类型而不是openxml,因此这个答案会使用它。解决方案不需要使用XML数据类型。如果您愿意,可以使用openxml重写。

您在评论中指出SD_ShippingDetails中有一个ID身份字段(我假设这是主键),但您也说过ShippingID和Weight的组合是唯一的。这让我们看起来像这样的表结构。

create table dbo.SD_ShippingDetails
(
  ID int identity primary key,
  ShippingID int not null,
  Weight varchar(20) not null,
  Height varchar(20),
  TotalBoxes varchar(20),
  Price numeric(18,2),
  unique (ShippingID, Weight)
);

存储过程首先需要更新SD_ShippingDetails中已存在的所有行,然后需要插入缺少的行。

create procedure dbo.SD_Insert_ShippingDetails
  @PBMXML as xml
as

update dbo.SD_ShippingDetails 
set Height = T.N.value('(Height/text())[1]', 'varchar(20)'),
    TotalBoxes = T.N.value('(TotalBoxes/text())[1]', 'varchar(20)'),
    Price = T.N.value('(Price/text())[1]', 'numeric(18,2)')
from @PBMXML.nodes('Root/ShippingBox') as T(N)
where ShippingID = T.N.value('(ShippingID/text())[1]', 'int') and
      Weight = T.N.value('(Weight/text())[1]', 'varchar(20)');

insert into dbo.SD_ShippingDetails(ShippingID, Weight, Height, TotalBoxes, Price)
select T.N.value('(ShippingID/text())[1]', 'int'),
       T.N.value('(Weight/text())[1]', 'varchar(20)'),
       T.N.value('(Height/text())[1]', 'varchar(20)'),
       T.N.value('(TotalBoxes/text())[1]', 'varchar(20)'),
       T.N.value('(Price/text())[1]', 'numeric(18,2)')
from @PBMXML.nodes('Root/ShippingBox') as T(N)
where not exists (
                 select *
                 from dbo.SD_ShippingDetails
                 where ShippingID = T.N.value('(ShippingID/text())[1]', 'int') and
                       Weight = T.N.value('(Weight/text())[1]', 'varchar(20)')
                 );

SQL Fiddle

答案 1 :(得分:0)

如果你有Sql Server 2005,那么将值放在#temp或@variables表中是最好的。

2008年及以后,您可以重新使用MERGE功能。

http://msdn.microsoft.com/en-us/library/bb522522(v=sql.105).aspx

这是xml碎化的一个很好的链接。请注意,您使用的是旧版本的OPENXML。这是一个更多的Sql Server 2000命令。查看Plamen的博客,了解2005年及以上的语法。

http://pratchev.blogspot.com/2007/06/shredding-xml-in-sql-server-2005.html

答案 2 :(得分:0)

我会将您的XML填充到变量表中,然后使用Update语句和Insert Not Exists

如果你有SQL 2008,你可以用这个替换你的删除和插入语句......

MERGE   SD_ShippingDetails AS Target
USING  (SELECT  ShippingID,
                Weight,
                Height,
                TotalBoxes,
                Price 
        FROM    OPENXML(@i,'Root/ShippingBox',2)      
                WITH   (ShippingID int,
                        Weight varchar(20),
                        Height varchar(20),
                        TotalBoxes varchar(20),
                        Price numeric(18,2)) ) AS source (ShippingID,Weight,Height,TotalBoxes,Price)
        ON (target.ShippingID = source.ShippingID)
WHEN    MATCHED THEN 
        UPDATE  SET Weight = source.Weight,
                    Height = source.Height,
                    TotalBoxes = source.TotalBoxes,
                    Price = source.Price
WHEN    NOT MATCHED THEN    
        INSERT (ShippingID,Weight,Height,TotalBoxes,Price)
        VALUES (source.ShippingID,source.Weight,source.Height,source.TotalBoxes,source.Price);