sql-server – 为什么TVP必须是READONLY,为什么其他类型的参数不
根据 this blog函数或存储过程的参数,如果它们不是OUTPUT参数,则基本上是按值传递,并且如果它们是OUTPUT参数,则基本上被视为更安全的传递版本. 起初我认为强制TVP被宣布为READONLY的目的是向开发人员明确表示TVP不能用作OUTPUT参数,但必须有更多进展因为我们不能将非TVP宣布为READONLY .例如,以下失败: create procedure [dbo].[test] @a int readonly as select @a
>自TV001于statistics aren’t stored开始,防止DML操作背后的理由是什么? 解决方法这个解释似乎与以下组合有关:a)来自链接博客的细节,这个问题中没有提到,b)TVP的语用符合参数总是进出的方式,c)和性质表变量.>链接博客文章中包含的缺失细节正是变量如何传入和传出存储过程和函数(这与“如果它们是OUTPUT参数的更安全版本的传递参数”问题中的措辞有关“ ):
这个难题的第1部分是参数总是“按值”传递.并且,仅当参数标记为OUTPUT并且存储过程成功完成时才会实际发回当前值.如果OUTPUT值真正“通过引用”传递,那么指向该变量的内存中的位置的指针将是传递的东西,而不是值本身.如果您传入指针(即内存地址),则即使存储过程的下一行导致错误并且中止执行,也会立即反映所做的任何更改. 总结第1部分:始终复制变量值;他们的内存地址没有引用它们.
此外,这种内存管理问题并不是一个新概念,因为它可以在SQL Server 2005中引入的SQLCLR API中找到(TVP在SQL Server 2008中引入).将NVARCHAR和VARBINARY数据传递给SQLCLR代码(即SQLCLR程序集中.NET方法的输入参数)时,您可以选择使用SqlString或SqlBinary分别使用“by value”方法,或者可以选择分别使用SqlChars或SqlBytes的“按引用”方法. SqlChars和SqlBytes类型允许将数据完全流式传输到.NET CLR,这样您就可以提取大块的大值,而不是复制整个200 MB(最多2 GB,右)值. 总结第2部分:TVP,就其本质而言,如果留在“永远复制价值”模型中,就会倾向于消耗大量内存(从而恶化性能).因此,TVP做了一个真正的“通过参考传递”. 现在,某个人,某个地方,可能正在与他们的监视器说话,“好吧,只需构建一个自动化设施,用于回滚对TVP参数所做的任何更改,如果有任何传入存储过程的话.杜.问题解决了.”没那么快.这就是表变量的性质所在:对表变量的更改不受事务约束!所以没有办法回滚变化.实际上,如果需要回滚,这是用于保存事务中生成的信息的技巧:-). 总结第3部分:表变量不允许在导致存储过程中止的错误的情况下“撤消”对它们所做的更改.这违反了设计目标,即让参数永远不会反映部分执行(第1部分). Ergo:需要READONLY关键字来防止对TVP的DML操作,因为它们是实际通过“引用”传递的表变量,因此即使存储过程遇到错误,也会立即反映对它们的任何修改,并且别无他法. 此外,其他数据类型的参数不能使用READONLY,因为它们已经是传入内容的副本,因此它不会保护任何尚未受保护的内容.那个,以及其他数据类型的参数的工作方式是读写的,因此将API改为现在包含只读概念可能会更加有效. (编辑:晋中站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |