2011-10-06 97 views
0

嗨我似乎无法包装我的头如何解析一个Xml文档,并决定是否需要插入或更新。插入或更新通过SQL Server中的行(批量)

我有一个现成的过程,loks这样的:

CREATE PROCEDURE [dbo].[SavePrice] 
-- Add the parameters for the stored procedure here 
@Groupid varchar(150), @Price varchar(150), @CustomerID varchar(150) 
AS 
BEGIN 
    -- SET NOCOUNT ON added to prevent extra result sets from 
    -- interfering with SELECT statements. 
    SET NOCOUNT ON; 

IF (EXISTS(SELECT * FROM dbo.Prices WHERE groupid = @Groupid AND CustomerID = @CustomerID)) 
    UPDATE 
     dbo.Prices 
    SET 
     price = @Price 
    WHERE 
     groupid = @Groupid 
    AND 
     CustomerID = @CustomerID; 

ELSE 
    INSERT INTO 
     dbo.Prices 
    (
     price, 
     groupid, 
     customerid 
    ) 
    VALUES 
    (
     @price, 
     @groupid, 
     @customerid 
    ); 
End 

现在我想这在散装最好从XML参数运行此

XML

<ArrayOfPrice xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <Price> 
    <Undergroup>111</Undergroup> 
    <Gain>10</Gain> 
    <CustomerID>14001099</CustomerID> 
    </Price> 
    </ArrayOfPrice> 

喜欢的东西这

foreach(Row r in XmlDoc) 
{  
    Procedure(r) 
} 

我很抱歉,但我真的很喜欢SQL(这就是为什么上面是用伪C#写的),所以我真的希望你能帮助我。 任何想法?

问候肯尼斯

EDIT

该溶液不使用XML来传递批量数据,但TableParameter

TABLETYPE

CREATE TYPE [dbo].[PriceDataType] As Table 
(
--This type has structure similar to the DB table 
GroupID varchar(50) Not Null, 
Price varchar(50) Not Null, 
CustomerID varchar(50) Not Null 
) 

存储过程

ALTER PROCEDURE [dbo].[SavePrice] 
    -- Add the parameters for the stored procedure here 
    @Dt PriceDataType READONLY 
AS 
BEGIN 
    -- SET NOCOUNT ON added to prevent extra result sets from 
    -- interfering with SELECT statements. 
    SET NOCOUNT ON; 

MERGE Prices AS Prices 
    USING (SELECT * FROM @Dt) AS Source 
    ON (Prices.GroupId = Source.GroupId) AND (Prices.CustomerId= Source.CustomerId) 
    WHEN MATCHED THEN 
     UPDATE SET Prices.Price = Source.Price 
    WHEN NOT MATCHED THEN 
     INSERT (Price, GroupId, CustomerId) 
     VALUES (Source.Price, Source.GroupId, Source.CustomerId); 
End 

C#

 public void SavePrices(Price[] prices) 
     { 


      SqlCommand cmd = new SqlCommand("SavePrice", conn); 
      cmd.CommandType = CommandType.StoredProcedure; 

      conn.Open(); 


      cmd.Parameters.Add(new SqlParameter("@Dt", SqlDbType.Structured)); 
      cmd.Parameters["@Dt"].Value = GetTableFromList(prices); 

      cmd.ExecuteScalar(); 


      conn.Close(); 
      cmd.Dispose(); 


     } 


     private DataTable GetTableFromList(Price[] ps) 
     { 
      DataTable tbl = new DataTable("PriceDataType"); 
      tbl.Columns.Add("GroupID", typeof(string)); 
      tbl.Columns.Add("Price", typeof(string)); 
      tbl.Columns.Add("CustomerID", typeof(string)); 

      foreach (Price p in ps) 
       tbl.Rows.Add(p.Undergroup, p.Gain, p.CustomerID); 
      return tbl; 
     } 

感谢您的帮助

+0

你只是在寻找关于如何编写存储过程或者如何用C#查询XML文档的建议吗? –

+0

只需存储过程我已经涵盖了C# –

+0

我为您添加了一个MERGE示例。 –

回答

2

由于您使用SQL Server 2008中,而不是用一个构建的存储过程,如果块,你可以利用MERGE语句执行INSERT或根据记录的存在进行更新。有关使用该语句的MSDN documentation

编辑:

这里是你的MERGE语句可能看起来像一个例子:

MERGE Prices AS Prices 
    USING (SELECT @GroupId, @CustomerId) AS Source 
    ON (Prices.GroupId = Source.GroupId) AND (Prices.CustomerId= Source.CustomerId) 
    WHEN MATCHED THEN 
     UPDATE SET Prices.Price = @Price 
    WHEN NOT MATCHED THEN 
     INSERT (Price, GroupId, CustomerId) 
     VALUES (@Price, @GroupId, @CustomerId) 

另外,如果你想批量真正插入你的纪录,你可以考虑使用一个table valued parameter。如果您想要插入到数据库中的XML文档中有5行“行”,则可以通过传递各个值(如您当前所做的)来调用存储过程5次。通过使用表值参数,您可以调用存储过程一次,方法是传递一个表参数,然后在存储过程中使用该表。

+0

这是非常聪明的,但你能帮我用OP中的xmlinput来实现他吗? –

+0

@Kenned - 所以你说你的C#技能是覆盖的,对吧?我建议把你的XML文档放到DataTable对象中。然后(如果你重写了你的存储过程),你可以将这个DataTable对象传递给你的存储过程(参见我在编辑中链接到的文档),并像使用其他表一样使用它(也就是说,你可以加入它,它,删除它等)。你采取的方法取决于你。如果你的XML文档中有很多“行”,你可以通过使用table参数来提高性能。 –

+0

谢谢我甚至不知道你可以将DataTable传递给商店程序。我会尝试一下 –