SQL的变量生存期的问题,
我
有一个自定义函数,根据ID返回一个表变量,
在下面的存储过程的循环内,声明一个和返回表有相同结构的表变量。在每次循环时根据游标的变化ID,传入自定义函数,
将返回的表插入到声明的表变量中。然后经过计算后,将结果插入另一张表。
问题是:每次循环计算的某些列的值是相同的。但自定义函数根据ID每次返回的表是正确的。
解决方法是:我怀疑是UPDATE时表变量中的数据没变。所以在每次循环时都要清空表变量,问题才得以解决。按程序的特点来说,一个变量从声明开始到它遇到的第一个左大括号结束,可是为
什么下面的问题在第二次循环时值还存在呢?
--------------------------------------
declare @win char(10)
DECLARE win_cursor CURSOR FOR
SELECT [ID]
FROM sys_CheckOneKm
WHERE CheckID=@runID
OPEN win_cursor
FETCH NEXT
FROM win_cursor into @win
WHILE @@FETCH_STATUS =0
BEGIN
/*-----------------------------
*在此计算ID为@win的千米表的参数
------------------------------*/
---定义数据参数
declare
@MQI decimal(15,7),@PQI decimal(15,7),@PCI decimal(15,7),@RQI decimal(15,7),@RDI decimal(15,7),@SRI decimal(15,7),@PSSI decimal(15,7),@SCI decimal(15,7),@BCI decimal(15,7),@TCI decimal(15,7) ,@Thinkness decimal(15,7)
--定义存储表
declare @pTable table(
[ID] [smallint] IDENTITY (1, 1) NOT NULL ,
-- MQI decimal(15,7),
-- PQI decimal(15,7),
-- PCI decimal(15,7),
RQI decimal(15,7),
RDI decimal(15,7),
SRI decimal(15,7),
PSSI decimal(15,7),
WiAi decimal(15,7),
Ai decimal(15,7),
Thinkness decimal(15,7)
)
delete @pTable
--调用运算千米函数
select * from @pTable --测试查看每一千米返回的基本数据
INSERT INTO @pTable(RQI ,RDI,SRI,PSSI,WiAi,Ai,Thinkness) SELECT RQI ,RDI,SRI,PSSI,WiAi,Ai,Thinkness FROM dbo.[retTabel](@win)
--select * from @pTable --测试查看每一千米返回的基本数据
print @win --测试打印出循环获得的千米ID
SET @PCI= dbo.[retPCI](@win,(SELECT SUM(CAST([WiAi] as decimal(15,7))) FROM @pTable))
SET @RQI=(SELECT AVG(CAST([RQI] as decimal(15,7))) FROM @pTable)
SET @RDI=(SELECT AVG(CAST([RDI] as decimal(15,7))) FROM @pTable)
SET @SRI=(SELECT AVG(CAST([SRI] as decimal(15,7))) FROM @pTable)
SET @PSSI=(SELECT AVG(CAST([PSSI] as decimal(15,7))) FROM @pTable)
SET @Thinkness=(SELECT AVG(CAST([Thinkness] as decimal(15,7))) FROM @pTable)
SET @PQI=dbo.[retPQI] (@PCI,@RQI,@RDI, @SRI)
--SET @SCI=(SELECT AVG(CAST([SCI] as decimal(15,7))) FROM dbo.[retTabel](@win))
--SET @BCI=(SELECT AVG(CAST([BCI] as decimal(15,7))) FROM dbo.[retTabel](@win))
--SET @TCI=(SELECT AVG(CAST([TCI] as decimal(15,7))) FROM dbo.[retTabel](@win))
--SET @MQI=(SELECT AVG(CAST([MQI] as decimal(15,7))) FROM dbo.[retTabel](@win))
--更新千米参数值
UPDATE sys_CheckOneKm SET MQI=@MQI,PQI=@PQI,PCI=@PCI,RQI=@RQI,RDI=@RDI,SRI=@SRI,PSSI=@PSSI,SCI=@SCI,BCI=@BCI,TCI=@TCI
,Thinkness=@Thinkness WHERE ID=@win
FETCH NEXT FROM win_cursor into @win
End
close win_cursor --关闭游标
deallocate win_cursor
END
GO
fetch into ....
end
close cur
deallocate cur
2、
如果你不删除表变量里的数据时表变量 里是存放的上一次的数据行
[解决办法]
@pTable 应该在每次循环开始都重新声明并赋值
------------
错误:变量在生成执行计划时声明并分配内存空间
难道@pTable 作用域是整个循环?
---------------
循环之外仍能访问,是整个批有效。
[解决办法]
--> @pTable貌似没有什么作用,里面这样处理,定义多一个@WiAi:declare @WiAi decimal(15,7)SELECT @WiAi=SUM(CAST([WiAi] as decimal(15,7))) @RQI=AVG(CAST([RQI] as decimal(15,7))), @RDI=AVG(CAST([RDI] as decimal(15,7))), @SRI=AVG(CAST([SRI] as decimal(15,7))), @PSSI=AVG(CAST([PSSI] as decimal(15,7))), @Thinkness=AVG(CAST([Thinkness] as decimal(15,7)))FROM dbo.[retTabel](@win)SET @PCI= dbo.[retPCI](@win,@WiAi)
[解决办法]
觉得楼主“按程序的特点来说,一个变量从声明开始到它遇到的第一个左大括号结束”这句话理解有问题。
以for循环为例,在for循环内部中定义的变量的一个变量是在for循环结束后才会消失的,即for(int i=0;i<10;i++)那么i变量在这个循环结束后才会结束它的生命,而不是遇到第一个}。那么楼主的@ptable声明在while循环中,自然也是这样的啊,第二次循环,@ptable依然存在,那么存放的是上一次循环的值,所以要delete
[解决办法]
变量在你的这个过程里是一直存在的,除非这个过程结束,或你人为进行处理。
同意
[解决办法]
变量只在当前批处理中有作用,超出这个批处理就失效了。
[解决办法]
这和存储过程有关,存储过程是预先已经编译好的,也就是说内存已经分配好了,只要执行第一次,那么数据是不会在后续执行过程中清理的,只是覆盖。要想解决你的问题,得人为增加代码来处理。