1:注释语句
2:批处理语句
3:if....else语句
A:注释语句
注释语句不是可执行语句,不参与程序的编译与运行.注释语句通常是一些说明性的文字.对代码的功能或者代码的的实现方式给出简明的解释和提示.很显然注释语句可以增加程序可读性,可修改性.
sql server支持两种形式的注释语句,一种是行注释,一种是块注释.
1:行注释:只对该行进行注释,形如:“--”的格式
2:块注释:对整块进行注释,形如:“/*...*/”的格式
B:批处理
1:所谓批处理是从客户机传递到服务器上的一组完整的数据和sql指令
2:批处理的所有语句被作为一个整体而被成组分析,编译,执行,如果在一个批处理中存在着一个语法错误,那么所有的语句都无法编译,这样有助于数据的完整性,还可以加快执行的速度.
3:所有批处理命令都使用go作为结束标志,当编译器读到go时它就会把go前面的所有语句(截止下一个go结束为止)当作一个批处理,而打包,发送给服务器.如果不加go,则sql server会认为所有语句都被视为一个批处理,而成组执行
4:大多数运行期间发生的错误,如算术溢出或违反约束,仅停止执行当前语句,而继续执行批处理中其它有所有语句
5:大多数create语句不能在同一个批处理中混合使用.换句话说,在同一个批处理里,不能够出现即运行create table语句,又运行其它的create命令.比如:create view,create default,create rule,create procdurce,create function命令
6:不能在同一个批处理中更改表的结构,然后引用新列.
sp_rename \'work.职工号\',\'职工编号\',\'column\'
select 职工编号 from work [会出现错误]
可以改为:sp_rename \'work.职工号\',\'职工编号\',\'column\'
go
select 职工编号 from work [会出现错误] [分成两个批处理语句]
7:如果execute语句是批处理语句的第一句,则不需要execute关键字,否则必须要加上execute关键字
8:use语句不能够与批处理语句放在一起
怎么使用批处理
1:好处:如果把一些sql语句放在批处理中,就可以保证这些语句要么都做,要么都不做,从而保证数据的完整性.
比如:delete from 部门 where 部门编号=\'A\'
delete from 职工 where 所在部门=\'A\'
即在部门表中删除一条记录,则在work表应该把该部门所有的职工都删除.此时,如果删除部门操作失败,则删除work的操作也会失败,从而保证的数据的完整性
变量 sql sever支持两种形式的变量,一种是局部变量,一种是全局变量.
局部变量与全局变量[系统变量]的区别
局部变量一般是用户为了编写程序的需要而定义的变量,则全局变量是用来存储服务器的一些参数,对用户来说,只能够引用全局变量的值,而不能修改全局变量的值.局部变量都必须以@开头,而全局变量必须以@@开头
定义局部变量
格式:declare @变量名 数据类型
比如:declare @age int
1:可以在一个declare中定义多个变量 如:declare @age int,@pay float,@name varchar(10)
2:可以使用中文变量 如:declare @年龄 int
3:局部变量只能够在定义它的批处理里面使用
比如:declare @agemax int
select @agemax=max(年龄) from work
go
select @agemax [错]
变量赋初值
sql server为我们提供两种为变量赋初值的方法
1:通过select语句
A:格式:select @变量名=值
B:可以从一个表中查询一个结果赋给某一个变量,比如把work表性别是男的职工的人数赋给变量n
select @n=count(*) from work where 性别=\'男\'
说明:1:当把查询结果赋给一个变量时,如果这个结果不止一个,只会把最后一个查询结果的值赋给变量.
2:可以为多个变量赋值:
比如:select @age=40,@name=\'chenyuqing\'.
再如:select @agemax=max(年龄),@agemin=min(年龄) from work
[从work表找出年龄的最大值和最小值分别赋给@agemax和@agemin变量]
3:注意赋值功能和查询功能不能混用.
比如:select @agetmax=max(年龄),min(年龄) from work [错误]
2:通过set语句
格式:set @变量名=值
比如:set @name=\'陈清\'
说明:1:不能通过set语句给多个变量赋值.例如:不能像这样写 set @a=4,@b=6
2:也可把查询的结果赋给某个变量.
例如:set @count=(select count(*) from work where 性别=\'女\') [注意括号不能少]
3:但一次只能够赋一个值给这个变量
举例:一个简单的应用
declare @name varchar(10)
set @name=\'王杰\'
select * from work where 姓名=@name
全局变量
全局变量是用来记录sql server服务器活动的一组数据
比如:@@error:用来判断执行的命令是否成功 [当@@error=0时表示执行成功,不为零表示执行失败]
@@rowcount:返回一条sql语句执行时影响到的数据行的数目.
@@total_read:返回自sql server服务器启动以来读磁盘的次数
@@total_write:返回自sql server服务器启动以来写磁盘的次数
@@version:返回当前sql server软件的相关信息.
C:if ...........else判断语句
格式:if 条件 语句体1
else 语句体2 [当条件成立时,做语句体1,否则做语句体2]
举例:1:查找职工号是07的职工,若他是经理,把他的基本工资加上100,否则把职称改成经理
declare @jc varchar(10)
set @jc=(select 职称 from work where 职工号=\'07\')
if @jc=\'经理\'
update work set 基本工资=基本工资+100
else
update work set 职称=\'经理\' where 职工号=\'07\'
2:查找职工号为001的职工,根据他的职称来确定他的工资
假定工资标准:经理:1500 厂长:1200 主管:800 文员:600
delclare @cj varchar(10)
select @cj=职称 from work where 职工号=\'001\'
if @cj=\'经理\'
update work set 基本工资=1500
else
if @cj=\'厂长\'
update work set 基本工资=1200
else
if @cj=\'主管\'
update work set 基本工资=800
else
update work set 基本工资=600
3:查找某一个职工的工资,如果这个职工的工资低于他所在职称的平均工资则把这个人的工资加100,如果等于平均工资,则删除这个职工,如果小于这打印该职工的工资.
declare @zgh varchar(10),@gz float,@pjgz float,@cj
set @zgh=\'001\'
set @gz=(select 基本工资 from work where 职工号=@zgh)
set @cj=(select 职称 from work where 职工号=@zgh)
或者:select @gz=基本工资,@cj=职称 from work where 职工号=@zgh
set @pjgz=(select avg(基本工资) from work where 职称=@cj)
if @gz<@pjgz
update work set 基本工资=基本工资+100 where 职工号=@zgh
else
if @gz=@pjgz
delete work where 职工号=@zgh;
else
print @gz
4:begin....end语句
5:while循环结构
6:case情况语句
D:复合语句 [begin....end]
复合语句,当条件满足时,如果要做几条语句,则可以把这几条语句用begin.....end括号起来.
比如:在work表中查询职工号为01的职工如果该职工性别为男,职称是经理
1:打印该记录,2:把基本工资加100,3:打印加了工资之后的记录,否则:打印\'不合格,不能加工资\'
declare @sex varchar(10),@jc varchar(10)
select @sex=性别,@jc=职称 from work where 职工号=\'01\'
if @sex=\'男\' and @jc=\'经理\'
begin
print \'条件合格可以加工资\'
select * from work where 职工号=\'01\'
update work set 基本工资=基本工资+100
select * from work where 职工号=\'01\'
end
else
print \'不合格,不能加工资\'
常用的另一个if逻辑判断是:
if [not] exists (select 语句)
语句1
else
语句2
这个结构执行的逻辑判断是检测是否存在满足条件的数据存在.如果存在则做语句体1,否则做语句体2
比如:在work表中查找有没有职工号是“001”,如果有
1:打印\'查到此人\',2:判断其职称是否是厂长,
如果是 A:打印此人是厂长可以删除,B:删除对应的记录
否则打印\'不是厂长不能删除\'
否则打印\'找不到此人\'
declare @jc varchar(10)
if exists(select * from work where 职工号=\'001\')
begin
print \'查到此人\'
select @jc=职称 from work where 职工号=\'001\'
if @jc=\'厂长\'
begin
print \'此人是厂长,可以删除\'
delete work where 职工号=\'001\'
end
else
print \'此人不是厂长,不能删除\'
end
else
print \'找不到此人\'
E:while循环结构.
功能:在满足条件的情况下,复制执行同样的语句
格式:while 条件
begin
语句
end
举例:1:求1....5的阶层
declare @n int,@re bigint
select @n=1,@re=1
while @n<=5
begin
select @re=@re*@n
select @n=@n+1
end
print @re
2:在work表中把员工的工资每次加上100,并查看最大工资,直到最大工资达到5000为止.
while(select max(基本工资) from work)<5000
begin
select max(基本工资) from work
update work set 基本工资=基本工资+100
end
3:有一商品表,里面有多个商品:彩电,空调,DVD,CD,VCD,和库存量和最小库存量,假定该商店日平均销售量为
彩电:25台,空调:30台,DVD:10台,CD:5台,VCD:12
现在要知道那一种商品经过多少天最先小于最小库存量
select * from 商品 [没有改变之前的商品表的情况]
declare @n int
set @n=0
while(not exists(select * from 商品 where 库存量>=最小库存量))
begin
update 商品 set 库存量=库存量-10 where 商品名=\'彩电\'
update 商品 set 库存量=库存量-30 where 商品名=\'空调\'
update 商品 set 库存量=库存量-10 where 商品名=\'DVD\'
update 商品 set 库存量=库存量-5 where 商品名=\'CD\'
update 商品 set 库存量=库存量-12 where 商品名=\'VCD\'
set @n=@n+1
end
select 商品名,@n 天数 from 商品 where 最小库存量>=库存量
select * from 商品 [改变之后的商品表的情况]
F:case 语句 情况语句
格式:case
when 条件 then 值
.
.
else 值
end
举例:1:有一个score.要求根据以下条件来设置总分等级的值
A:总分<=180 等级为差
B:总分>180 and 总分<=240 等级为良好
C:总分>240 and 总分<=270 等级为优良
D:总分>270 等级为优秀
update score set 等级=
case
when 总分<=180 then \'差\'
when 总分>180 and 总分<=240 then \'良好\'
when 总分>240 and 总分<=270 then \'优良\'
else \'优秀\'
end
2:有编程work表:要求根据职称来确定工资. 经理:3000,秘书:1500,文员:1200,主管:1400,其它:800
update 编程work set 基本工资=
case
when 职称=\'经理\' then 3000
when 职称=\'秘书\' then 1500
when 职称=\'文员\' then 1200
when 职称=\'主管\' then 1400
else 800
end [要写很多的“职称”]
改为:update 编程work set 基本工资=
case 职称
when \'经理\' then 3000
when \'秘书\' then 1500
when \'文员\' then 1200
when \'主管\' then 1400
else 800
end [只写一个“职称\']
3:要求创建一个含有每个学生分数和总分数和最优科目的表. 要求有如下列:姓名,语文,数学,化学,总分,最优科目
create table 编程分数
(姓名 varchar(10),
语文 int,
数学 int,
化学 int,
总分 as 语文+数学+化学
最优科目 as
case
when 语文>数学 and 语文>化学 then \'语文\'
when 数学>语文 and 数学>化学 then \'数学\'
when 化学>语文 and 化学>数学 then \'化学\'
end)
G:游标[cursor]
什么是游标:
通常情况下,数据库执行的大多数sql命令都是同时处理集合内部的所有数据.但是,用户有需要对这些数据集合中每一行进行操作.游标就是提供这种机制的结果集扩展.综上所述,游标应该包含两方面的内容.一方面:游标就是结果集;另一方面:游标不仅是结果集,它还能对结果中的第一行进行操作.
为什么要定义游标:因为游标可以做如下的事件:
A:允许定位在结果集的特定行.
B:从结果集的当前位置检索一行或多行.
C:支持对结果集中当前位置的行进行数据修改.
D:为由其他用户对显示在结果集中的数据库数据所做的更改提供不同级别的可见性支持.
游标的分类:游标根据所在位置分类可以分为服务器端游标和客户游标
服务器端游标:生成的结果集在服务器上,所以客户端对结果集中进行更改时,其更改语句必须从客户端发送到服务器,然后在服务器中将它解析并编译.打个比方:比如你要为经理作一项工作,你可以在公司做(结果集存储服务器端),今天做一点交付给经理检查,明天做一点也交付给经理检查,那这样经理就会因为你而很烦.当然,你完全可以拿回家(结果集放在客户端),做好之后,一次性交给经理,这就是客户游标
客户游标:客户端游标通过在客户端高速缓存区来存储所有结果集来实现.每次客户对结果集进行处理时,只需要从客户端高速缓存区来取得数据,减少与服务器的连接,但是由于结果集是放在客户端的,所以不能更好处理并发问题,因为该游标无法感知另外一个用户对该结果的更改.
服务器游标与客户端游标的区别
A:客户端游标:是静态游标,静态游标不会显示游标打开以后在数据库中新插入的行,或修改的值.
服务器端游标:即使在游标打开之后,有另外一用户对数据库的数据进行修改时,也可以显示出来.
B:服务器端游标:可以更好处理并发的问题,所以如果你应用到多个用户,建议使用服务器端游标.
客户端游标:客户端游标不行.
C:在使用服务器游标时,客户端无需缓存大量数据或维护游标位置的信息,这些工作由服务器完成.
怎么使用游标:
A:定义游标
B:打开游标
C:使用游标取数
D:关闭游标
定义游标:declare 游标名 cursor scroll for select 语句 [只能是select语句,为什么?]
比如:declare ww_work cursor scroll for select * from work
这样我们就定义了一个游标,它用来存储work表所有的记录,并且它可以一行一行来访问它的结果集.
说明:1:scroll关键字定义的游标具有任意的移动功能,如果省略,则些声明的游标只有往下移动的功能.
2:定义游标里面的select语句,用来说明游标要进行处理的结果集
再如:declare ww_degree cursor for select * from work where 学历=\'大专\'
声明了一个名为ww_degree的游标,它只处理work表中学历是大专的记录,并且只能够往下移动,不能滚动.
打开游标:要用游标来取数,必须要首先打开游标,否则不能使用游标来取数
格式:open 游标名
比如:open ww_degree [打开声明的游标]
说明:1:打开游标时,游标会自动地定位在记录集中的第一条记录上.
2:打开游标后,可通过变量@@cursor_rows来看当前声明的游标可以操作的数据
3:游标只需打开一次,并且游标打开之后,服务器为会其分配一个高速缓冲区,来存储结果集,所以在使用完之后,别忘记了关闭游标.
比如:declare ww cursor
for select * from work where 性别=\'男\'
open ww
print @@cursor_rows
使用游标取数:
格式:fetch [next|prior|first|last|absolute n|relative n] from 游标名
说明:first:第一行
last:最后一行
prior:当前位置前一行
next:当前位置下一行
relative n:按相当位置取n个数据
absolute n:按绝对位置取n个数据
比如:fetch relative 2 from ww [提取当前行的后2行]
fetch relative -1 from ww [提取当前行的前一行]
如果在定义游标时,没有用scroll关键字,那么该游标只能够向下走[next]
比如:declare ww cursor for select * from work where 性别=\'男\'
open ww
fetch ww [取出第一条]
while @@fetch_status=0
fetch next from ww
说明:1:@@fetch_status用来说明游标是否到了记录的末尾,如果没有到则返回零.
2:试着执行fetch frist from ww 行吗?[不行,因为该游标不是滚动游标]
把游标取到的数据存在变量里
格式:fetch 行操作语句 from 游标名 into @变量名
比如:declare @jc varchar(10),@gz int
declare abc cursor scroll for select 职称,基本工资 from work
open abc
fetch last from ww into @jc,@gz
把结果集中最后一行的职称和基本工资分别放入变量@jc和@gz中.
说明:在使用into子句对变量赋值时,变量和相应的数据类型,数目必须和声明游标时使用的select语句引用的数据列数目,类型完全一致.
举例:1:通过代码检索出和职工E1,E3都有联系的联系的北京的供应商的信息
declare ww_ab cursor for select * from 供应商 where 地址=\'北京\'
open ww_ab
declare @供应商号 varchar(10),@供应商名 varchar(10),@地址 varchar(10)
fetch from ww_ab into @供应商号,@供应商名,@地址
while @@fetch_status=0
begin
if (select count(distinct 职工号) from 订购单 where 供应商号=@供应商号 and 职工号 in(\'E3\',\'E7\'))>1
select @供应商号 供应商号,@供应商名 供应商名,@地址 地址
fetch next from ww_ab into @供应商号,@供应商名,@地址
end
2:利用游标求出每个工人的销售总量.
有职工表,游标职工住址和游标职工销售两个表
declare ad cursor for select 职工号,姓名 from 游标职工住址
open ad
declare @职工号 varchar(10),@姓名 varchar(10),@销售量 int
fetch from ad into @职工号,@姓名
while @@fetch_status=0
begin
select @销售量=sum(销售量) from 游标职工销售 where 职工号=@职工号
print @职工号+\' \'+@姓名+\' \'+str(@销售量)
fetch next from ad into @职工号,@姓名
end
关闭游标
由于游标会对某些数进行锁定,这样就会导致其它用户不能正常使用被锁定的数据,所以不用游标时应该关闭游标 [如何锁定以下再讲]
格式:close 游标名
说明:1:关闭游标并没有删除游标
2:关闭游标之后,可以通过open语句再次打开游标.也可以多次打开和关闭游标
删除游标
由于游标结构本身会占有一定的计算机资源,所以在使用完游标之后为了回收资源,应该释放游标.
格式:deallocate 游标名
sql server编程结构(四)--游标(下)
可更新游标和只读游标:
只读游标:如果定义游标时,加read_only就是一个只读游标,则用户不能通过游标对数据集进行update和delete操作.
可更新游标:如果在定义游标时,不加read_only就是一个可更新的游标,此时用户可以对通过游标来删除或更新数据集.
比如:declare ww_abcpu cursor read_only for select * from work where 性别=\'男\' [定义了一个只读游标]
通过:update work set 基本工资=基本工资+100 where current of ww_abcpu [检验一下]
再如:declare ww_abcpu cursor for select * from work where 性别=\'男\' [定义了一个可更新游标]
通过:update work set 基本工资=基本工资+100 where current of ww_abcpu [检验一下]
利用游标来修改数据
我们可以利用游标来修改游标所存储的结果集.包括对结果集的更新和删除
1:利用游标更新数据
A:要使用游标进行更新数据,必须声明一个可更新的游标
B:定义了可更新的游标之后,就可以通过游标更新语句来对指定表中的某个列进行更新
格式:update 表名 set 列名1=值,列名2=值,...列名n=值 where current of 游标名
例如:update work set 基本工资=基本工资+100 where current of ww_king
[把游标ww_king当前的记录行的基本工资加上100]
举例:1:用游标来把work表的所有性别是男的职工的工资都加100
declare pay cursor for select 基本工资 from work where 性别=\'男\'
open pay
while @@fetch_status=0
begin
update work set 基本工资=基本工资+100 where current of pay
fetch next from pay
end [相当于update work set 基本工资=基本工资+100 where 性别=\'男\']
2:有游标更新销售表和游标更新职工表:要求通过游标来把游标更新销售表中销售量超过200的职工基本工资提高0.5
declare @职工号 varchar(10),@基本工资 int,@销售量 int
declare ww_kingmax cursor for select 职工号,基本工资 from 游标更新职工
open ww_kingmax
fetch from ww_kingmax into @职工号,@基本工资
while @@fetch_status=0
begin
select @销售量=sum(销售量) from 游标更新销售 where 职工号=@职工号
if @销售量>100
update 游标更新职工 set 基本工资=基本工资*1.5 where current of ww_kingmax
fetch next from ww_kingmax into @职工号,@基本工资
end
说明:[fetch next from ww_kingmax into @职工号,@基本工资]完全可以不需要@基本工资,因为我们只需要职工号作为条件,但是由于上面定义了一个游标含有职工号和基本工资,根据前面的知识我们知道,必须要为两个变量赋值,所以要加上了@基本工资. [如果不用游标怎么实现]
3:有游标更新职工信息和游标更新职称工资两个表,要求在游标更新职工信息输入一个职称之后,用游标来确定该职称的工资和补贴
declare @职称 varchar(10),@基本工资 int,@补贴 int
declare ww_king cursor for select 职称,基本工资,补贴 from 游标更新职工信息
open ww_king
fetch from ww_king into @职称,@基本工资,@补贴
while @@fetch_status=0
begin
select @基本工资=基本工资,@补贴=补贴 from 游标更新职称工资 where 职称=@职称
update 游标更新职工信息 set 基本工资=@基本工资,补贴=@补贴 where current of ww_king
fetch next from ww_king into @职称,@基本工资,@补贴
end [想一想:不用游标怎么做???]
综上所述:我们可以用游标更新的方法来代替用单纯的sql语句的更新,但是某些情况下,我们只能用游标,而用单纯的sql就显得力不从心了.
2:利用游标删除数据
格式:delete 表名 where current of 游标名
举例:1:有一个work表,假设有100万行记录,现在要显示其中姓名重复的职工
A:select [distinct 姓名] from work a where (select count(*) from work b where a.姓名=b.姓名)>1
B:要删除其中姓名重复的职工
declare ab_king cursor for select 姓名 from work
open ab_king
declare @姓名 varchar(10)
fetch from ab_king into @姓名
while @@fetch_status=0
begin
if (select count(*) from work where 姓名=@姓名)>1
delete work where current of ab_king
fetch from ab_king into @姓名
end
几种特殊的游标
A:只读游标:这种游标只能从结果集中取数,并不能更新结果集.
定义的时候只需要加上[READ_ONLY]关键字就行了
比如:declare kk_king cursor read_only
for select * from work where 性别=\'男\'
B:可更新游标:这种游标可以对结果集进行更新,只要在定义时,不加[READ_ONLY]就行了
C:只进游标:这种游标只能执行next操作.定义的时候只要加上[FORWARD_ONLY]就行了
比如:declare kk_king cursor forward_only for select * from work
fetch prior from kk_king [试验一下可行吗?]
D:滚动游标:这种游标可以执行任意的命令比如:next,prior,last等.定义的时候只需要加上[SCROLL]关键字就行了
比如:declare kk_king cursor scroll for select * from work where 性别=\'女\'
E:静态游标:这种游标在定义时只需要加上[STATIC]就行了
比如:declare kk_king cursor static for select * from work
它具有两个特点:1:不能修改
update work set 基本工资=基本工资+100 where current of kk_king[能执行?]
2:不能反应用户对基本的修改
1)创建一个静态游标之后,用[fetch first from 游标名]去提取首行记录.
2)把基本改变一下,再次使用fetch命令来提取,看一下记录有没有改变
3:本身就是滚动游标,不能更新的
F:动态游标:1:这种游标可以反映在滚动游标时对结果集内的行所做的更改.
2:滚动游标是可更新的,定义时只需要加上[DYNAMIC]关键字就行了.[证明]
G:键集游标:这种游标在定义时只需要加入KEYSET关键字就行了.
比如:declare kk_king cursor keyset for select * from work
它具有特点:1:对基表中的非键值所做的更改在用户滚动游标时是可见的
比如:work表中以职工号作为主键.
1):用fetch命令提取一行记录后,对基表非职工号列进行修改.
2):用fetch命令提取新的行,看是否可见.
2:对基本表中键值所做的更改在用户滚动游标时对于键值列没有内容,对于非键值列为空,相当于不可视
1):用fetch命令提取一行记录后,对基表职工号列进行修改.
2):用fetch命令提取新行察看结果
3:对于通过使用[where current of 游标名]对键值的更新新键值在游标的尾部可见 [证明]
4:对其它用户插入的值是不可视的除非先关闭之后再打开
1):创建游标之后,往里面插入一行值
2):用fetch命令查看一下是否可见
H:悲观并发控制锁定游标:这种游标在定义时需要加上关键字[SCROLL_LOCKS]关键字
特点:会锁定当前游标位置上的记录,任何通过修改锁定记录上的修改都将暂无法得到提交,除非当游标移动后,会解除当前行的锁定,而是去锁定游标指定的行.
I:乐观并发控制游标:这种游标在定义时只需要加上[OPTIMISTIC]关键字
特点:当将行读入游标时,SQL Server不锁定行.相反,SQL
Server会在对数据进行修改之前,要检查数据是否自读入以来有没有被别的用户更改,如果更改,则修改失败[证明]
sql server注释的代码合并起来 sql server如何注释语句
转载文章标签 sql server注释的代码合并起来 批处理 结果集 服务器 文章分类 SQL Server 数据库
-
sql server 多行取消注释 sql server注释怎么写
开发中有时会用代码生成器来生成一些代码,这时会取数据库中的表注释和列注释拿过来当做代码的model类和属性做注释。sqlserver中给列加注释(说明)很简单。如果手动加表的说明: 右键属性 扩展属性 名称指定特定名称:MS_Description 这就是注释了
sql server 多行取消注释 sqlserver 表 注释 说明 代码生成器 sql 右键
















