在存储过程中插入或更新用户定义的表类型

Posted

技术标签:

【中文标题】在存储过程中插入或更新用户定义的表类型【英文标题】:Insert or Update user-defined table type in a stored procedure 【发布时间】:2014-03-28 09:15:02 【问题描述】:

我目前正在从事一个项目,我经常将大量数据插入或更新到远程数据库。数据量约为 50 组数据,每组 500-800 行,进入同一张表。

目前我有一个存储过程,我调用它来插入或更新每一行(为了便于阅读而进行了简化):

ALTER PROCEDURE stat_memberstat_upsert
...
AS
BEGIN
UPDATE Memberstats ...

if(@@ROWCOUNT = 0)
BEGIN 
    INSERT INTO Memberstats ...
END
END

这可行,但正如您所见,它会挂载到对同一个存储过程的大量调用(最坏的情况是大约 100,000 次调用)。我正在研究用户定义的表类型,这听起来像是一个很好的解决方案,因为它减少了对数据库服务器的调用,并且结构更庞大。问题是,当我查看解决方案、教程和文档时,我发现没有人提到使用表类型执行插入/更新例程的方法;它是插入或更新。

在处理表类型时,有没有办法进行插入/更新调用?


另外,我考虑了两种解决方法:

1:使用光标

我可以使用游标遍历表类型值并为每一行调用上面的 stat_memberstat_upsert 过程。这不会阻止对过程的多次调用,但由于调用是从本地存储过程完成的,因此速度可能会提高。

How to do ForEach on user defined table type in SQL Server stored procedure?(回答“为什么不使用光标???”)

2:预验证数据

第二种解决方案是检索已经插入的行主键,根据传入数据验证它们并将它们分类到 2 个表中,其中一个用于插入,另一个用于更新。然后将两个表都执行到数据库中。这意味着我需要将其封装在事务中,以便在验证和执行插入和更新期间表不会更改。

这些都是一个好的解决方案吗?

【问题讨论】:

我不确定您在哪里查看过您只能插入或更新的印象,但您是否查看过MERGE @Damien_The_Unbeliever 我从未听说过合并。谢谢你的提示;我目前正在检查是否可以使其与 Merge 一起使用 另外,可能超出了您的范围,但这听起来像是作为 SSIS 包更好地实现的东西? @Damien_The_Unbeliever 你是救生员。 MERGE 适用于表类型,速度现在令人难以置信。谢谢!您能否创建一个答案,以便我们关闭它? 【参考方案1】:

这两种解决方案都可能进一步减慢速度。 您可以简单地将插入语句插入表中

ALTER PROCEDURE stat_memberstat_upsert
...
AS
INSERT INTO Memberstats_temp ...
END

并有一个批处理过程,该过程将在低流量时间运行,以在截断此临时表之后从 Memberstats_temp 表中更新/插入 Memberstats 表。如果您需要实时更新表格,这不是解决方案。

【讨论】:

以上是关于在存储过程中插入或更新用户定义的表类型的主要内容,如果未能解决你的问题,请参考以下文章

从存储过程结果集中在表上插入/更新数据

SQL插入,使用合并存储过程更新

使用 JDBC 将用户定义的表类型传递给 SQL Server 存储过程

使用 JDBC 将用户定义的表类型传递给 SQL Server 存储过程

SQL Server 列存储索引更新/插入存储过程

使用多个表源合并(用户定义的表类型和输入参数)