概述
最后不要忘记:SQL是一种结构化(Structured)的语言(Language),所以它具有
编程语言的特性
声明变量和赋值
所谓变量,可以是看成一个存储数据的容器,所有它里面存储的值是可以变化的。使用变量必须首先声明(创建),然后再赋值(将数据装入这个容器中) 。
DECLARE
也可以一次性声明多个变量:
DECLARE
还可以在声明变量的同时给他赋值:
DECLARE
注意,SQL中的变量必须以@开头,以一个@开头的变量被称为局部变量。所谓“局部”,是指他的作用域(也就是能够产生作用、有用的区域)是局部的,而不是全局的。具体来说,局部变量的作用域位于一个批处理语句中。
SQL Server中还有一种变量,是使用@@开头的,被称之为全局变量。全局变量可以不受批处理的约束,可以在任何地方直接使用。但用户不能定义全局变量,全局变量只能由SQL SERVER定义。
但我就是要定义一个全局变量呢?比如:
DECLARE
SQL Server会将其作为一个名为@name(不是name)的局部变量使用。
演示:局部变量和全局变量的区别
常用的全局变量有:
PRINT
变量和列值一样,也可以进行运算。根据运算结果,就可以控制:
分支和循环
分支使用的只有两个关键字:
- IF:“如果”的意思,后面跟条件表达式。如果条件表达式结果为真,继续执行后面的子句……
- ELSE:必须和IF配合使用,“否则”的意思,后面不能再跟条件表达式。当其配合使用的IF表达式结果为假时,执行ELSE后面的子句
我们通过一个例子来学习:
DECLARE
@age的值是20的时候,输出的是Adult;把@age的值改成13,输出的就是Teenager。
如果IF...ELSE...后面跟的不止是一句SQL语句,就需要使用BEGIN...END,用以界定IF或ELSE的作用范围。比如:
DECLARE
ELSE后面还可以再跟IF,比如:
DECLARE
IF和ELSE还可以嵌套,比如:
DECLARE
SQL只有一个循环关键字:WHILE
WHILE后面接条件,只要条件为真,就会一直循环执行WHILE引导(通常由BEGIN...END界定)的循环体语句。循环无法终止,就是“死循环”,这是一定要注意避免出现的。所以在WHILE的循环体中,通常都会设置语句,使得一定条件下WHILE条件为假,以结束循环。比如:
DECLARE
运行上述SQL语句,会输入1,2,3,4,5。
使用这些分支循环,就可以构建大量的、复杂的SQL语句,这些SQL语句需要被有效的管理,
函数
应运而生。(复习:人人都是程序猿)我们其实已经学习并使用过很多系统函数(复习:),这里我们来学习如何创建自定义的函数。
SQL Server中函数的最大特点: 必须有一个返回值 。根据返回值类型,我们可以将其分为:
标量函数:返回一个简单类型的单一值。
其函数声明的SQL代码如下:
CREATE
注意:
- 函数不属于任何一张表,而属于整个数据库,所以函数名在整个数据库中不能重复
- 函数的命名规则见:,
- 函数的参数和变量声明一样,必须用@开头,且指明类型
- 标明函数返回类型时使用的关键字是RETURNS,带了一个S;函数体内标明返回值时,使用的是RETURN,没有S
- AS可以省略,BEGIN和END是不能省略的
- 函数体中:
- 不能对数据库中的数据进行修改,比如使用INSERT/UPDATE/DELETE等
- RETURN语句只能在函数体的最后
声明函数之后,运行,就可以在SQL Server Object Explorer中看到这个函数了:
可以看到,YzAdd被添加到:数据库17bang -> Programmability -> Functions -> Scalare-valued Functions下面,而且被自动的添加了 dbo 的schema。
然后,我们就可以调用它了:
PRINT
注意:Scalar函数必须指定schema_name(这里是dbo),不加schema_name会被认为是系统内置(build-in)函数。
函数还可以被 修改,这需要使用 ALTER 关键字。我们可以使用ALTER,把上述YzAdd函数的一个参数设定一个默认值:
ALTER
运行上述SQL语句,函数就会被修改,在SQL Server Object Explorer中查看:
@b已经变成了Default(区别于@a的No default)。
设置了默认值的参数,可以用两种方式调用:
PRINT
此外,函数还可以被加密,以免被其他用户看到函数的具体实现。未加密的函数,在函数上右键点击 View Code,就能查看到函数的“源代码”
但是,如果创建(或修改)函数时添加了WITH ENCRYPTION:
ALTER
再去View Code,就会发现:无法查看到函数体(函数的定义,如名称、参数、返回值等还是可以看到的)
CREATE
SQL函数的另一个特殊性,就表现在它的返回值可以是“表”,这种函数被称之为:表值函数。注意这里所称的表,实际上是一种具有表结构的数据,它和使用CREATE Table生成的表不一样:数据库中并没有这样一张表,这张“表”是通过函数运算而“临时”获得的。
表值函数又可以被细分为:
单行表值函数(Inline Function)
其SQL语句如下:
CREATE
除了RETURNS后直接接TABLEG关键字,这种函数的特点是:函数体只能有一句SELECT语句,且不能由BEGIN...END包裹。其他(如DEFAULT参数和WITH ENCRYTION)都和标量函数一样。
调用YzInlineTable函数,会返回一个“表”,所以,我们也要像表一样使用它:
--不是:PRINT YzInlineTable(2),而是:
注意:调用表值函数时可以不需要使用schema,¯_(ツ)_/¯
如果函数中需要封装更复杂的逻辑,我们就只有使用多行表值函数(Multi-Statement Function)了。它同样是返回一个表,但它和标量型函数一样有一个用BEGIN-END 语句括起来的函数体,返回值的数据是由函数体中的语句插入的。
SQL代码及语法代码如下所示:
CREATE
很函数相比,SQL中更常用的是
存储过程(Procedure)
和函数非常类似,它也是一组为了完成特定功能的 SQL 语句集合,经编译后存储在数据库中,用户通过指定存储过程的名称并给出参数来执行它。我们首先来
创建
一个最简单的存储过程GetExcellentStudents:
CREATE
和函数一样,存储过程也可以给参数一个默认值。创建完成之后,我们就可以在SQL Server Object Explorer里看到我们的存储过程:
调用:
DECLARE
存储过程没有RETURN的使用,但它可以用OUTPUT设置输出参数,一样的实现函数的效果。另外,存储过程没有函数 只读不写 的限制。
所以说,基本上,函数能干的事情存储过程都能干。这就是存储过程的使用比函数更为普遍的原因。一个常见的面试问题:何时使用存储过程何时使用函数 ?除了上述的语法的比较,我们建议再加上很重要的一条:按需要选择。如果你的需求是:
- 得到 一些数据以便于数据库内部 使用,最好使用函数;否则
- 请使用存储过程
参考:Function vs. Stored Procedure in SQL Server
调用
存储过程,需要使用EXECUTE(或简写EXEC)。
- 如果不指定参数名,应按存储过程定义时参数次序依次赋值;否则可不限定顺序。
- 使用默认值需用DEFAULT显式指定
- 输出参数要先声明,再使用,而且还要加上OUTPUT标识
DECLARE
其他和函数一样,
修改
存储过程需要使用ALTER:
ALTER
删除
需要使用DROP:
DROP
SQL Server也为我们提供了大量的
系统存储过程
其特点为都以sp_开头。所以,建议用户自定义的存储过程不要以"sp_"开头,而是使用其他字符标识(比如usp_)。
我们介绍两个常用的系统存储过程:
sp_rename :可更改数据库对象(比如表/列/索引等)名称。使用方法:
-- 将Student表中的Score(列),更名为FinalScore
sp_helptext :获取数据对象的帮助信息,使用方法:
EXEC
是否使用存储过程,曾经是一个争论异常激烈的话题。存储过程有以下优点:
- 因为事先编译,所以可以更快的执行
- 因为只需要向数据库传递存储过程名称和参数,所有需要的流量更少
但它的缺点也同样明显:
- 可读性差(对于Java/C#/PHP等开发人员而言)
- 难以调试(飞哥教过你们调试SQL么?^_^)维护
- 不能在不同数据库之间迁移(各个数据库的存储过程语法不一定相同)
随着计算机性能的大幅提升,以及业务逻辑的不断复杂化,目前主流的实践已经是“尽可能少的,或者干脆不使用存储过程”。这同样适用于之前讲的 函数 和接下来要讲的:
触发器
触发器是一种特殊的存储过程:顾名思义,触发器可以在进行某些数据库操作时自动触发,并执行触发器中定义的内容。
这是我们最后一部分内容的学习。“授人以鱼不如授人以渔”,我们课堂讲授的内容始终是有限的,同学们在以后的工作中必然会遇到更多的问题。这就需要同学们能够
查询文档
所以,最后,让我们来一起学习阅读 触发器的MSDN文档。
如果这个内容对我们是全新的,我们可以从头往下阅读。
既然文档里提到了DML和DDL,我们就刚好做一个总结。SQL语言共分为四大类(复习):
- 数据操纵语言:D(Data)M(manipulate)L(Language),包括增(INSERT)删(DELETE)改(UPDATE)
- 数据查询语言:DQ(Query)L,查(SELECT)
- 数据定义语言:DD(define)L,涉及数据库对象的操作,包括{CREATE|ALTER|DROP} {DATABASE|TABLE|INDEX|VIEW|FUNCTION|PROCEDURE} 。传统上DDL不受事务控制。TRUNCATE属于DDL,所以不能回滚。
- 数据控制语言:DC(control)L。授权相关:GRANT/REVOKE (课程没讲)
- 事务控制语言:T(transaction)CL:TRANSACTION/COMMIT/ROLLBACK/SAVE
文档中最核心的就是Syntax部分,不要被里面密密麻麻的符号吓坏了,我们一个一个的来看:
- 大写英语单词:关键字
- 小写英语单词:需由开发人员填写的内容
- []:可以使用,也可以不使用
- {}:必须使用
- |:并列可选项
- <>:占位
- ::=:
- [ ,...n ]
演示:浏览文档,创建一个TRIGGER
作业:
- 编写存储过程模拟“一起帮用户注册”的过程,包含以下逻辑:
- 检查用户名是否重复。如果重复,返回错误代码:1
- 检查用户密码是否符合“长度不小于4位”的要求。如果不符合,返回错误代码:2
- 如果有邀请人:
- 检查邀请人是否存在,如果不存在,返回错误代码:10
- 检查邀请码是否正确,如果邀请码不正确,返回错误代码:11
- 将用户名、密码和邀请人存入数据库(Register)
- 给邀请人增加10个帮帮点积分
- 通知邀请人(在Message表中生成一条数据)某人使用了他作为邀请人。
- 确保Problem有“发布时间(PublishTime)”和“最后更新时间(LatestUpdateTime)”两列,创建触发器实现:
- 更新一条数据,自动将当前时间计入该行数据的LatestUpdateTime
- 插入一条数据,自动将当前时间计入该行数据的PublishTime(提示:INSERTED伪表)
每日单词
感谢童鞋们的阅读!^_^
我就是:黑律师/包工头/创业狗/老码农……现在还是教书匠的大飞哥。
再次重申这个系列的目标是:
1)通俗易懂。2)实战为主。3)面向就业。
系列内容的完善需要你的反馈!
欢迎点赞和评论,以及加入我们的QQ交流群:326801052。
最后
以上就是狂野煎蛋为你收集整理的declare sql语句_跟飞哥学编程:SQL入门-:函数、存储过程和触发器的全部内容,希望文章能够帮你解决declare sql语句_跟飞哥学编程:SQL入门-:函数、存储过程和触发器所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复