一、变量的默认值和作用域
变量的作用域(变量的生命周期)只能是当前的批处理。
新声明的变量的默认值为空值,在表达式中使用它们之前必须先为它们赋初值。
下面的例子来说明:
declare @test int,           --声明变量和数据类型
        @test2 nvarchar(25)
select @test,@test2        --查询变量的值
查询结果:
-------------------------------------
NULL             NULL

declare @test int,           --声明变量和数据类型
        @test2 nvarchar(25)
select @test,@test2        --查询变量的值
set @test=1                   --给变量赋值
set @test2='a value'
select @test,@test2        --查询变量的值
查询结果:
--------------------------------------------------------------------
NULL                       NULL

-------------------------------------------------------------------
1                             a value    

declare @test int,           --声明变量和数据类型
        @test2 nvarchar(25)
select @test,@test2        --查询变量的值
set @test=1                   --给变量赋值
set @test2='a value'
select @test,@test2        --查询变量的值
go                                 --批处理结束符
select @test,@tese2
查询结果:
----------------------------------------------------
服务器: 消息 137,级别 15,状态 2,行 8
必须声明变量 '@tese2'。

从例子可以看到:go  将该批处理分成了两个批处理,所以最后一句提示:必须声明变量 '@test'。
二、使用set和select命令
2-1  set命令和select命令都可以使用表达式为变量赋值。它们之间的主要区别在于:
select可以从表、子查询或者视图中查询数据,并且也可以包含其他的select子句;
而set命令则只能从表达式中获取数据。
set和select命令中都可以使用函数。

select语句可以查询多列,而每个列中的数据都可以赋值给一个变量。如果select语句返回了多个行,
将会把结果集中最后一行的数据赋值给变量,系统不会报告任何错误。
下面例子可以说明:
declare @ID nvarchar(25),          --声明变量和数据类型
        @Name varchar(25)
set @ID=1433                           --给变量赋值          
select @ID=userid,
       @Name=username
       from j_user  order by userid     -- 将查询的值赋给变量
select @ID,@Name
查询结果:
-------------------------------------------
T002               特卖员2

将返回的73行中的最后一行的数据赋给了变量。

如果select语句没有返回任何行,那么它就不会改变变量的值。
请看下面的例子:
declare @ID nvarchar(25),          --声明变量和数据类型
        @Name varchar(25)
set @ID=1433                           --给变量赋值          
select @ID=userid,                      --给变量赋值          
       @Name=username
       from j_user
       where userid='100'      --查找编号为100的用户
  order by userid     -- 将查询的值赋给变量
select @ID,@Name
查询结果:
-----------------------------------------
1433                   NULL

使用下面的语法也可以为变量赋值:
declare @value nvarchar(25)
select @value =username  from j_user where userid='1433'
select @value
查询结果:
--------------------------------------------
梁江平

2-2  在SQL查询中使用变量
在SQL查询中任意可以使用表达式的地方都可以使用变量。
declare @value nvarchar(25)        --声明变量
set @value='1433'                     --给变量赋值
select username from j_user
where userid=@value                  --查询条件
查询结果:
---------------------------------------
梁江平

三、流程控制
3-1   if

与很多其他语言一样,T-SQL也提供了 if 这个古老的编程语句。但T-SQL if 命令的特别之处在于:
得用它只对其后的一条语句的执行与否进行控制——一个 if 只能控制一条命令。同时它没有 then ,
以及用来结束 if 块的 end if 命令。

if 1=0  print '世界乱套!'    --if 结果不为真,不执行后面的一句,跳到下一句。
print '这是不可能滴!'
执行结果:
-------------------------------
这是不可能滴!

3-2    begin/end 

 一个 if 命令吸能控制一条语句的执行与否,这显然缺乏实用性。
要解决这个问题,可以使用 begin/end 块,它可以将多条命令作为一个
整体构成 if 命令的下一条命令。
if 1=1
  begin
     print '第一句!'
     print '第二句!'
     print '做为整体来执行!'
  end
执行结果:
-----------------------------------
第一句!
第二句!
做为整体来执行!

尽快 if 命令看起来功能有限,但实际上并非如此,你可以在它的条件子句中作用一些功能非常
强大的SQL特性,如: if exists() 和  if…in() ,其功能与 where 子句中的相应特性类似。

