【SQL Server学习笔记】23:部分可编程对象

来源:互联网 发布:如何下载excel软件 编辑:程序博客网 时间:2024/06/05 17:07

变量

声明一个变量,则它可以在声明它的同一批处理语句中引用,因为SQL Server会将批处理中的语句编译成为单个可执行单元。

DECLARE @i AS INT;SET @i=10;

在SQL Server 2008以后,还可以直接这样写:

DECLARE @i AS INT=10;

可以用标量表达式的结果赋值给符合数据类型的变量,这是很自然的。

USE MyDB;DECLARE @s_name AS NVARCHAR(20);SET @s_name=(            SELECT firstname+N' '+lastname            FROM dbo.ok            WHERE myid=1182            );SELECT @s_name AS '得到的单值';

这里写图片描述
如果满足条件的查询结果有多行,自然就会出错:

USE MyDB;DECLARE @s_name AS NVARCHAR(20);SET @s_name=(            SELECT firstname+N' '+lastname            FROM dbo.ok            WHERE Pid=1012  --满足这个条件的可是有多行            );SELECT @s_name AS '得到的单值';

这里写图片描述
不过SQL Server支持一种非标准的赋值SELECT语句:

USE MyDB;DECLARE @s_name AS NVARCHAR(20);--下面是非标准的赋值SELECT语句SELECT @s_name=firstname+N' '+lastnameFROM dbo.okWHERE Pid=1012; --满足这个条件的可是有多行SELECT @s_name AS '得到的单值';

这里写图片描述
这个时候虽然有多行,但是每次查到一行满足条件的,都会去刷新那个变量值,所以不会出错,但也不能保证最后赋值进去的那个是自己想要的那个值,这依赖于SQL Server访问数据行的顺序。
从这个角度来看,SET实际上比这种非标准的赋值SELECT更安全。也就是宁可出错也不去用一个不能确保正确的值。

批处理

批处理语句将多条T-SQL语句作为一个可执行单元,要经历的阶段有:分析(语法检查)->解析(存在性、权限)->优化(作为执行单元)。

作为语法分析的单元

如果批处理单元中存在语法错误,整个批处理都不会提交到SQL Server执行,批处理之间可以用GO隔开。在使用时,不同的批处理不互相影响。
并且,变量只能在声明它的批处理中被使用:

PRINT @i;GODECLARE @i AS INT=10;PRINT @i+1;GOPRINT @i+2;

这里写图片描述

不能在同一批处理中编译的语句

有些语句必须单独放到一个批处理中,之前学表表达式时,创建视图的时候就出现了这样的问题。这样的语句有:

CREATE DEFAULTCREATE FUNCTIONCREATE PROCEDURECREATE RULECREATE SCHEMACREATE TRIGGERCREATE VIEW

必须用GO和旁边的其它语句隔开。

作为语句解析的单元

批处理作为语句解析的单元,如果对数据对象的架构进行修改,并在同一批处理中使用这些修改时,SQL Server可能还不知道架构定义发生了变化(因为在解析这条语句时,前面那条修改架构的还没有被执行)。

USE MyDB;ALTER TABLE dbo.ji1 ADD newcol INT;SELECT myint,mychar,mychar2,newcol FROM dbo.ji1;--在解析这句时,前面那句还没执行

这里写图片描述
解决方法还是放到两个批处理中去,按顺序解析执行。

USE MyDB;ALTER TABLE dbo.ji1 ADD newcol INT;GOSELECT myint,mychar,mychar2,newcol FROM dbo.ji1;--与前面那句已经是两个批处理块

这里写图片描述

GO n选项

从SQL Server 2005开始对GO就进行了增强,可以带一个数字表示GO之前的批处理将执行指定的次数。

DECLARE @i AS INT=6;PRINT @i;GO 3

这里写图片描述
GO是一个客户端命令,而不是服务器端的T-SQL命令,所以无论连接到的数据库引擎版本是什么,只要客户端工具是SQL Server 2005以上的就可以使用GO n了。

流程控制元素

判断条件实际上是不用加括号的,我习惯加上括号,看起来更清楚(改变优先级的时候肯定要加吧),也是向其它语言看齐。

IF-ELSE

只要注意下三值逻辑,当为FALSE或者UNKNOWN时都会进入ELSE块里。

DECLARE @i AS INT=5;IF(@i>5)SET @i=7;ELSE    IF(@i<3)        SET @i=1;    ELSE        SET @i=4;PRINT @i;

这里写图片描述
如果要一个块里多条语句,就像C++里面加括号那样,这里用BEGIN-END:

DECLARE @i AS INT=5;IF(@i>5)    BEGIN        SET @i=@i+1;        PRINT @i+1;    ENDELSE    BEGIN        SET @i=@i-1;        PRINT @i-1;    END

这里写图片描述

WHILE

WHILE也是只接受TRUE的,FALSE和UNKNOWN都会让循环终止。

DECLARE @i AS INT=1;WHILE(@i<=10)    BEGIN        PRINT @i;        SET @i=@i+1;    END

这里写图片描述

BREAK和CONTINUE在SQL里也是有的。

DECLARE @i AS INT=1;WHILE(@i<=10)    BEGIN        IF(@i=6)            BREAK;--跳出        PRINT @i;        SET @i=@i+1;    END

这里写图片描述

DECLARE @i AS INT=1;WHILE(@i<=10)    BEGIN        IF(@i=6)            BEGIN                SET @i=@i+1;                CONTINUE;--跳过            END        PRINT @i;        SET @i=@i+1;    END

这里写图片描述

用户自定义函数

例程是为了计算结果或执行任务而对代码进行封装的一种编程对象。本节只学用户自定义函数,除此之外还有存储过程和触发器,后面再学。

USE MyDB;IF OBJECT_ID('dbo.fn_cat') IS NOT NULL    DROP FUNCTION dbo.fn_cat;GOCREATE FUNCTION dbo.fn_cat(    @s1 AS NVARCHAR(10),    @s2 AS NVARCHAR(20))RETURNS NVARCHAR(21)AS    BEGIN        RETURN @s1+N'-'+@s2;    END;

然后就可以使用了:

SELECT    dbo.fn_cat(firstname,lastname) AS CATFROM dbo.ok;

这里写图片描述