我可以在两次调用SQL Server UDF之间保持状态吗?
我有一个SQL脚本,用于插入数据(通过INSERT语句,当前编号为数千),其中一列包含一个唯一的标识符(尽管不是IDENTITY类型,只是一个普通的int),实际上在几个不同的表中是唯一的。
我想在我的脚本中添加一个标量函数,以获取下一个可用的ID(即上次使用的ID + 1),但是我不确定这是否可行,因为似乎没有使用全局或者从UDF内部获取静态变量,我无法使用临时表,也无法从函数内部更新永久表。
目前,我的脚本如下所示:
declare @v_baseID int exec dbo.getNextID @v_baseID out --sproc to get the next available id --Lots of these - where n is a hardcoded value insert into tableOfStuff (someStuff, uniqueID) values ('stuff', @v_baseID + n ) exec dbo.UpdateNextID @v_baseID + lastUsedn --sproc to update the last used id
但我希望它看起来像这样:
--Lots of these insert into tableOfStuff (someStuff, uniqueID) values ('stuff', getNextID() )
对偏移量进行硬编码是一个麻烦,而且容易出错。将其打包成一个简单的标量函数非常吸引人,但是我开始认为不能那样做,因为似乎没有办法在调用之间保持偏移量计数器。是的,还是我想念的东西。
目前,我们正在使用SQL Server 2005.
编辑以澄清:
不会有两个用户点击它。这是一个升级脚本,将只运行一次,并且永远不会同时运行。
实际的sproc没有以sp_为前缀,修复了示例代码。
在正常使用中,我们确实使用id表和sproc根据需要获取ID,我只是在寻找一种更干净的方法来执行此脚本,该脚本实际上只是将一堆数据转储到db中。
解决方案
回答
如果我们有2个用户同时点击它,他们将获得相同的ID。为什么不使用带有标识的id表,而是将其插入并使用它作为唯一的(保证的)id,这样做也会更快
sp_getNextID
永远不会在proc前面加上sp_前缀,这对性能有影响,因为优化器首先检查主数据库以查看该proc是否存在,然后再检查本地DB,而且如果MS决定在服务包中创建sp_getNextID,则我们将永远不会执行
回答
这可能比它值得的工作还多,但是我们可以在SQL CLR UDF中使用静态C#/ VB变量,因此我认为我们可以通过每次UDF每次简单地增加此变量就可以完成我们想做的事情叫。当然,只要卸载appdomain,静态变量就会丢失。因此,如果我们需要一天到一天的ID连续性,则需要一种在首次访问NextId时轮询使用该ID的所有表以找到最高价值的方法。
回答
I'm starting to think it can't be done that way since there doesn't seem to be a way to maintain the offset counter between calls. Is that right, or is there something I'm missing.
我们什么都不会错过; SQL Server不支持全局变量,也不支持UDF中的数据修改。而且,即使我们想做一些像使用CONTEXT_INFO一样的笨拙操作(请参阅http://weblogs.sqlteam.com/mladenp/archive/2007/04/23/60185.aspx),也无法从UDF内进行设置反正。
有没有一种方法可以通过使变量成为变量并遍历其迭代,然后在该循环中进行插入来解决偏移量的"硬编码"?