if exists() 结构根据SQL select命令返回的结果集是否包含有行来进行判断。它只需要查看结果集有没有行,
所在在为它编写 select 语句时应当查询全部的列(select *  ),这种方法的速度更快,if exists() 中只要查询结果
返回了一条记录,就可以停止执行查询了,转而执行批处理中其它的语句了。
if exists(select * from d_retail where sure<>1 )
begin
   print '您还有单据没有完成!'
end
执行结果:
------------------------------
您还有单据没有完成!

     if/else
else 命令是可选的,只有当  if  条件的计算结果为假时,才会执行放在 else 命令后面的代码。
else 只能对其后的一条语句或者 begin/end 块的执行与否进行控制。
if  (条件)
    语句
else
    语句或者语句块

3-3   while
    在条件为真的情况下,while 命令可以循环地执行代码。与 if 命令类似,while 命令只能循环
执行其后的一条SQL语句。如果想循环执行一组命令,则需要使用 begin/end 。
declare @temp int
  set @temp=0
  while @temp<3
    begin
        print '循环次数:'+str(@temp)
        set @temp=@temp+1
    end
执行结果:
--------------------------------------------
循环次数:         0
循环次数:         1
循环次数:         2

可以使用 continue 和 break 命令来增强 while 命令的功能,使其能够构造更为复杂的循环体。
   使用 continue 命令可以从循环体中跳回到 while 命令,并按照正常的方式测试循环条件。(继续循环)
   使用 break 命令将会立即终止循环地,并继续执行循环体以后的代码,就像 while 条件为假时一样。

以下代码代码演示输出20以内的奇数,但如果变量值为9就直接退出:
declare @temp int                    --声明变量
   set @temp=0                       --给变量赋值0
   while @temp<20                  --循环条件:变量要小于20
       begin
             if (@temp % 2=0)        --判断是否为偶数
                begin
                    set @temp=@temp+1    --变量增长1
                     continue                       --退出当前循环,继续下次循环
                 end
             if(@temp=9)                  --判断变量值是否等于9
                 break                         --终止循环体
      print str(@temp)                    --输出变量值
       set @temp=@temp+1            --变量增长1

四、临时表和表变量
 4-1  局部临时表
          创建临时表的方法与创建用户定义表的方式基本相同,只是在创建临时表时必须使用由#打头的表名。
           实际上临时表是创建并保存在 tempdp 数据库中的。
               create table #TableName
               (
                      ID  int primary key,
                      Name  navrchar(25)
                )
       临时表的生命周期很短暂,当创建它的批处理或者过程结束时,临时表就被删除了。临时表的作用域是有限的。
只有创建局部临时表的连接人才能够看到它。

 4-2   全局临时表
         全局临时表与局部临时表类似,但其作用域却更为广泛,所有的用户都可以引用全局临时表。并且与局部临时表相
比,其生命周期更长,只有当最后一个引用它的会话结束之后才会将它删除。
          创建临时表需要使用邮两个##号打头的表名(##TableName),创建时首先要检查指定的全局临时表是否存在
    if  not  exists(select * from tempdp.dbo.sysobjects  where name='##TableName')
       create table  ##TableName
             (
                      ID    int,
                      Name   navrchar(25)
               )
每次SQL server 重新启动时它都会清除并重建 tempdb 数据库。

4-3  表变量
        表变量类似于临时表,其优点在于它只存在于内存之中。表变量与变量具有同样的作用域和生命周期,只有创建它们的
 批处理、过程或者函数才能够看到它们。当这些批处理、过程或者函数结束的时候,相应的表变量也就不再存在了。
        对于表变量存在以下限制:
        1. 不能使用  select * into  或者 insert  into @tablename exec  的方法来创建表变量;
        2. 不能在函数中创建表变量;
        3. 在完整情约束方面表变量不能使用外部键或者 check 约束,只能使用主键、默认值、空值和 unique 约束;
        4. 表变量不能拥有依赖它的对象,例如触发器或者外部键;

         表变量是作为变量来声明的,不需要使用 SQL DDL 语句来创建它们。在SQL查询中引用表变量时,可以像使用
  普通表一样使用它,只不是这个表的名字是一个变量名而已。
          下面的脚本必须作为一个批处理来执行,否则就会出错:

declare @workTable table
  (
   pk int primary key,
   coll int not null
  )
    insert into @workTable(pk,coll)
     values(1,101)
    select pk,coll from @workTable
   执行结果:
pk                    coll
-----------------------------------------
1                      101