Sql server 在SQL Server中通过XML插入或更新行(批量)
嗨,我似乎不知道如何解析Xml文档,以及如何决定它是否需要插入或更新 我现有的程序如下所示:Sql server 在SQL Server中通过XML插入或更新行(批量),sql-server,tsql,sql-server-2008,Sql Server,Tsql,Sql Server 2008,嗨,我似乎不知道如何解析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
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
很抱歉,我真的很烂SQL,这就是为什么上面是用伪C写的,所以我真的希望你能帮助我。
有什么想法吗
问候肯尼思
编辑
解决方案不是使用XML传递批量数据,而是使用TableParameter
表格类型
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
感谢您的帮助因为您使用的是SQL Server 2008,所以您可以利用MERGE语句根据记录的存在执行插入或更新,而不是使用if块构建存储过程。关于使用该声明,没有MSDN 编辑: 下面是合并语句的示例:
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)
此外,如果您想真正批量插入记录,可以考虑使用。如果要将XML文档中的5行插入到数据库中,可以像当前一样通过传入单个值来调用存储过程5次。通过使用表值参数,您可以通过向存储过程传递一个表参数来调用它一次,然后在存储过程中使用该表。您是在寻找关于如何编写存储过程的建议,还是在寻找关于如何使用C查询XML文档的建议?仅是存储过程我添加了C coveredI合并示例。这很聪明,但你能帮我在OP中用xmlinput实现his吗?@Kenned-你说你的C技能已经涵盖了,对吗?我的建议是将XML文档放入DataTable对象中。然后,如果您返工存储过程,您可以将该DataTable对象传递给您的存储过程。请参阅我在“编辑”中链接的文档,并像使用任何其他表一样使用它,即您可以加入它、从中选择、从中删除等。您采取的方法由您决定。如果XML文档中有相当多的行,那么使用table参数可以提高性能。谢谢,我甚至不知道可以将DataTable传递给存储过程。我会尝试它完美无瑕谢谢,顺便说一句,我将我的解决方案添加到了OPGreat solution@Ek0nomik。此外,我认为,如果您想让MERGE语句真正覆盖所有基础,那么您需要在更新期间删除源中不存在的行,并且这只有在您将数据作为DataTable对象传递以便有完整的源和目标进行比较时才可能。我目前正在实现一些非常类似的东西,由于DELETE操作也是一项要求,所以解决方案没有达到我所需要的效果,并且DataTable类型与MERGE结合使用保存了我。
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
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;
}
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)