【网学网提醒】:网学会员为需要朋友们搜集整理了T_SQL编程基础语法相关资料,希望对各位网友有所帮助!
T-SQL编程基础语法
一、数据类型
1、字符型:char、nchar、varchar、nvarchar、text、ntext
a)char:固定长度的非Unicode字符数据,最大的长度为8000字符。
b)nchar:固定长度的Unicode数据,最大的长度为4000字符。
c)varchar:可变长度的非Unicode数据,最大的长度为8000字符。
d)nvarchar:可变长度的Unicode数据,最大的长度为4000字符。
e)text:可变长度的非Unicode数据,最大的长度为2^31-1个字符。
f)ntext:可变长度的Unicode数据,最大的长度为2^30-1个字符
对于定义为char或nchar的列,SQLSERVER将用字符串来填满指定的字节数。
定义为varchar或nvarchar的列只存储输入的实际长度,可能舍去尾部空间。SQLSERVER处理尾部空间,取决于SETANSI_PADDING,以及该列是固定长度还是可变长度。
根据SETANSI_PADDING值处理尾部空间ANSI_PADDINGchar和ncharVarchar和nvarchar
ON串被空格填充到列的长度串未被空格填充到列的长度,尾部空间被保留
OFF串被空格填充到列的长度串未被空格填充到列的长度,尾部空间被截掉
2、日期和时间型:smalldatetime、datetime。
a)smalldatetime:从1900年1月1日到2079年6月6日,精确到1分钟。
b)datetime:从1753年1月1日到9999年12月31日,精确到三百分之一秒,即3.33毫秒。
3、数据型数值类型
A、整型:smallint、int、tinyint。
a)smallint:从2^15到2^15-1。
b)int:从-2^31到2^31-1。
c)tinyint:从0到255。
B、近似数字数据类型:float和real。
a)float:浮点精度数字数据,从-1.79E+308到1.79E+308。
b)real::浮点精度数字数据,从-3.40E+308到3.40E+308。
C、精确数字数据类型:decimal和numeric。
a)decimal:不带符号的整数,按10进位。
b)numeric:decimal(十近制)的同义词。
D、货币数据类型:money和smallmoney。
a)money:从-2^63到2^63-1,精确到每个货币单位的万分之一。
b)smallmoney:从-214,748.3648到+214,748.3647,精确到每个货币单位的万分之一。
4、逻辑数据类型:bit
Bit:整形数据,值为1或0。
5、自定义的数据类型
用户可以通过两个系统存储过程创建和删除用户定义类型。(它们不是真正的新数据类型,而像是一种复合型数据类型或结构。)
Sp_addtype过程创建用户定义的数据类型。
Sp_droptype过程删除定义的数据类型。
(1)创建自定义的数据类型
①格式:Sp_addtype自定义数据类型名,系统的数据类型,'[null|notnull]'
②说明:A、用户自定义的数据类型是基于系统的数据类型创建的。
B、[null|notnull]:指定该列是否为空。默认为null。
C、如果系统数据类型包括圆括弧,必须用引号把它括起来。
③实例:Sp_addty
pebirthday,datetime,'notnull'
Createtablestu1(sidint,sbirthdaybirthday)
(2)删除自定义的数据类型
①格式[:Exec]sp_droptype自定义的数据类型。
②实例:[Exec]sp_droptypebirthday。
注意:我们还可以通过企业管理器创建自定义的数据类型。首先,选中一个数据库,点击右键,选中“新建”,从弹开的菜单中选中“用户定义的数据类型”,在打开的窗体中填充相应的选项即可。
二、常量与变量
1.常量:
数字常量:整数和小数常量在SQL中被写成普通的小数数字,前面可加正负号,例如:12,?37,200.45
在数字常量的各个位之间不要加逗号,例如,123123这个数字是不能表示为:123,123。
浮点常量使用符号e来指定,例如:1.5e3,3.14e1,2.5e7
e被读作“乘10的几次幂”。
字符串常量:SQL规定字符数据常量要包含在单引号内,例如:'loving'。
如果在常量文本中要包含一个单引号,则在这个常量内写作两个连续的单引号。
因此常量值:'ILOVE''0.5公里'即表示'ILOVE'0.5公里'。
日期和时间常量:
SQL规定日期、时间和时间间隔的常量值被指定为字符串常量。下面的书写是合法的。
例如:'1984-03-10','03/03/1976'。
日期和时间根据国家不同,书定方式也不同。例如,美国表示为mm/dd/yyyy,欧洲表示为dd.mm.yyyy,日本表示为yyyy-mm-dd等。
符号常量:除了用户提供的常量外,SQL包含几个特有的符号常量,这些常量代表不同的常用数据值。
例如,CURRENT_DATE表示当前的日期,类似的如CURRENT_TIME、CURRENT_TIMESTAMP等。
这些符号常量也可以通过SQLSERVER的内嵌函数访问。
(1)日期常量:
字母日期格式:'December10,2010'--表示2010年12月10日
数字日期格式:'12/10/2010'、'December10,2010'--表示2010年12月10日
未分割的字符串格式:'20101209'、'December9,2010'--表示2010年12月9日
时间常量:'14:30:24'、'2:30:24PM'--表示下午2时30分24秒
日期时间常量:'December10,201014:30:24'--表示2010年12月10日下午2时30分24秒
(2)货币money常量:
$542023
-$45.56
+$423456.78
2.变量的定义与输出
变量是一种语言中必不可少的组成部分。Transact-SQL语言中有两种形式的变量,一种是用户自己定义的局部变量,另外一种是系统提供的全局变量。
局部变量:
局部变量是一个能够拥有特定数据类型的对象,它的作用范围仅限制在程序内部。局部变量可以作为计数器来计算循环执行的次数,或是控制循环执行的次数。另外,利用局部变量还可以保存数据值,以供控制流语句测试以及保存由存储过程返回的数据值等。局部变量被引用时要在其名称前加上标志“@”,而
且必须先用DECLARE命令定义后才可以使用。
局部变量定义格式:declare@local_variable1data_type[,...@local_variablendata_type]
其中变量名命名规则:以字母、下划线(_)、@或#开头,后续可跟一个或若干字符、下划线(_)、$、@或#,但不能全为下划线(_)、@或#。
全局变量:
全局变量是SQLServer系统内部使用的变量,其作用范围并不仅仅局限于某一程序,而是任何程序均可以随时调用。全局变量通常存储一些SQLServer的配置设定值和统计数据。用户可以在程序中用全局变量来测试系统的设定值或者是Transact-SQL命令执行后的状态值。
使用全局变量时应该注意以下几点:
①全局变量不是由用户的程序定义的,它们是在服务器级定义的。
②用户只能使用预先定义的全局变量。
③引用全局变量时,必须以标记符“@@”开头。
④局部变量的名称不能与全局变量的名称相同,否则会在应用程序中出现不可预测的结果。
例1.查看数据库的版本
select@@version
例2.查看数据库服务器名和实例名
print'ServerName...............:'+convert(varchar(30),@@SERVERNAME)
print'Instance..................:'+convert(varchar(30),@@SERVICENAME)
转换函数:cast(表达式as数据类型)或convert(数据类型,表达式)
例:declare@aint,@bsmallint,@cchar(6),@ddatetime,@mmoney
declare@edecimal(5,2),@ffloat,@gnumeric(5,2)
set@a=33417--可以set@a=(selectsagefromstudentwheresno='200215121')
set@b=89--使用SET语句给变量赋值,每次只能给一个变量赋值。
set@c='数据库'
set@d='12/11/2010'--或'12-11-2010'或'20101211'
set@m=$15000.32
set@e=89.34
set@f=95.6
set@g=88.9
--可使用SELECT语句给变量赋值,每次可给多个变量赋值。
--如select@a=33417,@b=89,@c='数据库',@d='12/15/2010',@m=$15000.32,@e=89.34,@f=95.6,@g=88.9
--使用print输出数据(自动按字符类型转换)
print'a='+convert(char(5),@a)+';b='+convert(char(4),@b)+';c='+@c
print@a--隐性转换为nvarchar类型输出
print@d
printconvert(char,@m)--不允许从数据类型money到nvarchar的隐性转换。请使用CAST或CONVERT函数进行显示转换成字符型。
print@e
print@f
print@g
--使用select方式输出数据(按原类型)
select@a,@b,@c,@d日期,@m货币,@e,@f,@g
三、运算符
在SQLServer2000中,运算符主要有以下六大类:算术运算符、赋值运算符、位运算符、比较运算符、逻辑运算符以及字符串串联运算符。
字符串串联运算符允许通过加号(+)进行字符串串联,这个加号即被称为字符串串联运算符。
例如对于语句SELECT'abc'+'def',其结果为abcdef。
运算符的优先等级从高到低如下所示
括号:();
乘、除、求模运算
符:*、/、%;
加减运算符:+、-;
比较运算符:=、>、<、>=、<=、<>、!=、!>、!<;
位运算符:^、&;、|;
逻辑运算符:NOT;
逻辑运算符:AND;
逻辑运算符:OR。
四、函数
在Transact-SQL语言中,函数被用来执行一些特殊的运算以支持SQLServer的标准命令。
Transact-SQL编程语言提供了三种函数:
㈠行集函数:行集函数可以在Transact-SQL语句中当作表引用。
㈡聚合函数:聚合函数用于对一组值执行计算并返回一个单一的值。
㈢标量函数:标量函数用于对传递给它的一个或者多个参数值进行处理和计算,并返回一个单一的值。
SQLServer中最常用的几种函数
1.字符串函数
字符串函数可以对二进制数据、字符串和表达式执行不同的运算,大多数字符串函数只能用于char和varchar数据类型以及明确转换成char和varchar的数据类型,少数几个字符串函数也可以用于binary和varbinary数据类型。此外,某些字符串函数还能够处理text、ntext、image数据类型的数据。
字符串函数的分类:
基本字符串函数:UPPER、LOWER、SPACE、REPLICATE、STUFF、REVERSE、LTRIM、RTRIM。
字符串查找函数:CHARINDEX、PATINDEX。
长度和分析函数:DATALENGTH、SUBSTRING、RIGHT。
转换函数:ASCH、CHAR、STR、SOUNDEX、DIFFERENCE。
2.日期和时间函数
日期和时间函数用于对日期和时间数据进行各种不同的处理和运算,并返回一个字符串、数字值或日期和时间值。在SQLServer2000中,日期和时间函数的类型如下:DATEADD(datepart,number,date)
DATEDIFF(datepart,date1,date2)
DATENAME(datepart,date)
DATEPART(datepart,date)
DAY(date)
GETDATE()
MONTH(date)
YEAR(date)
从GETDATE函数返回的日期中提取月份数。
SELECTDATEPART(month,GETDATE())AS'MonthNumber'
运行结果为:
MonthNumber
------------
2
从日期03/12/1998中返回月份数、天数和年份数。
SELECTMONTH('03/12/1998'),DAY('03/12/1998'),YEAR('03/12/1998')
运行结果为:
-----------------
3121998
3.数学函数
数学函数用于对数字表达式进行数学运算并返回运算结果。数学函数可以对SQLServer提供的数字数据(decimal、integer、float、real、money、smallmoney、smallint和tinyint)进行处理。
在同一表达式中使用CEILING()、FLOOR()、ROUND()函数。
selectceiling(13.4),floor(13.4),round(13.4567,3)
运行结果为:
-------------------------
141313.4570
4.转换函数
一般情况下,SQLServer会自动处理某些数据类型的转换。例如,如果比较char和datetime表达式、smallint和int表达式、或不同长度的char表达式,SQLServer可以将它们自动转换,这
种转换被称为隐性转换。但是,无法由SQLServer自动转换的或者是SQLServer自动转换的结果不符合预期结果的,就需要使用转换函数做显示转换。转换函数有两个:CONVERT和CAST。
CONVERT和CAST函数
CAST(expressionASdata_type)
CONVERT函数允许用户把表达式从一种数据类型转换成另一种数据类型,还允许把日期转换成不同的样式。其语法形式为:
CONVERT(data_type[(length)],expression[,style])
USEpubs
SELECTtitle,ytd_sales
FROMtitles
WHERECAST(ytd_salesASchar(20))LIKE'15%'
ANDtype='trad_cook'
运行结果为:
Titleytd_sales
------------------------------
FiftyYearsinBuckinghamPalaceKitchens15096
5.系统函数
系统函数用于返回有关SQLServer系统、用户、数据库和数据库对象的信息。系统函数可以让用户在得到信息后,使用条件语句,根据返回的信息进行不同的操作。与其它函数一样,可以在SELECT语句的SELECT和WHERE子句以及表达式中使用系统函数。
返回Northwind数据库的Employees表中的首列的名称。
USENorthwind
SELECTCOL_NAME(OBJECT_ID('Employees'),1)
运行结果为:
EmployeeID
6.聚合函数
聚合函数可以返回整个或者几个列或者一个列的汇总数据,它常用来计算SELECT语句查询的统计值。聚合函数经常与SELECT语句的GROUPBY子句一同使用。
----统计函数----
AVG--求平均值
COUNT--统计数目
MAX--求最大值
MIN--求最小值
SUM--求和
--AVG
usepangu
selectavg(e_wage)asdept_avgWage
fromemployee
groupbydept_id
--MAX
--求工资最高的员工
usepangu
selecte_name
fromemployee
wheree_wage=
(selectmax(e_wage)
fromemployee)
--STDEV()
--STDEV()函数返回表达式中所有数据的标准差
--STDEVP()
--STDEVP()函数返回总体标准差
--VAR()
--VAR()函数返回表达式中所有值的统计变异数
--VARP()
--VARP()函数返回总体变异数
----算术函数----
/***三角函数***/
SIN(float_expression)--返回以弧度表示的角的正弦
COS(float_expression)--返回以弧度表示的角的余弦
TAN(float_expression)--返回以弧度表示的角的正切
COT(float_expression)--返回以弧度表示的角的余切
/***反三角函数***/
ASIN(float_expression)--返回正弦是FLOAT值的以弧度表示的角
ACOS(float_expression)--返回余弦是FLOAT值的以弧度表示的角
ATAN(float_expression)--返回正切是FLOAT值的以弧度表示的角
ATAN2(float_expression1,float_expression2)
--返回正切是float_expression1/float_expres-sion2的以弧度表示的角
DEGREES(numeric_expression)
--把弧度转换为角度返回与表达式相同的数据类型可为
--INTEGER/MONEY/REAL/FLOAT类型
RADIANS(numeric_expression)--把角度转换为
弧度返回与表达式相同的数据类型可为
--INTEGER/MONEY/REAL/FLOAT类型
EXP(float_expression)--返回表达式的指数值
LOG(float_expression)--返回表达式的自然对数值
LOG10(float_expression)--返回表达式的以10为底的对数值
SQRT(float_expression)--返回表达式的平方根
/***取近似值函数***/
CEILING(numeric_expression)--返回>=表达式的最小整数返回的数据类型与表达式相同可为
--INTEGER/MONEY/REAL/FLOAT类型
FLOOR(numeric_expression)--返回<=表达式的最小整数返回的数据类型与表达式相同可为
--INTEGER/MONEY/REAL/FLOAT类型
ROUND(numeric_expression)--返回以integer_expression为精度的四舍五入值返回的数据
--类型与表达式相同可为INTEGER/MONEY/REAL/FLOAT类型
ABS(numeric_expression)--返回表达式的绝对值返回的数据类型与表达式相同可为
--INTEGER/MONEY/REAL/FLOAT类型
SIGN(numeric_expression)--测试参数的正负号返回0零值1正数或-1负数返回的数据类型
--与表达式相同可为INTEGER/MONEY/REAL/FLOAT类型
PI()--返回值为π即3.1415926535897936
RAND([integer_expression])--用任选的[integer_expression]做种子值得出0-1间的随机浮点数
----字符串函数----
ASCII()--函数返回字符表达式最左端字符的ASCII码值
CHAR()--函数用于将ASCII码转换为字符
--如果没有输入0~255之间的ASCII码值CHAR函数会返回一个NULL值
LOWER()--函数把字符串全部转换为小写
UPPER()--函数把字符串全部转换为大写
STR()--函数把数值型数据转换为字符型数据
LTRIM()--函数把字符串头部的空格去掉
RTRIM()--函数把字符串尾部的空格去掉
LEFT(),RIGHT(),SUBSTRING()--函数返回部分字符串
CHARINDEX(),PATINDEX()--函数返回字符串中某个指定的子串出现的开始位置
SOUNDEX()--函数返回一个四位字符码
--SOUNDEX函数可用来查找声音相似的字符串但SOUNDEX函数对数字和汉字均只返回0值
DIFFERENCE()--函数返回由SOUNDEX函数返回的两个字符表达式的值的差异
--0两个SOUNDEX函数返回值的第一个字符不同
--1两个SOUNDEX函数返回值的第一个字符相同
--2两个SOUNDEX函数返回值的第一二个字符相同
--3两个SOUNDEX函数返回值的第一二三个字符相同
--4两个SOUNDEX函数返回值完全相同
QUOTENAME()--函数返回被特定字符括起来的字符串
/*selectquotename('abc','{')quotename('abc')
运行结果如下
----------------------------------{
{abc}[abc]*/
REPLICATE()--函数返回一个重复character_expression指定次数的字符串
/*selectreplicate('abc',3)replicate('abc',-2)
运行结果如下
----------------------
abcabcabcNU
LL*/
REVERSE()--函数将指定的字符串的字符排列顺序颠倒
REPLACE()--函数返回被替换了指定子串的字符串
/*selectreplace('abc123g','123','def')
运行结果如下
----------------------
abcdefg*/
SPACE()--函数返回一个有指定长度的空白字符串
STUFF()--函数用另一子串替换字符串指定位置长度的子串
----数据类型转换函数----
CAST()函数语法如下
CAST()(
AS[length])
CONVERT()函数语法如下
CONVERT()([length],[,style])
selectcast(100+99aschar)convert(varchar(12),getdate())
运行结果如下
------------------------------------------
199Jan152000
----日期函数----
DAY()--函数返回date_expression中的日期值
MONTH()--函数返回date_expression中的月份值
YEAR()--函数返回date_expression中的年份值
DATEADD(,,)
--函数返回指定日期date加上指定的额外日期间隔number产生的新日期
DATEDIFF(,,)
--函数返回两个指定日期在datepart方面的不同之处
DATENAME(,)--函数以字符串的形式返回日期的指定部分
DATEPART(,)--函数以整数值的形式返回日期的指定部分
GETDATE()--函数以DATETIME的缺省格式返回系统当前的日期和时间
----系统函数----
APP_NAME()--函数返回当前执行的应用程序的名称
COALESCE()--函数返回众多表达式中第一个非NULL表达式的值
COL_LENGTH(<'table_name'>,<'column_name'>)--函数返回表中指定字段的长度值
COL_NAME(,)--函数返回表中指定字段的名称即列名
DATALENGTH()--函数返回数据表达式的数据的实际长度
DB_ID(['database_name'])--函数返回数据库的编号
DB_NAME(database_id)--函数返回数据库的名称
HOST_ID()--函数返回服务器端计算机的名称
HOST_NAME()--函数返回服务器端计算机的名称
IDENTITY([,seedincrement])[AScolumn_name])
--IDENTITY()函数只在SELECTINTO语句中使用用于插入一个identitycolumn列到新表中
/*selectidentity(int,1,1)ascolumn_name
intonewtable
fromoldtable*/
ISDATE()--函数判断所给定的表达式是否为合理日期
ISNULL(,)--函数将表达式中的NULL值用指定值替换
ISNUMERIC()--函数判断所给定的表达式是否为合理的数值
NEWID()--函数返回一个UNIQUEIDENTIFIER类型的数值
NULLIF(,)
--NULLIF函数在expression1与expression2相等时返回NULL值若不相等时则返回expression1的值
====精妙SQL语句====
说明:复制表(只复制结构,源表名:a新表名:b)
SQL:select*intobfromawhere1<>1
说明:复制表(源表名:a,新表名:b)
SQL:
select*intobfroma
说明:拷贝表(拷贝数据,源表名:a,目标表名:b,表b必须存在)
SQL:insertintob(b1,b2,b3)selectd,e,ffroma;
说明:显示文章、提交人和最后回复时间
SQL:selecta.title,a.username,b.adddate
fromtablea,(selectmax(adddate)adddatefromtablewheretable.title=a.title)b
说明:外连接查询(表名1:a表名2:b)
SQL:selecta.a,a.b,a.c,b.c,b.d,b.ffromaLEFTOUTJOINbONa.a=b.c
说明:日程安排提前五分钟提醒
SQL:select*from日程安排wheredatediff('minute',f开始时间,getdate())>5
说明:两张关联表,删除主表中已经在副表中没有的信息
SQL:
deletefrominfowherenotexists(select*frominfobzwhereinfo.infid=infobz.infid)
---------数学函数
1.绝对值
S:selectabs(-1)value
O:selectabs(-1)valuefromdual
2.取整(大)
S:selectceiling(-1.001)value
O:selectceil(-1.001)valuefromdual
3.取整(小)
S:selectfloor(-1.001)value
O:selectfloor(-1.001)valuefromdual
4.取整(截取)
S:selectcast(-1.002asint)value
O:selecttrunc(-1.002)valuefromdual
5.四舍五入
S:selectround(1.23456,4)value1.23460
O:selectround(1.23456,4)valuefromdual1.2346
6.e为底的幂
S:selectExp(1)value2.7182818284590451
O:selectExp(1)valuefromdual2.71828182
7.取e为底的对数
S:selectlog(2.7182818284590451)value1
O:selectln(2.7182818284590451)valuefromdual;1
8.取10为底对数
S:selectlog10(10)value1
O:selectlog(10,10)valuefromdual;1
9.取平方
S:selectSQUARE(4)value16
O:selectpower(4,2)valuefromdual16
10.取平方根
S:selectSQRT(4)value2
O:selectSQRT(4)valuefromdual2
11.求任意数为底的幂
S:selectpower(3,4)value81
O:selectpower(3,4)valuefromdual81
12.取随机数
S:selectrand()value
O:selectsys.dbms_random.value(0,1)valuefromdual;
13.取符号
S:selectsign(-8)value-1
O:selectsign(-8)valuefromdual-1
----------数学函数
14.圆周率
S:SELECTPI()value3.1415926535897931
O:不知道
15.sin,cos,tan参数都以弧度为单位
例如:selectsin(PI()/2)value得到1(SQLServer)
16.Asin,Acos,Atan,Atan2返回弧度
17.弧度角度互换(SQLServer,Oracle不知道)
DEGREES:弧度-〉角度
RADIANS:角度-〉弧度
---------数值间比较
18.求集合最大值
S:selectmax(value)valuefrom
(select1value
union
select-2value
union
select4value
union
select3value)a
O:selectgreatest(1,-2,4,3)valuefromdual
19.求集合最小值
S:selectmin(value)valuefrom
(select1value
union
select-2value
union
select4value
union
select3value)a
O:selectleast(1,-2,4,3)valuefromdual
20.如何处理null值(F2中的null以10代替)
S:selectF1,IsNull(F2,10)valuefromTbl
O:selectF1,nvl(F2,10)valuefromTbl
--------数值间比较
21.求字符序号
S:selectas
cii('a')value
O:selectascii('a')valuefromdual
22.从序号求字符
S:selectchar(97)value
O:selectchr(97)valuefromdual
23.连接
S:select'11'+'22'+'33'value
O:selectCONCAT('11','22')||33valuefromdual
23.子串位置--返回3
S:selectCHARINDEX('s','sdsq',2)value
O:selectINSTR('sdsq','s',2)valuefromdual
23.模糊子串的位置--返回2,参数去掉中间%则返回7
S:selectpatindex('%d%q%','sdsfasdqe')value
O:oracle没发现,但是instr可以通过第四霾问刂瞥鱿执问?BR>selectINSTR('sdsfasdqe','sd',1,2)valuefromdual返回6
24.求子串
S:selectsubstring('abcd',2,2)value
O:selectsubstr('abcd',2,2)valuefromdual
25.子串代替返回aijklmnef
S:SELECTSTUFF('abcdef',2,3,'ijklmn')value
O:SELECTReplace('abcdef','bcd','ijklmn')valuefromdual
26.子串全部替换
S:没发现
O:selectTranslate('fasdbfasegas','fa','我')valuefromdual
27.长度
S:len,datalength
O:length
28.大小写转换lower,upper
29.单词首字母大写
S:没发现
O:selectINITCAP('abcddsafdf')valuefromdual
30.左补空格(LPAD的第一个参数为空格则同space函数)
S:selectspace(10)+'abcd'value
O:selectLPAD('abcd',14)valuefromdual
31.右补空格(RPAD的第一个参数为空格则同space函数)
S:select'abcd'+space(10)value
O:selectRPAD('abcd',14)valuefromdual
32.删除空格
S:ltrim,rtrim
O:ltrim,rtrim,trim
33.重复字符串
S:selectREPLICATE('abcd',2)value
O:没发现
34.发音相似性比较(这两个单词返回值一样,发音相同)
S:SELECTSOUNDEX('Smith'),SOUNDEX('Smythe')
O:SELECTSOUNDEX('Smith'),SOUNDEX('Smythe')fromdual
SQLServer中用SELECTDIFFERENCE('Smithers','Smythers')比较soundex的差
返回0-4,4为同音,1最高
--------------日期函数
35.系统时间
S:selectgetdate()value
O:selectsysdatevaluefromdual
36.前后几日
直接与整数相加减
37.求日期
S:selectconvert(char(10),getdate(),20)value
O:selecttrunc(sysdate)valuefromdual
selectto_char(sysdate,'yyyy-mm-dd')valuefromdual
38.求时间
S:selectconvert(char(8),getdate(),108)value
O:selectto_char(sysdate,'hh24:mm:ss')valuefromdual
39.取日期时间的其他部分
S:DATEPART和DATENAME函数(第一个参数决定)
O:to_char函数第二个参数决定
参数---------------------------------下表需要补充
yearyy,yyyy
quarterqq,q(季度)
monthmm,m(mO无效)
dayofyeardy,y(O表星期)
daydd,d(dO无效)
weekwk,ww(wkO无效)
weekdaydw(O不清楚)
Hourhh,hh12,hh24(hh12,hh24S无效)
minutemi,n(nO无效)
secondss,s(sO无效)
millisecondms(O无效)
----------------------------------------------
40.当月最后一天
S:不知道
O:selectLAST_DAY(sysdate)valuefromdual
41.本星期的某一天(比如星期日)
S:不知道
O:SELECTNext_day(sysdate,7)vauleFROMDUAL;
42.字符串转
时间
S:可以直接转或者selectcast('2004-09-08'asdatetime)value
O:SELECTTo_date('2004-01-0522:09:38','yyyy-mm-ddhh24-mi-ss')vauleFROMDUAL;
43.求两日期某一部分的差(比如秒)
S:selectdatediff(ss,getdate(),getdate()+12.3)value
O:直接用两个日期相减(比如d1-d2=12.3)
SELECT(d1-d2)*24*60*60vauleFROMDUAL;
44.根据差值求新的日期(比如分钟)
S:selectdateadd(mi,8,getdate())value
O:SELECTsysdate+8/60/24vauleFROMDUAL;
45.求不同时区时间
S:不知道
O:SELECTNew_time(sysdate,'ydt','gmt')vauleFROMDUAL;
-----时区参数,北京在东8区应该是Ydt-------
ASTADT大西洋标准时间
BSTBDT白令海标准时间
CSTCDT中部标准时间
ESTEDT东部标准时间
GMT格林尼治标准时间
HSTHDT阿拉斯加—夏威夷标准时间
MSTMDT山区标准时间
NST纽芬兰标准时间
PSTPDT太平洋标准时间
YSTYDTYUKON标准时间
四、sqlserver中的流程控制语句
流程控制语句主要用来控制SQL语句、语句块或者存储过程的执行流程。
1.IF…ELSE语句
IF…ELSE语句是条件判断语句,其中,ELSE子句是可选的,最简单的IF语句没有ELSE子句部分。IF…ELSE语句用来判断当某一条件成立时执行某段程序,条件不成立时执行另一段程序。SQLServer允许嵌套使用IF…ELSE语句,而且嵌套层数没有限制。
IF…ELSE语句的语法形式:
IFBoolean_expression{sql_statement|statement_block}[ELSE{sql_statement|statement_block}]
例:
declare@xint@yint@zint
select@x=1@y=2@z=3
if@x>@y
print'x>y'--打印字符串'x>y'
elseif@y>@z
print'y>z'
elseprint'z>y'
2.BEGIN…END语句
BEGIN…END语句能够将多个Transact-SQL语句组合成一个语句块,并将它们视为一个单元处理。在条件语句和循环等控制流程语句中,当符合特定条件便要执行两个或者多个语句时,就需要使用BEGIN…END语句,其语法形式为:
BEGIN{sql_statement|statement_block}END
3.CASE函数
CASE函数可以计算多个条件式,并将其中一个符合条件的结果表达式返回。CASE函数按照使用形式的不同,可以分为简单CASE函数和搜索CASE函数。
CASE函数的语法形式
CASEinput_expressionWHENwhen_expressionTHENresult_expression[...n][ELSEelse_result_expressionEND
搜索CASE函数的语法形式
CASEWHENBoolean_expressionTHENresult_expression[...n][ELSEelse_result_expressionEND
例:
usepangu
updateemployee
sete_wage=
case
whenjob_level=’1’thene_wage*1.08
whenjob_level=’2’thene_wage*1.07
whenjob_level=’3’thene_wage*1.06
elsee_wage*1.05
end
4.WHILE…CONTINUE…BREAK语句
WHILE…CONTINUE…BREAK语句用于设置重复执行SQL语句或语句块的条件。只要指定
的条件为真,就重复执行语句。其中,CONTINUE语句可以使程序跳过CONTINUE语句后面的语句,回到WHILE循环的第一行命令。BREAK语句则使程序完全跳出循环,结束WHILE语句的执行。
结束WHILE语句的语法形式为:
WHILEBoolean_expression{sql_statement|statement_block}[BREAK]{sql_statement|statement_block}[CONTINUE]
例:
eclare@xint@yint@cint
select@x=1@y=1
while@x<3
begin
print@x--打印变量x的值
while@y<3
begin
select@c=100*@x+@y
print@c--打印变量c的值
select@y=@y+1
end
select@x=@x+1
select@y=1
end
5.GOTO语句
GOTO语句可以使程序直接跳到指定的标有标识符的位置处继续执行,而位于GOTO语句和标识符之间的程序将不会被执行。GOTO语句和标识符可以用在语句块、批处理和存储过程中,标识符可以为数字与字符的组合,但必须以“:”结尾。
GOTO语句的语法形式
GOTOlabel
……
label:
程序清单2-50:利用GOTO语句求出从1加到5的总和。
declare@sumint,@countint
select@sum=0,@count=1
label_1:
select@sum=@sum+@count
select@count=@count+1
if@count<=5
gotolabel_1
select@count,@sum
6.WAITFOR语句
WAITFOR语句用于暂时停止执行SQL语句、语句块或者存储过程等,直到所设定的时间已过或者所设定的时间已到才继续执行。WAITFOR语句的语法形式为:
WAITFOR{DELAY'time'|TIME'time'}
其中,DELAY用于指定时间间隔,TIME用于指定某一时刻,其数据类型为datetime,格式为‘hh:mm:ss’。
--例等待1小时2分零3秒后才执行SELECT语句
waitfordelay’01:02:03’
select*fromemployee
--例等到晚上11点零8分后才执行SELECT语句
waitfortime’23:08:00’
select*fromemployee
7.RETURN语句
RETURN语句用于无条件地终止一个查询、存储过程或者批处理,此时位于RETURN语句之后的程序将不会被执行。RETURN语句的语法形式为:
RETURN[integer_expression]
其中,参数integer_expression为返回的整型值。存储过程可以给调用过程或应用程序返回整型值。
8.数据库操作语句
SELECT--从数据库表中检索数据行和列
INSERT--向数据库表添加新数据行
DELETE--从数据库表中删除数据行
UPDATE--更新数据库表中的数据
--数据定义
CREATETABLE--创建一个数据库表
DROPTABLE--从数据库中删除表
ALTERTABLE--修改数据库表结构
CREATEVIEW--创建一个视图
DROPVIEW--从数据库中删除视图
CREATEINDEX--为数据库表创建一个索引
DROPINDEX--从数据库中删除索引
CREATEPROCEDURE--创建一个存储过程
DROPPROCEDURE--从数据库中删除存储过程
CREATETRIGGER--创建一个触发器
DROPTRIGGER
--从数据库中删除触发器
CREATESCHEMA--向数据库添加一个新模式
DROPSCHEMA--从数据库中删除一个模式
CREATEDOMAIN--创建一个数据值域
ALTERDOMAIN--改变域定义
DROPDOMAIN--从数据库中删除一个域
--数据控制
GRANT--授予用户访问权限
DENY--拒绝用户访问
REVOKE--解除用户访问权限
--事务控制
COMMIT--结束当前事务
ROLLBACK--中止当前事务
SETTRANSACTION--定义当前事务数据访问特征
--程序化SQL
DECLARE--为查询设定游标
EXPLAN--为查询描述数据访问计划
OPEN--检索查询结果打开一个游标
FETCH--检索一行查询结果
CLOSE--关闭游标
PREPARE--为动态执行准备SQL语句
EXECUTE--动态地执行SQL语句
DESCRIBE--描述准备好的查询
---局部变量
declare@idchar(10)
--set@id='10010001'
select@id='10010001'
---全局变量
---必须以@@开头
***SELECT***
select*(列名)fromtable_name(表名)wherecolumn_nameoperatorvalue
ex:(宿主)
select*fromstock_informationwherestockid=str(nid)
stockname='str_name'
stocknamelike'%findthis%'
stocknamelike'[a-zA-Z]%'---------([]指定值的范围)
stocknamelike'[^F-M]%'---------(^排除指定范围)
---------只能在使用like关键字的where子句中使用通配符)
orstockpath='stock_path'
orstocknumber<1000
andstockindex=24
notstocksex='man'
stocknumberbetween20and100
stocknumberin(10,20,30)
orderbystockiddesc(asc)---------排序,desc-降序,asc-升序
orderby1,2---------by列号
stockname=(selectstocknamefromstock_informationwherestockid=4)
---------子查询
---------除非能确保内层select只返回一个行的值,
---------否则应在外层where子句中用一个in限定符
selectdistinctcolumn_nameformtable_name---------distinct指定检索独有的列值,不重复
selectstocknumber,"stocknumber+10"=stocknumber+10fromtable_name
selectstockname,"stocknumber"=count(*)fromtable_namegroupbystockname
---------groupby将表按行分组,指定列中有相同的值
havingcount(*)=2---------having选定指定的组
select*
fromtable1,table2
wheretable1.id*=table2.id--------左外部连接,table1中有的而table2中没有得以null表示
table1.id=*table2.id--------右外部连接
selectstocknamefromtable1
union[all]-----union合并查询结果集,all-保留重复行
selectstocknamefromtable2
***insert***
insertintotable_name(Stock_name,Stock_number)value("xxx","xxxx")
value(selectStockname,StocknumberfromStock_table2)---value为sele
ct语句
***update***
updatetable_namesetStockname="xxx"[whereStockid=3]
Stockname=default
Stockname=null
Stocknumber=Stockname+4
***delete***
deletefromtable_namewhereStockid=3
truncatetable_name-----------删除表中所有行,仍保持表的完整性
droptabletable_name---------------完全删除表
***altertable***---修改数据库表结构
altertabledatabase.owner.table_nameaddcolumn_namechar(2)null.....
sp_helptable_name----显示表已有特征
createtabletable_name(namechar(20),agesmallint,lnamevarchar(30))
insertintotable_nameselect.........-----实现删除列的方法(创建新表)
altertabletable_namedropconstraintStockname_default----删除Stockname的default约束
五、事务
(一)定义及其性质:
事务:事务是作为单个逻辑工作单元执行的一系列操作。
属性:一个逻辑工作单元必须有四个属性,称为ACID(原子性、一致性、隔离性和持久性)属性,只有这样才能成为一个事务:
1.原子性:事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。
2.一致性:事务在完成时,必须使所有的数据都保持一致状态。
在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。事务结束时,所有的内部数据结构(如B树索引或双向链表)都必须是正确的。
3.隔离性:由并发事务所作的修改必须与任何其它并发事务所作的修改隔离。
事务查看数据时数据所处的状态,要么是另一并发事务修改它之前的状态,要么是另一事务修改它之后的状态,事务不会查看中间状态的数据。这称为可串行性,因为它能够重新装载起始数据,并且重播一系列事务,以使数据结束时的状态与原始事务执行的状态相同。
4.持久性:事务完成之后,它对于系统的影响是永久性的。
该修改即使出现系统故障也将一直保持。
(二)指定和强制事务处理
SQL程序员要负责启动和结束事务,同时强制保持数据的逻辑一致性。程序员必须定义数据修改的顺序,使数据相对于其组织的业务规则保持一致。然后,程序员将这些修改语句包括到一个事务中,使MicrosoftSQLServer能够强制该事务的物理完整性。
企业数据库系统(如SQLServer)有责任提供一种机制,保证每个事务物理的完整性。
SQLServer提供:锁定设备,使事务相互隔离。
记录设备,保证事务的持久性。即使服务器硬件、操作系统或SQLServer自身出现故障,SQLServer也可以在重新启动时使用事务日志,将所有未完成的事务自动地回滚到系统出现故障的位置。
事务管理特
性,强制保持事务的原子性和一致性。事务启动之后,就必须成功完成,否则SQLServer将撤消该事务启动之后对数据所作的所有修改。
(三)控制事务:
应用程序主要通过指定事务启动和结束的时间来控制事务。这可以使用Transact-SQL语句或数据库API函数。系统还必须能够正确处理那些在事务完成之前便终止事务的错误。事务是在连接层进行管理。当事务在一个连接上启动时,在该连接上执行的所有的Transact-SQL语句在该事务结束之前都是该事务的一部分。
1、启动事务
在MicrosoftSQLServer中,可以按显式自动提交或隐性模式启动事务。
1)显式事务:通过发出BEGINTRANSACTION语句显式启动事务。
2)自动提交事务:这是SQLServer的默认模式。每个单独的Transact-SQL语句都在其完成后提交。不必指定任何语句控制事务。
3)隐性事务:通过API函数或Transact-SQLSETIMPLICIT_TRANSACTIONSON语句,将隐性事务模式设置为打开。下一个语句自动启动一个新事务。当该事务完成时,再下一个Transact-SQL语句又将启动一个新事务。
4)连接模式在连接层进行管理。如果一个连接从一种事务模式改变到另一种,那么它对任何其它连接的事务模式没有影响。
2、结束事务
可以使用COMMIT或ROLLBACK语句结束事务。
1)COMMIT:如果事务成功,则提交。COMMIT语句保证事务的所有修改在数据库中都永久有效。COMMIT语句还释放资源,如事务使用的锁。
2)ROLLBACK:如果事务中出现错误,或者用户决定取消事务,可回滚该事务。ROLLBACK语句通过将数据返回到它在事务开始时所处的状态,来恢复在该事务中所作的所有修改。ROLLBACK还会释放由事务占用的资源。
3、指定事务边界
可以用Transact-SQL语句或API函数和方法确定SQLServer事务启动和结束的时间。
1)Transact-SQL语句:使用BEGINTRANSACTION、COMMITTRANSACTION、COMMITWORK、ROLLBACKTRANSACTION、ROLLBACKWORK和SETIMPLICIT_TRANSACTIONS语句来描述事务。这些语句主要在DB-Library应用程序和Transact-SQL脚本(如使用osql命令提示实用工具运行的脚本)中使用。
2)API函数和方法:数据库API(如ODBC、OLEDB和ADO)包含用来描述事务的函数和方法。它们是SQLServer应用程序中用来控制事务的主要机制。
3)每个事务都必须只由其中的一种方法管理。在同一事务中使用两种方法可能导致不确定的结果。例如,不应先使用ODBCAPI函数启动一个事务,再使用Transact-SQLCOMMIT语句完成该事务。这样将无法通知SQLServerODBC驱动程序该事务已被提交。在这种情况下,应使用ODBCSQLEndTran函数结束该事务。
4、事务处理过程中的错误
1)如果
服务器错误使事务无法成功完成,SQLServer将自动回滚该事务,并释放该事务占用的所有资源。如果客户端与SQLServer的网络连接中断了,那么当网络告知SQLServer该中断时,将回滚该连接的所有未完成事务。如果客户端应用程序失败或客户计算机崩溃或重启,也会中断该连接,而且当网络告知SQLServer该中断时,也会回滚所有未完成的连接。如果客户从该应用程序注销,所有未完成的事务也会被回滚。
2)如果批处理中出现运行时语句错误(如违反约束),那么SQLServer中默认的行为将是只回滚产生该错误的语句。可以使用SETXACT_ABORT语句改变该行为。在SETXACT_ABORTON语句执行之后,任何运行时语句错误都将导致当前事务自动回滚。编译错误(如语法错误)不受SETXACT_ABORT的影响。
3)如果出现运行时错误或编译错误,那么程序员应该编写应用程序代码以便指定正确的操作(COMMIT或ROLLBACK)。
事务定义:
事务是单个的工作单元。如果某一事务成功,则在该事务中进行的所有数据更改均会
提交,成为数据库中的永久组成部分。如果事务遇到错误且必须取消或回滚,则所有
数据更改均被清除。
事务三种运行模式:
自动提交事务
每条单独的语句都是一个事务。
显式事务
每个事务均以BEGINTRANSACTION语句显式开始,
以COMMIT或ROLLBACK语句显式结束。
隐性事务
在前一个事务完成时新事务隐式启动,但每个事务仍以COMMIT或ROLLBACK语句
显式完成。
事务操作的语法:
BEGINTRANSACTION
BEGINDISTRIBUTEDTRANSACTION
COMMITTRANSACTION
COMMITWORK
ROLLBACKWORK
SAVETRANSACTION
BEGINTRANSACTION
BEGINTRANSACTION
标记一个显式本地事务的起始点。
BEGINTRANSACTION将@@TRANCOUNT加1。
BEGINTRANSACTION代表一点,由连接引用的数据在该点是逻辑和物理上都一致的。如果遇上错误,在BEGINTRANSACTION之后的所有数据改动都能进行回滚,以将数据返回到已知的一致状态。每个事务继续执行直到它无误地完成并且用COMMITTRANSACTION对数据库作永久的改动,或者遇上错误并且用ROLLBACKTRANSACTION语句擦除所有改动
语法
BEGINTRAN[SACTION][transaction_name|@tran_name_variable[WITHMARK['description']]]
例子:
BEGINTRANT1
UPDATEtable1...
--nesttransactionM2
BEGINTRANM2WITHMARK
UPDATEtable2...
SELECT*fromtable1
COMMITTRANM2
UPDATEtable3...
COMMITTRANT1
BEGINDISTRIBUTEDTRANSACTION
指定一个由Microsoft分布式事务处理协调器(MSDTC)管理的Transact-SQL分布式事务的起始。
语法
BEGINDISTRIBUTEDTRAN[SACTION]
[transaction_name|@tran_name_variable]
参数
transaction_name
是用户定义的事务名,用
于跟踪MSDTC实用工具中的分布式事务。transaction_name必须符合标识符规则,但是仅使用头32个字符
@tran_name_variable
是用户定义的一个变量名,它含有一个事务名,该事务名用于跟踪MSDTC实用工具中的分布式事务。必须用char、varchar、nchar或nvarchar数据类型声明该变量。
注释
执行BEGINDISTRIBUTEDTRANSACTION语句的服务器是事务创建人,并且控制事务的完成
当连接发出后续COMMITTRANSACTION或ROLLBACKTRANSACTION语句时,
主控服务器请求MSDTC在所涉及的服务器间管理分布式事务的完成。
有两个方法可将远程SQL服务器登记在一个分布式事务中:
分布式事务中已登记的连接执行一个远程存储过程调用,该调用引用一个远程服务器。
分布式事务中已登记的连接执行一个分布式查询,该查询引用一个远程服务器。
示例
本例在本地和远程数据库上更新作者的姓。本地和远程数据库将同时提交或同时回滚本事务。
说明
当前的SQLServer上必须安装MSDTC.
USEpubs
GO
BEGINDISTRIBUTEDTRANSACTION
UPDATEauthors
SETau_lname='McDonald'WHEREau_id='409-56-7008'
EXECUTElink_Server_T.pubs.dbo.changeauth_lname'409-56-7008','McDonald'
COMMITTRAN
GONote:
如果需要连接远程DB,如果是linkServer方式连接的话,一定要修该linkServer的RPC选项置为True。
SETXACT_ABORT
指定当Transact-SQL语句产生运行时错误时,Microsoft?SQLServer?是否自动回滚当前事务。
(可以比较简单的理解,如果中间有任何一句SQL出错,所有SQL全部回滚.特别适用于Procedure中间调用Procedure,如果第一个ProcedureOk,被调用的Procedure中间有错误,如果SETXACT_ABORT=false,则出错的部分回滚,其他部分提交,当然外部Procedure也提交。).
---在分布式Trans中一定要注意设置下面参数(XACT_ABORT)
语法SETXACT_ABORT{ON|OFF}
注释当SETXACT_ABORT为ON时,如果Transact-SQL语句产生运行时错误,整个事务将终止并回滚。为OFF时,只回滚产生错误的Transact-SQL语句,而事务将继续进行处理。编译错误(如语法错误)不受SETXACT_ABORT的影响。
对于大多数OLEDB提供程序(包括SQLServer),隐性或显式事务中的数据修改语句必须将XACT_ABORT设置为ON。
SETXACT_ABORT的设置是在执行或运行时设置,而不是在分析时设置。
示例下例导致在含有其它Transact-SQL语句的事务中发生违反外键错误。在第一个语句集中产生错误,但其它语句均成功执行且事务成功
提交。在第二个语句集中,SETXACT_ABORT设置为ON。这导致语句错误使批处理终止,并使事务回滚。
CREATETABLEt1(aintPRIMARYKEY)
CREATETABLEt2(aintREFERENCESt1(a))
GO
INSERTINTOt1
VALUES(1)
INSERTINTOt1VALUES(3)
INSERTINTOt1VALUES(4)
INSERTINTOt1VALUES(6)
GO
SETXACT_ABORTOFF
GO
BEGINTRAN
INSERTINTOt2VALUES(1)
INSERTINTOt2VALUES(2)/*Foreignkeyerror*/
INSERTINTOt2VALUES(3)
COMMITTRAN
GO
SETXACT_ABORTON
GO
BEGINTRAN
INSERTINTOt2VALUES(4)
INSERTINTOt2VALUES(5)/*Foreignkeyerror*/
INSERTINTOt2VALUES(6)
COMMITTRAN
GO
SAVETRANSACTION
在事务内设置保存点。
语法SAVETRAN[SACTION]{savepoint_name|@savepoint_variable}
参数savepoint_name
是指派给保存点的名称。保存点名称必须符合标识符规则,但只使用前32个字符。
@savepoint_variable
是用户定义的、含有有效保存点名称的变量的名称。
必须用char、varchar、nchar或nvarchar数据类型声明该变量。注释
用户可以在事务内设置保存点或标记。保存点定义如果有条件地取消事务的一部分,事务可以返回的位置。如果将事务回滚到保存点,则必须(如果需要,使用更多的Transact-SQL语句和COMMITTRANSACTION语句)继续完成事务,或者必须(通过将事务回滚到其起始点)完全取消事务。若要取消整个事务,请使用ROLLBACKTRA, NSACTIONtransaction_name格式。这将撤消事务的所有语句和过程。
Note:1:在由BEGINDISTRIBUTEDTRANSACTION显式启动或从本地事务升级而来的分布式事务中,不支持SAVETRANSACTION。
2:当事务开始时,将一直控制事务中所使用的资源直到事务完成(也就是锁定)。当将事务的一部分回滚到保存点时,将继续控制资源直到事务完成(或者回滚全部事务)。
例子:begintransaction
savetransactionA
insertintodemovalues('BB','Bterm')
rollbackTRANSACTIONA
createtabledemo2(namevarchar(10),ageint)
insertintodemo2(name,age)values('lis',1)
committransaction
ROLLBACKTRANSACTION
将显式事务或隐性事务回滚到事务的起点或事务内的某个保存点。
语法
ROLLBACK[TRAN[SACTION]
[transaction_name|@tran_name_variable|savepoint_name|@savepoint_variable]]
参数
transaction_name
是给BEGINTRANSACTION上的事务指派的名称。transaction_name必须符合标识符规则,但只使用事务名称的前32个字符。嵌套
事务时,transaction_name必须是来自最远的BEGINTRANSACTION语句的名称。
@tran_name_variable
是用户定义的、含有有效事务名称的变量的名称。必须用char、varchar、nchar或nvarchar数据类型声明该变量。
savepoint_name
是来自SAVETRANSACTION语句的savepoint_name。savepoint_name必须符合标识符规则。当条件回滚只影响事务的一部分时使用savepoint_name。
@savepoint_variable
是用户定义的、含有有效保存点名称的变量的名称。必须用char、varchar、nchar或nvarchar数据类型声明该变量。
注释
ROLLBACKTRANSACTION清除自事务的起点或到某个保存点所做的所有数据修改。ROLLBACK还释放由事务控制的资源。
不带savepoint_name和transaction_name的ROLLBACKTRANSACTION回滚到事务的起点。嵌套事务时,该语句将所有内层事务回滚到最远的BEGINTRANSACTION语句。在这两种情况下,ROLLBACKTRANSACTION均将@@TRANCOUNT系统函数减为0。ROLLBACK
TRANSACTIONsavepoint_name不减少@@TRANCOUNT。
Note:
ROLLBACKTRANSACTION语句若指定savepoint_name则不释放任何锁。
在由BEGINDISTRIBUTEDTRANSACTION显式启动或从本地事务升级而来的分布式事务中,ROLLBACKTRANSACTION不能
引用savepoint_name。在执行COMMITTRANSACTION语句后不能回滚事务。
在事务内允许有重复的保存点名称,但ROLLBACKTRANSACTION若使用重复的保存点名称,则只回滚到最近的使用该保存点名称的SAVETRANSACTION。
在存储过程中,不带savepoint_name和transaction_name的ROLLBACKTRANSACTION语句将所有语句回滚到最远的BEGINTRANSACTION。在存储过程中,ROLLBACKTRANSACTION语句使@@TRANCOUNT在触发器完成时的值不同于调用该存储过程时的@@TRANCOUNT值,并且生成一个信息。该信息不影响后面的处理。
如果在触发器中发出ROLLBACKTRANSACTION:将回滚对当前事务中的那一点所做的所有数据修改,包括触发器所做的修改。
触发器继续执行ROLLBACK语句之后的所有其余语句。如果这些语句中的任意语句修改数据,则不回滚这些修改。执行其余的语句不会激发嵌套触发器。在批处理中,不执行所有位于激发触发器的语句之后的语句。每次进入触发器,@@TRANCOUNT就增加1,即使在自动提交模式下也是如此。(系统将触发器视作隐性嵌套事务。)
在存储过程中,ROLLBACKTRANSACTION语句不影响调用该过程的批处理中的后续语句;
将执行批处理中的后续语句。在触发器中,ROLLBACKTRANSACTION语句终止含有激发触发器的语句的批处理;
不执行批处理中的后续语句。
ROLLBACKTRANSACTION语句不生成显示给用户的信息。如果在存储过程或触发器中需要警告,请使用RAISERROR或PRINT语句。RAISERROR是用于指出错误的首选语句。
ROLLBACK对游标的影响由下面三个规则定义:
当CURSOR_CLOSE_ON_COMMIT设置为ON时,ROLLBACK关闭但不释放所有打开的游标。
当CURSOR_CLOSE_ON_COMMIT设置为OFF时,ROLLBACK不影响任何打开的同步STATIC或INSENSITIVE游标不影响已完全填充的异步STATIC游标。将关闭但不释放任何其它类型的打开的游标。
对于导致终止批处理并生成内部回滚的错误,将释放在含有该错误语句的批处理内声明的所有游标。
不论游标的类型或CURSOR_CLOSE_ON_COMMIT的设置,所有
游标均将被释放,其中包括在该错误批处理所调用的存储过程内声明的游标。在该错误批处理之前的批处理内声明的游标以规则1和2为准。死锁错误就属于这类错误。在触发器中发出的ROLLBACK语句也自动生成这类错误。
权限
ROLLBACKTRANSACTION权限默认授予任何有效用户。
例子:
begintransaction
savetransactionA
insertintodemovalues('BB','Bterm')
rollbackTRANSACTIONA
--select*intodemo2fromdemo1
createtabledemo2(namevarchar(10),ageint)
insertintodemo2(name,age)values('lis',1)
rollbacktransaction
COMMITTRANSACTION
标志一个成功的隐性事务或用户定义事务的结束。如果@@TRANCOUNT为1,COMMIT
TRANSACTION使得自从事务开始以来所执行的所有数据修改成为数据库的永久部分,释放连接
占用的资源,并将@@TRANCOUNT减少到0。如果@@TRANCOUNT大于1,则COMMIT
TRANSACTION使@@TRANCOUNT按1递减。
只有当事务所引用的所有数据的逻辑都正确时,发出COMMITTRANSACTION命令。
COMMITWORK
标志事务的结束。
语法
COMMIT[WORK]
注释
此语句的功能与COMMITTRANSACTION相同,但COMMITTRANSACTION接受用户定义的事务
名称。这个指定或没有指定可选关键字WORK的COMMIT语法与SQL-92兼容
例子:
begintransactiona
insertintodemovalues('BB','Bterm')
commitTRANSACTIONA
隐性事务
当连接以隐性事务模式进行操作时,SQLServer将在提交或回滚当前事务后自动启动新事务。无须描述事务的开始,只需提交或
回滚每个事务。隐性事务模式生成连续的事务链。
在为连接将隐性事务模式设置为打开之后,当SQLServer首次执行下列任何语句时,都会自动启动一个事务:
ALTERTABLE
INSERT
CREATE
OPEN
DELETE
REVOKE
DROP
SELECT
FETCH
TRUNCATETABLE
GRANT
UPDATE
在发出COMMIT或ROLLBACK语句之前,该事务将一直保持有效。在第一个事务被提交或回滚之后,下次当连接执行这些语句
中的任何语句时,SQLServer都将自动启动一个新事务。SQLServer将不断地生成一个隐性事务链,
直到隐性事务模式关闭为止
例子:
begintransaction
savetransactionA
insertintodemovalues('BB','Bterm')
rollbackTRANSACTIONA
createtabledemo2(namevarchar(10),ageint)
insertintodemo2(name,age)values('lis',1)
rollbacktransaction
--在Createtabledemo2时SQLServer已经隐式创建一个Trans,知道提交或回滚
嵌套事务处理:
1:Trans嵌套,将内部的trans合并到外部并形成一个Trans.
begintrant1
----Inthefirsttrans.
Insertintodemo2(name,age)values('lis',1)
---SecondTransbegintransactiont2
insertintodemovalues('BB','Bterm')
committransactiont2
----In
thefirsttrans.
Insertintodemo2(name,age)values('lis',2)
rollbacktransactiont1
Note:
在一系列嵌套的事务中用一个事务名给多个事务命名对该事务没有什么影响。系统仅登记第一个(最外部的)事务名。回滚
到其它任何名字(有效的保存点名除外)都会产生错误。
事实上,任何在回滚之前执行的语句都没有在错误发生时回滚。这语句仅当外层的事务回滚时才会进行回滚。
例:内部事务回滚SQLserver报错。
begintrant1
Insertintodemo2(name,age)values('lis',1)
---SecondTrans
--Server:Msg6401,Level16,State1,Line6
---Cannotrollbackt2.Notransactionorsavepointofthatnamewasfound.
begintransactiont2
insertintodemovalues('BB','Bterm')
rollbacktransactiont2
----Inthefirsttrans.
Insertintodemo2(name,age)values('lis',2)
committransactiont1
例:内部事务提交SQLserver不会报错。
begintrant1
Insertintodemo2(name,age)values('lis',1)
---SecondTransnoerror
begintransactiont2
insertintodemovalues('BB','Bterm')
committransactiont2
----Inthefirsttrans.
Insertintodemo2(name,age)values('lis',2)
committransactiont1
SQLServer的隔离级别:
1:设置TimeOut参数
SetLock_TimeOut5000
被锁超时5秒将自动解锁
SetLock_TimeOut0
产立即解锁,返回Error默认为-1,无限等待
2:
(SETTRANSACTIONISOLATIONLEVEL
{READCOMMITTED
|READUNCOMMITTED
|REPEATABLEREAD|SERIALIZABLE})
READCOMMITTED
指定在读取数据时控制共享锁以避免脏读,但数据可在事务结束前更改,从而产生不可重复读取或
幻像数据。该选项是SQLServer的默认值。
避免脏读,并在其他session在事务中不能对已有数据进行修改。共享锁。
READUNCOMMITTED
执行脏读或0级隔离锁定,这表示不发出共享锁,也不接受排它锁。当设置该选项时,可以对数
据执行未提交读或脏读;在事务结束前可以更改数据内的数值,行也可以出现在数据集中或从数据
集消失。该选项的作用与在事务内所有语句中的所有表上设置NOLOCK相同。这是四个隔离级别中
限制最小的级别。
REPEATABLEREAD
锁定查询中使用的所有数据以防止其他用户更新数据,但是其他用户可以将新的幻像行插入数据
集,且幻像行包括在当前事务的后续读取中。因为并发低于默认隔离级别,所以应只在必要时才使
用该选项。
SERIALIZABLE
在数据集上放置一个范围锁,以防止其他用户在事务完成之前更新数据集或将行插入数据集内。这
是四个隔离级别中限制最大的级别。因为并发级别较低,所以应只在必要时才使用该选项。该选项
的作用与在事务内所有SELECT语句中的所有表上设置HOLDLOCK相同。
六、触发器。
定义:何为触发器?在SQLServer里面也就是对某一个表的一定的操作,触发某种条件,从而执行的一段程序。触发器是一个特殊的存储过程。
常见的触发器有三种:分别应用于Insert,Update,Delete事件。(SQLServer2000定义了新的触发器,这里不提)
我为什么要使用触发器?比如,这么两个表:
CreateTableStudent(--学生表
StudentIDintprimarykey,--
....
)
CreateTableBorrowRecord(--学生借书记录表
BorrowRecordintidentity(1,1),--流水号
StudentIDint,--
BorrowDatedatetime,--借出时间
ReturnDAteDatetime,--归还时间
...
)
用到的功能有:
1.如果我更改了学生的,我希望他的借书记录仍然与这个学生相关(也就是同时更改借书记录表的);
2.如果该学生已经毕业,我希望删除他的的同时,也删除它的借书记录。
等等。
这时候可以用到触发器。对于1,创建一个Update触发器:
CreateTriggertruStudent
OnStudent
forUpdate
As
ifUpdate(StudentID)
begin
UpdateBorrowRecord
SetStudentID=i.StudentID
FromBorrowRecordbr,Deletedd,Insertedi
Wherebr.StudentID=d.StudentID
end
理解触发器里面的两个临时的表:Deleted,Inserted。注意Deleted与Inserted分别表示触发事件的表“旧的一条记录”和“新的一条记录”。
一个Update的过程可以看作为:生成新的记录到Inserted表,复制旧的记录到Deleted表,然后删除Student记录并写入新纪录。
对于2,创建一个Delete触发器
CreatetriggertrdStudent
OnStudent
forDelete
As
DeleteBorrowRecord
FromBorrowRecordbr,Deltedd
Wherebr.StudentID=d.StudentID
从这两个例子我们可以看到了触发器的关键:A.2个临时的表;B.触发机制。
这里我们只讲解最简单的触发器。复杂的容后说明。
事实上,我不鼓励使用触发器。触发器的初始设计思想,已经被“级联”所替代
七、存储过程
将常用的或很复杂的工作,预先用SQL语句写好并用一个指定的名称存储起来,那么以后要叫数据库提供与已定义好的存储过程的功能相同的服务时,只需调用execute,即可自动完成命令。
(一)存储过程的优点:
1.存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译,而一般SQL语句每执行一次就编译一次,所以使用存储过程可提高数据库执行速度。
2.当对数据库
进行复杂操作时(如对多个表进行Update,Insert,Query,Delete时),可将此复杂操作用存储过程封装起来与数据库提供的事务处理结合一起使用。
3.存储过程可以重复使用,可减少数据库开发人员的工作量
4.安全性高,可设定只有某此用户才具有对指定存储过程的使用权
(二)创建存储过程语法格式:
CREATEPROC[EDURE][owner.]procedure_name[;number]
[{@parameterdata_type}
[VARYING][=default][OUTPUT]
][,...n]
[WITH
{RECOMPILE|ENCRYPTION|RECOMPILE,ENCRYPTION}]
[FORREPLICATION]
ASsql_statement[...n]
参数
owner
拥有存储过程的用户ID的名称。owner必须是当前用户的名称或当前用户所属的角色的名称。
procedure_name
新存储过程的名称。过程名必须符合标识符规则,且对于数据库及其所有者必须唯一。
;number
是可选的整数,用来对同名的过程分组,以便用一条DROPPROCEDURE语句即可将同组的过程一起除去。例如,名为orders的应用程序使用的过程可以命名为orderproc;1、orderproc;2等。DROPPROCEDUREorderproc语句将除去整个组。如果名称中包含定界标识符,则数字不应包含在标识符中,只应在procedure_name前后使用适当的定界符。
@parameter
过程中的参数。在CREATEPROCEDURE语句中可以声明一个或多个参数。用户必须在执行过程时提供每个所声明参数的值(除非定义了该参数的默认值,或者该值设置为等于另一个参数)。存储过程最多可以有2.100个参数。
使用@符号作为第一个字符来指定参数名称。参数名称必须符合标识符的规则。每个过程的参数仅用于该过程本身;相同的参数名称可以用在其它过程中。默认情况下,参数只能代替常量,而不能用于代替表名、列名或其它数据库对象的名称。
data_type
参数的数据类型。除table之外的其他所有数据类型均可以用作存储过程的参数。但是,cursor数据类型只能用于OUTPUT参数。如果指定cursor数据类型,则还必须指定VARYING和OUTPUT关键字。对于可以是cursor数据类型的输出参数,没有最大数目的限制。
VARYING
指定作为输出参数支持的结果集(由存储过程动态构造,内容可以变化)。仅适用于游标参数。
default
参数的默认值。如果定义了默认值,不必指定该参数的值即可执行过程。默认值必须是常量或NULL。如果过程将对该参数使用LIKE关键字,那么默认值中可以包含通配符(%、_、[]和[^])。
OUTPUT
表明参数是返回参数。该选项的值可以返回给EXEC[UTE]。使用OUTPUT参数可将信息返回给调用过程。Text、ntext和image参数可用作OUTPUT参
数。使用OUTPUT关键字的输出参数可以是游标占位符。
n
表示最多可以指定2.100个参数的占位符。
{RECOMPILE|ENCRYPTION|RECOMPILE,ENCRYPTION}
RECOMPILE表明SQLServer不会缓存该过程的计划,该过程将在运行时重新编译。在使用非典型值或临时值而不希望覆盖缓存在内存中的执行计划时,请使用RECOMPILE选项。
ENCRYPTION表示SQLServer加密syscomments表中包含CREATEPROCEDURE语句文本的条目。使用ENCRYPTION可防止将过程作为SQLServer复制的一部分发布。
FORREPLICATION
指定不能在订阅服务器上执行为复制创建的存储过程。.使用FORREPLICATION选项创建的存储过程可用作存储过程筛选,且只能在复制过程中执行。本选项不能和WITHRECOMPILE选项一起使用。
AS
指定过程要执行的操作。
sql_statement
过程中要包含的任意数目和类型的Transact-SQL语句。但有一些限制。
n
是表示此过程可以包含多条Transact-SQL语句的占位符。
(三)存储过程设计与功能
1、设计存储过程
几乎任何可写成批处理的Transact-SQL代码都可用于创建存储过程。
2、存储过程的设计规则
存储过程的设计规则包括:
CREATEPROCEDURE定义本身可包括除下列CREATE语句以外的任何数量和类型的SQL语句,存储过程中的任意地方都不能使用下列语句:CREATEDEFAULT;CREATETRIGGER;CREATEPROCEDURE;CREATEVIEW;CREATERULE
可在存储过程中创建其它数据库对象。可以引用在同一存储过程中创建的对象,前提是在创建对象后再引用对象。
可以在存储过程内引用临时表。
如果在存储过程内创建本地临时表,则该临时表仅为该存储过程而存在;退出该存储过程后,临时表即会消失。
如果执行调用其它存储过程的存储过程,那么被调用存储过程可以访问由第一个存储过程创建的、包括临时表在内的所有对象。
如果执行在远程Microsoft?SQLServer?2000实例上进行更改的远程存储过程,则不能回滚这些更改。远程存储过程不参与事务处理。
存储过程中参数的最大数目为2100。
存储过程中局部变量的最大数目仅受可用内存的限制。
根据可用内存的不同,存储过程的最大大小可达128MB。
3、限定存储过程内的名称
在存储过程内部,如果用于诸如SELECT或INSERT这样的语句的对象名没有限定用户,那么用户将默认为该存储过程的所有者。在存储过程内部,如果创建存储过程的用户没有限定SELECT、INSERT、UPDATE或DELETE语句中引用的表名,那么通过该存储过程对这些表进行的访问将默认地受到该过程的创建者权限的限制。
如果有其他用户要使用存储
过程,则用于语句ALTERTABLE、CREATETABLE、DROPTABLE、TRUNCATETABLE、CREATEINDEX、DROPINDEX、UPDATESTATISTICS和DBCC的对象名必须用该对象所有者的名称限定。例如,Mary拥有表marytab,如果她希望其他用户能够执行使用该表的存储过程,必须在该表用于上述某一条语句时对其表名进行限定。
此规则是必需的,因为运行存储过程时将解析对象的名称。如果未限定marytab,而John试图执行该过程,SQLServer将查找John所拥有的名为marytab的表。
4、加密过程定义
如果要创建存储过程,并且希望确保其他用户无法查看该过程的定义,那么可以使用WITHENCRYPTION子句。这样,过程定义将以不可读的形式存储。
存储过程一旦加密其定义即无法解密,任何人(包括存储过程的所有者或系统管理员)都将无法查看存储过程定义。
5、SET语句选项
当ODBC应用程序与SQLServer连接时,服务器将自动设置会话的下列选项:
SETQUOTED_IDENTIFIERON
SETTEXTSIZE2147483647
SETANSI_DEFAULTSON
SETCURSOR_CLOSE_ON_COMMITOFF
SETIMPLICIT_TRANSACTIONSOFF
这些设置将提高ODBC应用程序的可移植性。由于基于DB-Library的应用程序通常不设置这些选项,所以应在上述所列SET选项打开和关闭的情况下都对存储过程进行测试。这样可确保存储过程始终能正确工作,而不管特定的连接在唤醒调用该存储过程时可能设置的选项。需要特别设置其中一个选项的存储过程,应在开始该存储过程时发出一条SET语句。此SET语句将只对该存储过程的执行保持有效,当该存储过程结束时,将恢复原设置。
(四)示例
A.创建使用参数的存储过程
下例创建一个在pubs数据库中很有用的存储过程。给出一个作者的姓和名,该存储过程将显示该作者的每本书的标题和出版商。
CREATEPROCau_info@lastnamevarchar(40),@firstnamevarchar(20)
AS
SELECTau_lname,au_fname,title,pub_name
FROMauthorsINNERJOINtitleauthorONauthors.au_id=titleauthor.au_id
JOINtitlesONtitleauthor.title_id=titles.title_id
JOINpublishersONtitles.pub_id=publishers.pub_id
WHEREau_fname=@firstname
ANDau_lname=@lastname
GO
将出现一条说明该命令未返回任何数据也未返回任何行的消息,这表示已创建该存储过程。
现在执行au_info存储过程:
EXECUTEau_infoRinger,Anne
GO
下面是结果集:
au_lnameau_fnametitlepub_name
-------------------------------------------------------
RingerAnneTheGourmetMicrowaveBinnet&;Hardley
RingerAnneIsAngertheEnemy?NewMoonBooks
(2row(s)affected)
B.创建使用参数默认值的存储过程
下例创建一个存储过程p
ub_info2,该存储过程显示作为参数给出的出版商所出版的某本书的作者。如果未提供出版商的名称,该存储过程将显示由AlgodataInfosystems出版的书籍的作者。
CREATEPROCpub_info2@pubnamevarchar(40)='AlgodataInfosystems'ASSELECTau_lname,au_fname,pub_nameFROMauthorsaINNERJOINtitleauthortaONa.au_id=ta.au_idJOINtitlestONta.title_id=t.title_idJOINpublisherspONt.pub_id=p.pub_idWHERE@pubname=p.pub_name
执行未指定参数的pub_info2:
EXECUTEpub_info2
GO
下面是结果集:
au_lnameau_fnamepub_name
------------------------------------------
GreenMarjorieAlgodataInfosystems
BennetAbrahamAlgodataInfosystems
O'LearyMichaelAlgodataInfosystems
MacFeatherStearnsAlgodataInfosystems
StraightDeanAlgodataInfosystems
CarsonCherylAlgodataInfosystems
DullAnnAlgodataInfosystems
HunterSherylAlgodataInfosystems
LocksleyCharleneAlgodataInfosystems
(9row(s)affected)
C.执行用显式值替代参数默认值的存储过程
在下例中,存储过程showind2的@table参数默认值是titles。
CREATEPROCshowind2@tablevarchar(30)='titles'ASSELECTTABLE_NAME=sysobjects.name,INDEX_NAME=sysindexes.name,INDEX_ID=indidFROMsysindexesINNERJOINsysobjectsONsysobjects.id=sysindexes.idWHEREsysobjects.name=@table
列标题(例如,TABLE_NAME)可使结果更具可读性。下面是该存储过程显示的authors表的情况:
EXECUTEshowind2authors
GO
TABLE_NAMEINDEX_NAMEINDEX_ID
------------------------------
authorsUPKCL_auidind1
authorsaunmind2
(2row(s)affected)
如果用户未提供值,则SQLServer将使用默认表titles:
EXECUTEshowind2
GO
下面是结果集:
TABLE_NAMEINDEX_NAMEINDEX_ID
------------------------------
titlesUPKCL_titleidind1
titlestitleind2
(2row(s)affected)
D.使用参数默认值NULL创建存储过程
参数默认值可以是NULL值。在这种情况下,如果未提供参数,则SQLServer将根据存储过程的其它语句执行存储过程。不会显示错误信息。
过程定义还可指定当不给出参数时要采取的其它某种措施。例如:
CREATEPROCshowind3@tablevarchar(30)=NULLASIF@tableISNULLPRINT'Giveatablename'ELSESELECTTABLE_NAME=sysobjects.name,INDEX_NAME=sysindexes.name,INDEX_ID=indidFROMsysindexesINNERJOINsysobjectsONsysobjects.id=sysindexes.idWHEREsysobjects.name=@table
E.使用包含通配符的参数默认值创建存储过程
如果存储过程将参数用于LIKE关键字,那么默认值可包括通配符(%、_、[]和[^])。例如,可将showind修改为当
不提供参数时显示有关系统表的信息:
CREATEPROCshowind4@tablevarchar(30)='sys%'ASSELECTTABLE_NAME=sysobjects.name,INDEX_NAME=sysindexes.name,INDEX_ID=indidFROMsysindexesINNERJOINsysobjectsONsysobjects.id=sysindexes.idWHEREsysobjects.nameLIKE@table
在存储过程au_info的下列变化形式中,两个参数都有带通配符的默认值:
CREATEPROCau_info2@lastnamevarchar(30)='D%',@firstnamevarchar(18)='%'ASSELECTau_lname,au_fname,title,pub_nameFROMauthorsINNERJOINtitleauthorONauthors.au_id=titleauthor.au_idJOINtitlesONtitleauthor.title_id=titles.title_idJOINpublishersONtitles.pub_id=publishers.pub_idWHEREau_fnameLIKE@firstnameANDau_lnameLIKE@lastname
如果执行au_info2时不指定参数,将显示姓以字母D开头的所有作者:
EXECUTEau_info2
GO
下面是结果集:
au_lnameau_fnametitlepub_name
--------------------------------------------------------
DullAnnSecretsofSiliconValAlgodataInfosystems
delCastilloInnesSiliconValGastronoBinnet&;Hardley
DeFranceMichelTheGourmetMicrowaveBinnet&;Hardley
(3row(s)affected)
下例在两个参数的默认值已定义的情况下,省略了第二个参数,因此可找到姓为Ringer的所有作者的书和出版商:
EXECUTEau_info2Ringer
GO
au_lnameau_fnametitlepub_name
--------------------------------------------------------
RingerAnneTheGourmetMicrowaveBinnet&;Hardley
RingerAnneIsAngertheEnemy?NewMoonBooks
RingerAlbertIsAngertheEnemy?NewMoonBooks
RingerAlbertLifeWithoutFearNewMoonBooks
(4row(s)affected)
几个实例
(AjaxCity表中内容)
IDCityNameShort
1苏州市SZ
2无锡市WX
3常州市CZ
1.选择表中所有内容并返回一个数据集
CREATEPROCEDUREmysp_All
AS
select*fromAjaxCity
GO
执行结果
2.根据传入的参数进行查询并返回一个数据集
CREATEPROCEDUREmysp_para
@CityNamevarchar(255),
@Shortvarchar(255)
AS
select*fromAjaxCitywhereCityName=@CityNameAndShort=@Short
GO
执行结果
3.带有输出参数的存储过程(返回前两条记录的ID的和)
CREATEPROCEDUREmysp_output
@SUMintoutput
AS
select@SUM=sum([ID])from(selecttop2*fromAjaxCity)astmpTable
GO
执行结果
4.在存储过程中使用游标
现在想统计出各个地级市下面的县级市的个数,并组成一个字符串.
结果应该是"5,2,2".
CREATEPROCEDUREmysp_Cursor
@Resultvarchar(255)output//声明输出变量
AS
declarecity_cursorcursorfor//声明游标变量
select[ID]fromAjaxCity
set@Result=''
declare@Fieldint//声明临时存放CityID的变量
opencity_cursor//打开游标
fetchnextfromcity_cursorinto@Field//将实际ID赋给变量
while(@@fetch_status=0)//循环开始
begin
if@Result=''
select@Result=convert(nvarchar(2),count(*))fromAjaxCountywhereCityID=@Field
else
select@Result=@Result+','+convert(nvarchar(2),count(*))fromAjaxCountywhereCityID=@Field
fetchnextfromcity_cursorinto@Field//下一个CityID
end
closecity_cursor//关闭游标
deallocatecity_cursor//释放游标引用
GO
执行结果
存储过程的结构跟其他编程语言非常相似。存储过程接受输入参数形式的数据。这些输入参数在执行系列语句的时候被运用并生成结果。结果在通过使用记录集、输出参数和返回代码返回。听起来似乎很复杂,实际上存储程序非常简单。
实例
假设我们有如下名为Inventory的表格,表格里的数据需要实时更新,仓库经理会不停地检查仓库里的货存数量和可供发货的货存数量。以前,每一个地区的仓库经理都会进行如下查询:
以下是引用片段:
SELECTProduct,Quantity
FROMInventory
WHEREWarehouse='FL'
这样的查询使SQLServer性能效率非常低下。每次仓库经理执行该查询,数据库服务器都不得不重新对其进行编译然后重新开始执行。这样的查询还要求仓库经理具备SQL方面的知识,并且拥有访问表格数据的权限。
我们可以通过使用存储过程来简化这个查询过程。首先创建一个名为sp_GetInventory的过程,能够获取一个已有仓库的货存水平。下面是创建该程序的SQL代码:
以下是引用片段:
CREATEPROCEDUREsp_GetInventory
@locationvarchar(10)
AS
SELECTProduct,Quantity
FROMInventory
WHEREWarehouse=@location
A地区的仓库经理可以执行下面的命令来获得货存水平:
以下是引用片段:
EXECUTEsp_GetInventory'FL'
B地区的仓库经理可以使用同样的存储过程来访问该地区的货存信息。
以下是引用片段:
EXECUTEsp_GetInventory'NY'
当然,这只是一个很简单的例子,但是可以看出来存储过程的好处。仓库经理不一定要懂得SQL或者存储过程内在的工作原理。从性能的角度看的话,存储过程无疑大大地提高了工作的效率。SQLServer只需创建执行计划一次,然后就可以重复使用存储过程,只需要在每次执行时输入适当的参数就可以了。
货
存表格Inventory:
IDProductWarehouseQuantity
142GreenbeansNY100
214PeasFL200
825CornNY140
512LimabeansNY180
491TomatoesFL80
379WatermelonFL85