首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > SQL Server >

SQL的变量生存期的有关问题

2012-01-24 
SQL的变量生存期的问题,我有一个自定义函数,根据ID返回一个表变量,在下面的存储过程的循环内,声明一个和返

SQL的变量生存期的问题,

  有一个自定义函数,根据ID返回一个表变量,
  在下面的存储过程的循环内,声明一个和返回表有相同结构的表变量。在每次循环时根据游标的变化ID,传入自定义函数,
将返回的表插入到声明的表变量中。然后经过计算后,将结果插入另一张表。
  问题是:每次循环计算的某些列的值是相同的。但自定义函数根据ID每次返回的表是正确的。
  解决方法是:我怀疑是UPDATE时表变量中的数据没变。所以在每次循环时都要清空表变量,问题才得以解决。按程序的特点来说,一个变量从声明开始到它遇到的第一个左大括号结束,可是为
什么下面的问题在第二次循环时值还存在呢?
--------------------------------------

SQL code
 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



[解决办法]
变量在你的这个过程里是一直存在的,除非这个过程结束,或你人为进行处理。
[解决办法]
1、这样更合理吧

declare cur cursor for ...
open cur
declare @t table(....)
fetch cur ...
while @@fetch_status ...
begin
delete from @t....
insert @t select ....


fetch into ....
end

close cur
deallocate cur
2、

如果你不删除表变量里的数据时表变量 里是存放的上一次的数据行

[解决办法]
@pTable 应该在每次循环开始都重新声明并赋值
------------
错误:变量在生成执行计划时声明并分配内存空间


难道@pTable 作用域是整个循环? 
---------------
循环之外仍能访问,是整个批有效。
[解决办法]

SQL code
--> @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
[解决办法]
变量在你的这个过程里是一直存在的,除非这个过程结束,或你人为进行处理。


同意
[解决办法]
变量只在当前批处理中有作用,超出这个批处理就失效了。
[解决办法]
这和存储过程有关,存储过程是预先已经编译好的,也就是说内存已经分配好了,只要执行第一次,那么数据是不会在后续执行过程中清理的,只是覆盖。要想解决你的问题,得人为增加代码来处理。

热点排行