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

C# 使用XML数据更新数据库中的行,c#,sql-server,sql-server-2005,datagridview,C#,Sql Server,Sql Server 2005,Datagridview,这是我第一次使用XML将数据插入表中。我正在保存前端的数据(所有Datagridview行)导入xml文件并将其发送到数据库以插入表SD_ShippingDetails。下面是用于读取xml数据和保存数据的查询。从查询中可以看出,我正在删除相关的ShippingID详细信息并再次插入。(从SD_ShippingDetails中删除,其中ShippingID=@ShippingID)。我们是否可以通过从XML获取数据来更新SD_ShippingDetails中已有的行。如果可以,请帮助我进行查询

这是我第一次使用XML将数据插入表中。我正在保存前端的数据(所有Datagridview行)导入xml文件并将其发送到数据库以插入表SD_ShippingDetails。下面是用于读取xml数据和保存数据的查询。从查询中可以看出,我正在删除相关的ShippingID详细信息并再次插入。(从SD_ShippingDetails中删除,其中ShippingID=@ShippingID)。我们是否可以通过从XML获取数据来更新SD_ShippingDetails中已有的行。如果可以,请帮助我进行查询

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 

谢谢。

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

2008年及以后,您可以借助合并功能

这里有一个很好的xml分解链接。注意,您使用的是较旧版本的OPENXML。这是一个更为Sql Server 2000的命令。查看下面Plamen的博客,了解2005年及以上的语法


我将把XML填充到一个变量表中,然后使用
Update
语句和
Insert
,其中
不存在

如果您有SQL 2008,您可以用以下语句替换您的delete和insert语句

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

您使用的是SQLServer2005,因此可以使用XML数据类型而不是openxml,因此此答案使用该数据类型。解决方案不需要使用XML数据类型。如果愿意,可以使用openxml重写

您在注释中指定在SD_ShippingDetails中有一个ID标识字段(我假设它是主键),但您还说ShippingID和权重的组合是唯一的。这就给我们留下了一个如下的表结构

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)')
                 );

您可以将XML数据填充到临时/变量表中,然后使用合并插入/更新现有表。你知道怎么做吗?嗨,伙计,你能帮我查询一下吗?因为我不知道怎么做。你需要提供一些XML。如果你使用的是SQL 2005,你不能像其他人指出的那样使用合并(是的,它已经在sql 2008中引入:-(他将他的问题标记为“sql Server 2005”,因此为什么合并(upsert)我相信这对他不起作用。嗨,谢谢你,伙计。虽然我没有完全理解我写的查询。作为紧急事项,我从网络上复制了它,它工作得很好。我已经通过了链接,但不太了解。我会尝试用链接编写更新查询。第一步是将数据放入@variable或#temp表中。我首先从@variable表开始。第2步是更新……并将实际表的PK与PK(主键)匹配是的,更新匹配的行是比删除所有内容并重新插入更好的策略。我不知道如何实现这一点。如果我不使用XML概念,而是通过在前端循环插入Datagridview中的每一行,会不会影响性能?有一点是肯定的,对DB将增加。您正在谈论RBAR“一行接一行”。试着考虑“基于集合”,而不是RBAR。您稍后会感谢我。PS是的,这会影响性能。每次RBAR操作后都必须重建任何索引。注意:这是给不知道的dotnet开发人员的一个小建议。我认为,当我们使用XML参数创建StoredProcess时,我们不需要在前端将参数作为XElement(XML类型)发送。将参数设置为SQLDBTYPE.XML,将值设置为字符串。