您好我似乎无法解决如何解析Xml文档并决定是否需要插入或更新。
我有一个像这样的现有程序:
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 Argument
批量运行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#编写的原因),所以我真的希望你能帮助我。 有什么想法吗?
关心肯尼思
修改
解决方案不是使用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 :(得分:2)
由于您使用的是SQL Server 2008,因此可以使用MERGE
语句执行INSERT或UPDATE,而不是使用if块构建存储过程,具体取决于是否存在记录。使用该声明时有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次。通过使用表值参数,您可以通过处理表参数来调用存储过程一次,然后在存储过程中使用该表。