Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 在SQL Server中通过XML插入或更新行(批量)_Sql Server_Tsql_Sql Server 2008 - Fatal编程技术网

Sql server 在SQL Server中通过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

嗨,我似乎不知道如何解析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参数运行

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)