bbq*_*bot 4 sql-server t-sql parameter array table-valued-parameters
我在一个新职位上,被告知要实现一个存储过程,该过程将接受用户 ID 列表并更新一个标志。
当我建议使用表值参数(数组模拟)时,我被告知要实现如下所示,因为这是以前的做法。我不是 DBA,但我是一名全栈开发人员,这对我来说很有趣。
仅供参考 - 用户 ID 实现为类型 int
CREATE PROCEDURE [dbo].[UpdateUsers]
@rgIDs varbinary(max) -- contains several ids
AS
DECLARE @tblTmp TABLE (ID int PRIMARY KEY)
DECLARE @ich int, @cch int, @ID int
SET @cch = DATALENGTH (@rgIDs)
SET @ich = 1
WHILE (@ich < @cch)
BEGIN
SET @ID = SUBSTRING (@rgIDs, @ich, 4)
UPDATE dbo.Users u
SET isUpdated = 1
WHERE u.ID = @ID
SET @ich = @ich + 4
END
Run Code Online (Sandbox Code Playgroud)
不是表值类型在这里工作得更好吗?更具可读性、性能、更不容易出错等......?
我相信我将使用 SQL Server 2012 或 2014。绝对> 2008年。
我被告知要按照下面的演示进行实施,因为这是以前的做法。......这对我来说很有趣。
你知道什么比这种方法更有趣吗?那条“推理”。旧的“这就是它一直以来的做法”只是一种避免思考和讨论它的方法。即使发现代码是最好的方法,仅此一项就应该引起危险。之前有人告诉我同样的事情,这是出于同样可悲的潜在原因:采用这种方法是出于过时的原因(例如旧版本的 SQL Server 没有特定功能,但我们使用的是具有该功能的较新版本)。非常令人沮丧。
不是表值类型在这里工作得更好吗?更具可读性、性能、不易出错等...
假设您使用的是 SQL Server 2008 或更高版本,那么答案通常都是肯定的。我的意思是,当前的代码是一种避免字符串拆分操作的有点聪明的方法。但是,TVP 可以是强类型的,因此无需int
将应用程序层中的值修改为byte[]
just 以便它可以在WHILE
此处循环解压缩。基于该列表中的 ID 数量(当前代码创建和提交)每个语句1 个事务,因为循环未包含在显式事务中,因此单个基于集合的UPDATE
语句的性能将比 N 个语句好得多. 因此,在当前方法中,要更新的 20 个 ID = 20 个事务。这就是为什么单一的、基于集合的UPDATE
UPDATE
WHILE
UPDATE
效率更高。
只要确保实现全流方法,这意味着:不要将集合中的值转储到DataTable
! 不幸的是,您在大多数示例中都会发现这样做是对时间、内存和 CPU 的不必要浪费。相反,创建一个实现IEnumerable
、接受 UserID 集合并返回 的方法IEnumerable<SqlDataRecord>
。然后,使用该方法作为SqlParameter
TVP的“值” 。在该方法中,循环遍历集合,并对每个元素调用yield return;
.
在我对以下问题的回答中,我有一些关于 StackOverflow 的示例代码:
请注意,我听说,虽然尚未测试,但在更新的 SQL Server 版本(2014 或更新版本)上,通过对用户定义的表类型使用内存中 OLTP 可能会获得额外的性能提升。
此外,由于您提到这一点是希望“更易读的代码”的一部分,我建议使用有意义的参数和变量名称:-)。是的,我确实意识到这可能不是您的代码,但只是想我会提到它。此外,我会摆脱DECLARE @tblTmp
它,因为它没有被使用,但同样,我意识到这可能是您编辑的更大示例的一部分。
归档时间: |
|
查看次数: |
409 次 |
最近记录: |