SQL中declare变量的作用域(续)-----一些问题

在上次讨论了declare变量的作用域以后我们继续深入谈论一下,准确的说是我有些疑惑想跟大家讨论,有高手明白的话指点一下。

关于作用域的谈论:http://www.cnblogs.com/breezeli/archive/2010/04/16/1713308.html

这个问题不太好解释,大家看一段代码,在循环中定义表变量。

注意 代码使用Northwind 数据库,需要Northwind 库的请访问http://msdn.microsoft.com/zh-cn/library/ms143221.aspx

 

DECLARE   @id   INT
DECLARE  myCURSOR  CURSOR   FOR
    
SELECT   TOP   3  c.CategoryID  FROM  Categories c
OPEN  myCURSOR
FETCH   NEXT   FROM  myCURSOR  INTO   @id
 
WHILE   @@FETCH_STATUS   =   0
    
BEGIN
        
-- 当前循环的id输出
          SELECT   @id

        
DECLARE   @TessTable   TABLE  (
                
[ name ]   NVARCHAR ( 40 )
        )

        
-- DELETE FROM @TessTable

        
INSERT   INTO   @TessTable
        
SELECT  p.ProductName 
        
FROM  Products p
        
WHERE  p.CategoryID = @id

        
-- 当前循环的id下所有的产品名称输出
          SELECT   *   FROM   @TessTable
        
FETCH   NEXT   FROM  myCURSOR  INTO   @id
    
END
    
CLOSE  myCURSOR
    
DEALLOCATE  myCURSOR 
END

 

 

逻辑比较简单,就是从分类表(Categories)中取出所有分类的id,游标循环所有id,依次把每个类别的商品名称放到表变量中显示出来,这个查询没有实际意义就是为了展示一下问题,对代码本身的优劣不做过多要求。

  不知道大家看了这个查询后想象到的输出结果应该是什么样的?我认为结果是每次循环输出两个表,第一个是SELECT @id的结果输出当前循环到的CategoryID ,另一个是SELECT * FROM @TessTable的结果输出属于@id的所有产品的名称

 举例来说:

 比如我们现在有数据:

Categories

CategoryID

Name

1

Beverages

2

Condiments

Products

Id

ProductName

CategoryID

1

Chai

1

2

Chang

1

3

Aniseed Syrup

2

注意

表结构是我随意捏造的跟Northwind 略有不同

这样的数据那我认为的输出的两个表,以第1次循环来应该是

 

无名列

1

1

 

 

Name

1

Chai

2

Chang

实际截图:

  

 

第二次循环的第一个输出表的内容就应该是2,二个输出表应该就一项应该是Aniseed Syrup,不知道多少人跟我想的一样,可惜的是有多少人跟我想的一样就有多少人错了。

实际的结果第二次循环的输出内容为:

 

无名列

1

2

 

 

Name

1

Chai

2

Chang

3

Aniseed Syrup

第二次的查询结果是追加在第一次查询结果的表变量里的,为什么这样,我只能猜测,第一次循环时定义了表变量,因为declare的作用域是整个批处理,所以第二次循环是declare语句就不在执行了,当然这没什么理论依据,只是根据查询推断出来的,按说定义了一个变量再一次定义同名变量,应该会有错误,但是以上代码可以完好只执行,放到try里面也捕捉不到错误,哪位大虾能说清具体原理的指教一下小弟。

如果你想得到正确的结果那就把declare下面那句delete打开,每次都清一下数据结果就是正确的了。

 

说完表变量,那大家想象如果是变量做这样的操作,会不会累加啊?我上代码:

 

     DECLARE   @i   INT
    
SET   @i = 1
    
WHILE   @i < 6
    
BEGIN
        
PRINT   ' i: ' + cast ( @i   AS   nVARCHAR )

        
DECLARE   @t   VARCHAR
--       set @t='0'
         SET   @t = ' a ' + @t + cast ( @i   AS   nVARCHAR )

        
PRINT   ' t: ' + cast ( @t   AS   nVARCHAR )

        
SET   @i = @i + 1
    
END
    
GO

 

 

猜谜继续啊,你们猜猜是什么结果。

我直接说好了

i:1

i:2

i:3

i:4

i:5

 

 

这就是结果,根本没有print @t的内容,而且同样放到try里面不报错

这句--set @t='0'打开给@t赋一个初始值的话下面就就可以输出了但是结果依然很神奇

i:1

t:a

i:2

t:a

i:3

t:a

i:4

t:a

i:5

t:a

 

 

谁能告诉我为什么?

你可能感兴趣的:(sql)