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

 

 

谁能告诉我为什么?

posted on 2010-04-16 14:30  水一  阅读(1950)  评论(4编辑  收藏  举报

导航