网站导航网学 原创论文 原创专题 网站设计 最新系统 原创论文 论文降重 发表论文 论文发表 UI设计定制 论文答辩PPT格式排版 期刊发表 论文专题
返回网学首页
网学原创论文
最新论文 推荐专题 热门论文 论文专题
当前位置: 网学 > 交易代码 > SQL语法 > 正文

sqlserver2008R2数据库编程学习资料强荐

论文降重修改服务、格式排版等 获取论文 论文降重及排版 论文发表 相关服务

【网学网提醒】:网学会员鉴于大家对十分关注,论文会员在此为大家搜集整理了“sqlserver2008R2数据库编程学习资料强荐”一文,供大家参考学习


    用Transact-SQL编程
    Transact-SQL(简称T-SQL)是ANSI标准SQL数据库查询语言的一个强大实现,是一种数据定义、操作和控制语言。Transact-SQL是SQLServer编程的重要工具,也是SQLserver编程的基础。无论是数据库管理员还是数据库程序设计员,都必须熟练掌握该语言,以进行数据库设计、维护和编程,与SQLServer进行交互工作,从而构建高效的数据库应用程序。本章将介绍T-SQL编程语言,及其语法元素和语句类型。同时,也将介绍通过T-SQL编程管理数据库事务,来实现维护数据库的一致性和完整性的目的;通过T-SQL编程创建锁,以解决发生事务并发问题等高级编程操作。本章学习目标学习目标:本章学习目标:了解T-SQL语言类型掌握T-SQL编程语法熟悉PIVOT和UNPIVOT操作符的使用掌握事务的概念及其运用了解事务产生的并发问题了解锁模式及如何查看锁掌握游标的声明及使用
    4.1Transact-SQL概述
    Transact-SQL语言是一种交互查询语言,具有功能强大、简单易学的特点。该语言是结构化查询语言(SQL)的增强版本,与多种ANSISQL标准兼容,而且在标准的基础上还进行了许多扩展。
    4.1.1
    Transact-SQL语言与SQL语言
    Transact-SQL语言是微软公司对SQL语言的扩展。不同的数据库供应商一方面采纳SQL语言作为自己数据库的操作语言,另一方面又对SQL语言进行不同程度的扩展,而这些扩展往往又是SQL语言的下一个版本的主要实践来源。接下来,我们先来对SQL语言进行简单的介绍。SQLStructureQueryLanguage,(机构化查询语言)是国际标准化组织(ISO)
     采纳的标准数据库语言。该语言是由美国国际标准协会(ANSI)和国际标准化组织(ISO)定义的标准,Transact-SQL是Microsoft公司对此标准的一个实现。Transact-SQL语言既允许用户直接查询存储在数据库中的数据,也可以把语句嵌入到某种高级程序设计语言中来使用,例如可以嵌套到MicrosoftVisualC#.NET语言中。Transact-SQL在关系数据库管理系统中,可以实现数据的检索、操纵和添加等功能,它同其他程序设计语言一样,有自己的数据类型、表达式、关键字等。当然,该语言与其他语言相比,要简单得多,主要有如下4个特点。
    一体化Transact-SQL语言集数据定义语言、数据操纵语言、数据控制语言元素为一体。其中,附加语言元素不是标准SQL语言的内容,但是它增加了用户对数据库操纵的灵活性和简便性,从而增强了程序的功能。使用方式Transact-SQL语言有两种使用方式,即交互使用和嵌入高级语言使用。统一的语法结构使Transact-SQL语言可用于所有用户的数据库活动模
    型,包括系统管理员、应用程序员、决策支持系统管理人员以及许多其他类型的终端用户。非过程化语言Transact-SQL语言只需要提出“干什么”,不需要指出“如何
    干”,语言的操作过程有系统自动完成。另外,Transact-SQL语言不要求用户指定对数据的存储方法,所有的Transact-SQL语句都使用查询优化器,用以指定数据以最快速度存取手段。人性化Transact-SQL语言继承SQL语言易学易用的特点,并符合人们的思
    维方式,因此非常容易理解和掌握。
    4.1.2
    Transact-SQL语言类型
    在SQLServer2008系统中,Transact-SQL可以创建、维护、保护数据库对象,并且可以操作对象中的数据,所以Transact-SQL语言是一种完整的语言。根据Transact-SQL语言的执行功能特点,可以将Transact-SQL语言分为三种类型:数据定义语言、数据操纵语言和数据控制语言。1.数据定义语言.数据定义语言(DataDefinitionLanguage,DDL)是T-SQL中最基本的语言类型,它用于创建数据库和各种数据库对象,如表、视图、存储过程等。创建了数据库对象后,才可能为其他语言的操作提供所要使用的对象。在数据定义语言中,主要的T-SQL语言包括CREATE语句、ALTER语句和DROP语句。CREATE语句用来创建数据库及各种数据库对象;ALTER语句用来修改数据库及其他数据库对象;DROP语句则用来删除数据库及数据库对象。
     2.数据操纵语言.数据操纵语言(DataManipulationLanguage,DML)是用来操纵数据库中的数据语句。当使用数据定义语言创建了数据库及表后,使用数据操纵语言便可以实现在表中查询、插入、更新、删除数据等操纵。数据操纵语言主要包括的语句有:SELECT语句、INSERT语句、UPDATE语句、DELETE语句、CURSOR语句等。3.数据控制语言.数据控制语言(DataControlLanguage,DCL)是用来确保数据库安全的一系列语句。例如,给不同的用户设置不同的权限,访问并使用不同的数据内容。数据控制语言就是用于控制数据库组件的存取许可、存取权限等以解决涉及到权限管理的问题,其主要包括GRANT、REVOKE、DENY等语句。GRANY语句可以将指定的安全对象的权限授予相应的主体,REVOKE语句则删除授予的权限,DENY语句拒绝授予主体权限,并且防止主体通过组或角色成员继承权限。另外,除了上面T-SQL语言的三种基本类型外,还有三种常用的类型:事务管理语言、流程控制语言和附加的语言元素。在数据库中执行操纵时,经常需要多个操作同时完成或者同时取消。例如,两个帐号之间的转帐操作,必须保证款项从一个帐号转出的同时,进入到另一个帐号中。如果在操作
    过程中一方取消转移,那么两边应该同时撤销操作。事务便是可以实现操作同时完成或同时取消的操作。在事务中的操作要么全部完成,要么全部失败。而用于事务管理的语句就是事务管理语言。在事务管理语言中,COMMIT语句用于提交事务;ROLLBACK语句用于回滚操作,即撤销执行操作。流程控制语言是用于设计应用程序的语句,IF、如WHILE、CASE语句等。Transact-SQL附加语言元素不是SQL的标准内容,而是Transact-SQL语言为了编程方便而增加的语言元素。这些语言元素包括变量、运算符、函数、流程控制语句和注释等内容。
    4.2
    编程基础
    Transact-SQL语言是一系列操作数据库及数据库对象的命令语句,因此了解基本语法和流程语句的构成是必须的,这主要包括常量和变量、运算符、表达式、注释等。
     4.2.1
    常量与变量
    在任何语言中,最不可少的便是常量和变量,它们是语言编程的基础元素。常量,也称为文字值或标量值,是指程序运行中值不变的量,用于表示特定数据值的符号,根据代表的数据类型不同,值也就不同,可以是日期型、数值型、字符串型等。在表4-1列出了SQLServer2008中可用的常量类型及常量的表示说明。表4-1常量类型及说明
    常量类型字符串常量常量表示说明包括在单引号或双引号中,由字母数(a-z、A-Z)、数字字符(0-9)以及特殊字符(如感叹号(!)、at符(@)和数字号(#))组成二进制常量只有0或者1构成的串,并且不使用引号。如果使用一个大于1的数字,他将被转换为1十进制整型常量十六进制整型常量日期常量实型常量货币常量使用单引号将日期时间字符串括起来组成有定点表示和浮点表示两种方式以前缀为可选的小数点和可选的货币符号的数字字符串来表示使用不带小数点的十进制数据表示使用前缀0X后跟十六进制数字串表示
    变量,就是在脚本中没有固定值的元素对象。MicrosoftSQLServer2008在系统中,存在两种类型的变量。第一种是系统定义和维护的全局变量;第二种是用户定义用来保存中间结果的局部变量。1.系统全局变量.系统全局变量是SQLServer系统提供并赋值的变量。用户不能建立全局变量,也不能用SET语句来修改全局变量的值。通常将全局变量的值赋给局部变量,以便保存和处理。全局变量以两个@符号开头。例如,可以使用全局变量@@VERSION查看当前使用的SQLServer的版本信息,语句如下所示:
    SELECT@@VERSIONAS[当前SQLServer版本]
    在查询窗口中执行上述语句,如图4-1所示。
     图4-1使用全局变量2.局部变量.局部变量是作用域局限在一定范围内
    的Transact-SQL对象。在SQLServer中,局部变量是用户自定义的,可以保存单个特定类型数据值对象。通常情况下,局部变量在一个批处理(也可以是存储过程或触发器)中被声明或定义,然后该批处理内的SQL语句就可以设置这个变量的值,或者是引用这个变量已经被赋予的值。当这个批处理结束后,这个局部变量的生命周期也就随之消失。要创建局部变量,使用DECLARE语句,其语法如下:
    DECLARE{@local_variabledata_type|@cursor_variableCURSOR}[,…n]
    主要参数说明如下:
    @local_variabledata_type是变量的名称,他必须以@开发。是任何由系统提供的或用户定义的数据类型。变量不能是text、ntext
    或image数据类型。table_type_definition和CHECK。n表示可以指定多个变量并对变量赋值的占位符。当声明表变量时,表变量必须是DECLARE语句中正在声明的变量。用于定义表数据类型。表声明包括列定义、名称、数据类型和约束。允许的约束类型只包括PRIMARYKEY、UNIQUEKEY、NULL
    声明局部变量后要给局部变量赋值,可以使用SET或SELECT语句:
    SET@local_variable=expressionSELECT@local_variable=expression[,…n]
    其中,@local_variable是除cursor、text、ntext、image外的任何类型变量名;expression是任何有效的SQLServer表达式。SELECT@lacol_variable通常用于将单个值返回到变量中,如果expres
     sion为列名,则返回多个。如果SELECT语句返回多个值,将返回的最后一个值赋予变量。如果SELECT语句没有返回行,变量将保留当前值。如果expression是不返回值的子查询,则将变量设为NULL。因此,通常情况下使用SET而不是SELECT给变量赋值。例如,将局部变量hello声明为char类型,长度为20,并为其赋值为hello,world!其SQL语句如下:
    DECLARE@hellochar(20)
    SET@hello='hello,world!'
    4.2.2
    运算符
    运算符实现运算功能,用来指定在一个或多个表达式中执行操作的符号,以产生新的结果。在SQLServer2008中,运算符可以分为:算术运算符、赋值运算符、位运算符、比较运算符、逻辑运算符、字符串连接运算符和一元运算符。1.算术运算符算术运算符是用于对两个表达式进行数学运算的运算符,一般得到的结果是数值型。表4-2列出了SQLServer中的主要算术运算符。表4-2算术运算符
    运算符+*/%加法运算减法运算乘法运算除法运算,如果两个表达式值都是整数,那么结果只取整数值,小数值将略去取模运算,返回两数相除后的余数说明
    例如下列T-SQL数学运算语句所示:
    SELECT2.5+5.6'加'SELECT5.9-1'减'SELECT2.0*5.0'浮点型乘'SELECT2*5'整数乘'SELECT10.0/15.0'浮点型除'SELECT10/15'整数
    除'SELECT90/16'取模'
    在查询管理器中执行上述语句,运行结果如图4-2所示。
     图4-2执行数学运算的结果从上面执行的结果中可以看到,浮点型数值和整数型数值的乘除法运算得到的结果并不相同,这时因为,有浮点型数值的运算结果的类型是浮点型,而整数型数值运算结果的类型是整数,所以,整数型乘除只保留整数。2.赋值运算符在Transact-SQL语言中,赋值运算符只有等号“=”一个。赋值运算符有两个主要的用途:第一个是给变量赋值,如下语句所示。
    DECLARE@URLvarchar(20)SET@URL='baidu'
    第二个是在WHERE子句中提供查询条件,如下语句所示:
    SELECT*FROM学生信息WHERE籍贯='上海'
    3.位运算符位运算符在两个表达式之间执行位操作,这两个表达式可以是任意两个整数数据类型的表达式。位运算符的符号及其定义如表4-3所示。表4-3位运算符
    运算符&;描述位与逻辑运算,从两个表达式中取对应的位。当且仅当输入表达式中两个位的值都为1时,结果中的位才被设置为1,否则,结果中的位被设置为0|位或逻辑运算,从两个表达式中取对应的位。如果输入表达式中两个位只要有一个的值为1时,结果的位就被设置为1,只有当两个位的值都为0时,结果中的位才被设置为0
     ^
    位异或运算,从两个表达式中取对应的位。如果输入表达式中两个位只有一个的值为1时,结果中的位就被设置为1;只有当两个位的值都为0或1时,结果中的位才被设置为0
    例如,下列语句分别计算2与51的位与、位或、位异或的运算结果。
    SELECT5&;51'位与'SELECT5|51'位或'SELECT5^51'位异或'
    执行该语句,运算结果如图4-3所示。
    图4-3执行位运算符的结果在位与运算中,5的二进制值为0000000000000101,51的二进制值为0000000000110011。根据位与运算规则,当且仅当输入的表达式中两个位的值都为1时,结果中的位才被设置为1;否则,结果中的位被设置为0。那么,5与51的位与逻辑运算值为0000000000000001,而二进制为0000000000000001的十进制值就是1。4.比较运算符比较运算符用来测试两个表达式是否相同。除了text、ntext或image数据类型的表达式外,比较运算符可以用于所有的表达式。比较运算符的符号及其表达式如表4-4所示。表4-4比较运算符
    运算符=><>=<=等于大于小于大于或等于小于或等于描述<>!=!运算符不等于不等于不小于不大于描述
    5.逻辑运算符
     逻辑运算符用于对表达式或操作数进行比较或测试,其运算结果返回的是布尔类型的值,即true或false。true表示条件成立,flase则表示
    条件不成立。在Transact-SQL中可使用逻辑运算符如表4-5所示。表4-5逻辑运算符
    运算符ALLANDANYBETWEENEXISTSINLIKENOTORSOME说明如果一组的比较都为true,则比较结果为true如果两个布尔表达式都为true,则结果为true;如果其中一个表达式为false,则结果为false如果一组的比较中任何一个为true,则结果为true如果操作数在某个范围之内,那么结果为true如果子查询中包含了一些行,那么结果为true如果操作数等于表达式列表中的一个,那么结果为true如果操作数与某种模式相匹配,那么结果为true对任何其他布尔运算符的结果值取反如果两个布尔表达式中的任何一个为true,那么结果为true如果在一组比较中,有些比较为true,那么结果为true
    例如,查询数据库“电子书查询系统”中会员所在地区为“北京”或者“上海”的会员,语句如下所示:
    USE电子书查询系统SELECT*FROM会员信息WHERE所在地区LIKE'北京'OR所在地区LIKE'上海'
    执行语句的结果如图4-4所示。
    图4-4使用逻辑运算符查询结果在该语句中,使用LIKE和OR逻辑运算符,表示如果数据中会员所在地区有北京或者上海的记录,那么就返回记录。
     6.字符串运算符加号(+)是字符串连接运算符,可以用他将字符串串联起来。其他所有字符串操作都使用字符串函数(如SUBSTRING)进行处理。默认情况下,对于varchar数据类型的数据,在INSERT或赋值语句中,空的字符串将被解释为空字符串。在串联varchar、char或text数据类型的数据时,空的字符串被解释为空字符串。例如,'abc'+''+'def被存储为'abcdef'。但是,如果兼容级别设置为65,则空常量将作为单个空白字符处理,'abc'+''+'def'将被存储为'abcdef'。7.一元运算符一元运算符表示只对一个表达式执行操作。该表达式可以是numeric数据类型中的任何一种数据类型。在Transact-SQL语言中的一元表达式如表4-6所示。表4-6一元运算符
    运算符+~数值为正数值为负返回数字的逻辑非描述
    8.运算符的优先级当一个复杂的表达式有多个运算符时,运算符优先级决定执行运算的先后次序。执行的顺序可能严重地影响所得到的值。SQLServer2008中运算符优先级如表4-7所示。在一个表达式中按先高后低的顺序进行运算(即数字越小其优先级越高)。表4-7运算符优先级
    优先级123456789~(位非)*(乘)、/(除)、%(取模)+(正)、-(负)、+(加)(+连接)、、-(减)、&;(位与)=、>、<、>=、<=、<>、!=、!>、!<(比较运算符)^(位异或)、|(位或)NOTANDALL、ANY、BETWEEN、IN、LIKE、OR、SOME=(赋值
    )运算符
     4.2.3
    表达式
    表达式是符号与运算符的组合,由变量、常量、运算符、函数组成。在T-SQL语句中,使用表达式可以为查询操作带来很大的灵活性。它可以在查询语句中的任何位置使用,例如:检索数据的筛选条件、指定数据的值。根据表达式包含的内容,可以将表达式分为两种类型:简单表达式和复杂表达式。简单表达式是指仅由变量、常量、运算符、函数等组成的表达式。简单表达式结构单一,一般用来描述一个简单的条件。复杂表达式是指由两个或多个简单表达式通过运算符连接起来的表达式。在复杂表达式中,如果两个或多个表达式有不同的数据类型,表达式中元素组合的顺序由表达式中运算符的优先级决定。例如:下面的复杂表达式,该表达式内包含有字段、字符串、逻辑运算符等。该语句用来查询Reader表中名称为黄山,密码为123的用户信息。程序如下:
    SELECTB.Bnum,B.Bname,B.writer,BR.Rcert,Br.botime,R.Rcert,R.RnameFROMBooksB,BorrowORreturnBR,ReaderRwhereB.Bnum=Br.BnumandBr.Rcert=R.RcertGO
    执行该语句,运行结果如图4-5所示。
    图4-5使用复杂表达式构成简单表达式中元素的数据类型、排序规则、精度、小数位数和值就是它所引用元素的数据类型、排序规则、精度、小数位数和值。使用比较运算符或逻辑运算符组合两个或多个表达式时,其结果为布尔型(Boolean),即TRUE、FALSE或UNKNOWN。用算术运算符、位运算符或字符串运算符组合两个表达式时,生成的数据类型取决于运算符。
     4.2.4
    注释
    注释是程序代码中不被执行的文本字符串,用于对代码进行说明或暂时用来进行诊断的部分语句。一般地,注释主要描述程序名称、作者名称、变量说明、代码更改日期、算法描述等。在SQLServer2008系统中,支持两种注释方式,即双连字符(--)注释方式和正斜杠星号字符(/*…*/)注释方式。在双连字符(--)注释方式中,从双连字符开始到行尾的内容都是注释内容。这些注释内容既可以与要执行的代码处于同一行,也可以另起一行。双连字符(--)注释方式主要用于在一行中对代码进行解释和描述。当然,双连字符(--)注释方式也可以进行多行注释,但是每一行都须以双连字符开始。服务器不对注释进行计算。在正斜杠星号字符(/*…*/)注释方式中,开始注释对(/*)和结束注释对(*/)之间的所有内容均视为注释。这些注释字符既可以用于多行注释,也可以与执行的代码处在同一行,甚至还可以处在可执行代码的内部。服务器不计位于/*和*/之间的文本。多行/*…*/注释不能跨越批。整个注释必须包含在一个批内
    。为了更好的说明双连字符(--)注释方式和正斜杠星号字符(/*…*/)注释方式的用法,下面将举出一个具体实例,程序如下:
    USE电子书查询系统GO--查看会员的信息SELECT*FROM会员信息/*按照会员所在地区查询查询地区为'北京'的客户信息*/SELECT*FROM会员信息WHERE所在地区='北京'
    执行语句的结果如图4-6所示。
     图4-6在语句中使用注释双连字符(--)注释方式和正斜杠星号字符(/*…*/)注释方式都没有注释长度的限制。一般地,行内注释采用双连字符(--),多行注释采用正斜杠星号字符(/*…*/)注释方式。
    4.2.5
    控制流程
    在程序设计语言中,需要使用一些语句组织形式来控制程序的运行。这些程序设计语言的基本结构分为顺序结构、条件分支结构和循环结构。顺序结构是一种自然结构,条件分支结构和循环结构都需要根据程序的执行状况对程序的执行顺序进行调整和控制。在Transact-SQL语言中,流程控制语句就是用来控制程序执行流程的语句,也称流控制语句或控制流语句。下面将对主要的流程控制语句进行介绍。1.BEGIN…END语句块BEGIN…END可以定义Transact-SQL语句块,这些语句块作为一组语句执行,允许语句嵌套;关键字BEGIN定义Transact-SQL语句的起始位置,END标识同一块Transact-SQL语句的结尾。下面结合示例详细介绍关键字BEGIN…END,语法格式为:
    BEGIN{sql_statement︱statement_block}END
     上述语句中参数说明如下:
    sql_statement使用语句块定义的任何有效的Transact-SQL语句。使用语句块定义的任何有效的Transact-SQL语句块。statement_block
    2.IF…ELSE条件语句用于指定Transact-SQL语句的执行条件。如果条件真,则执行条件表达式后面的Transact-SQL语句。当条件为假时,可以使用ELSE关键字指定要执行的Transact-SQL语句。他的语法格式为:
    IFBoolean_expression{sql_statement|statement_block}ELSE{sql_statement|statement_block}
    上述语句中参数说明如下:
    Boolean_expressionsql_statement返回true或false的表达式。如果布尔表达式中含有SELECT语句,必须用圆括号将SELECT语句括起来。使用语句块定义的任何有效的Transact-SQL语句。使用语句块定义的任何有效的Transact-SQL语句块。statement_block
    例如,使用IF…ELSE条件语句根据相应场馆的使用状态执行不用的Transact-SQL语句,具体代码如下所示:
    USE体育场管理系统GOIF(SELECT状态FROM场馆信息WHERE场馆名称='足球场')='空闲'BEGINPRINT'该场馆已经没人使用,可以出租'SELECT*FROM场馆信息WHERE场馆名称='足球场'ENDELSEPRINT'该场馆已经有人预订了,非常抱歉'GO
    执行上述语句,结果如图4-7
    所示。
     图4-7
    使用IF…ELSE语句
    3.CASE分支语句CASE关键字可根据表达式的真假来确定是否返回某个值,可在允许使用表达式的任何位置使用这一关键字。使用CASE语句可以进行多个分支的选择。CASE具有两种格式:
    简单格式:将某个表达式与一组简单表达式进行比较以确定结果。搜索格式:计算一组布尔表达式以确定结果。
    (1)简单CASE格式的语法如下:
    CASEinput_expressionWHENwhen_expressionTHENresult_expression[…n][ELSEelse_result_expression]END
    上述语句中参数说明如下:
    input_expression表达式。when_expression用来和input_expression表达式做比较的表达式,input_expression和每个when_expression的数据类型必须相同,或者是隐性转换。result_expression当input_expression=when_expression的取值为true时,需当input_expression=when_expression的取值为false时,使用简单CASE格式时所计算的表达式,可以是任何有效的
    要返回的表达式。else_result_expression需要返回的表达式。
    (2)搜索CASE格式的语法如下:
    CASEWHENBoolean_expressionTHENresult_expression[…n]
     [ELSEelse_result_expression]END
    语句中参数的含义与简单CASE格式的参数含义类似。4.WHILE循环语句设置重复执行Transact-SQL语句或语句块的条件。当指定的条件为真时,重复执行循环语句。可以在循环体内设置BREAK和CONTINUE关键字,以便控制循环语句的执行过程。他的语法格式如下:
    WHILEBoolean_expression{sql_statement|statement_block}[BREAK]{sql_statement|statement_block}[CONTINUE]{sql_statement|statement_block}
    上述语句中参数说明如下:
    Boolean_expressionsql_statementBREAK布尔表达式,可以返回true或false。如果布尔表达式中含有SELECT语句,必须用圆括号将SELECT语句括起来。使用语句块定义的任何有效的Transact-SQL语句。使用语句块定义的任何有效的Transact-SQL语句块。statement_block
    导致从最内层的WHILE循环中退出,将执行出现在END关键字后使WHILE循环重新开始执行,忽略CONTINUE关键字后的任
    面的任何语句块,END关键字为循环结束标记。CONTINUE何语句。
    5.WAITFOR延迟语句WAITFOR语句可以将他之后的语句在一个指定的间隔之后执行,或在将来的某一指定时间执行。他可以悬挂起批处理、储存过程或事务的执行,直到发生以下情况为止:已超过指定的时间间隔、到达指定的时间。该语句是通过暂停语句的执行而改变语句的执行过程。他的语法如下:
    WAITFOR{DELAYtime|TIMEtime|(receive_statement)[TIMEOUTtimeout]}
    上述语句中参数说明如下:
    DELAYTime可以继续执行批处理、存储过程或事务之前必须经过的指定时段,最长
    可以24小时。要等待的时间。可以使用datetime数据可接受的格式之一指定time,也可以将其指定为局部变量,不能指定日期。因此,不允许指定datetime值的日期部分。
     TIME指示SQLServer等待到指定时间。receive_statemen任何有效的RECEIVE语句。
    例如下面的示例使用TIME关键字等到晚上10点执行【体育场管理系统】数据库检查来确保所有页已正确分配和使用:
    USE体育场管理系统GOBEGINWAITFORTIME'22:00'DBCCCHECKALLOCENDGO
    6.RETURN无条件退出语句无条件终止查询、存储过程或批处理的执行。存储过程或批处理中RETURN语句后面的所有语句都不在执行。当在存储过程中使用该语句时,可以使用该语句指定返回给调用应用程序、批处理或过程的整数值。如果RETURN语句未指定值,则存储过程的返回值是0。他的语法格式如下:
    RETUREN[integer_expression]
    上述语句中integer_expression参数返回一个整数值。存储过程可向执行调用的过程或应用程序返回一个整数值。7.GOTO跳转语句使得Transact-SQL批处理的执行跳至指定标签的语句。也就是说,不执行GOTO语句和标签之间的所有语句。由于该语句破坏了结构化语句的结构,应该尽量减少该语句的使用。他的语法格式如下:
    GOTOlabel
    这里的Label参数指定要跳转到的语句标号,其名称要符合标识符的规定。8.TRY...CATCH错误处理语句如果TRY块内部发生错误,则会将控制传递给CATCH块中包含的另一个语句组。TRY...CATCH构造捕捉所有严重级别大于10但不终止数据库连接的错误。他的使用格式如下:
    BEGINTRY{sql_statement|statement_block}ENDTRYBEGINCATCH{sql_statement|statement_block}ENDCATCH
    上述语句中参数sql_statement︱statement_block可以定义为任何有效的T
     ransact-SQL语句或语句块。例如,下面的示例显示一个生成被字符串变量除的错误SELECT语句,执行后返回发生错误的信息,具体代码如下所示:
    USE体育场管理系统GOIF(SELECT状态FROM场馆信息WHERE场馆名称='足球场')='空闲'BEGINPRINT'该场馆已经没人使用,可以出租'SELECT*FROM场馆信息WHERE场馆名称='足球场'ENDELSEPRINT'该场馆已经有人预订了,非常抱歉'GO
    执行上述代码,具体的结果如图4-8所示。
    图4-8
    使用TRY...CATCH错误处理语句
    4.4
    常用函数
    SQLServer2008为Transact-SQL语言提供了大量功能强大的系统函数,利用该函数不需要写很多代码就能够完成很多任务。在SQLServer2008中,函数主要用来获得有关信息,进行算术计算、统计分析、实现数据类型转换等操作。本节将介绍常用的聚合、数学、字符串、日期和时间函数,以及如何自定义函数
    等。
     4.4.1
    聚合函数
    聚合函数常用于GROUPBY子句,用于聚合分组的数据。所有聚合函数均为确定性函数,也就是说只要使用一组特定输入值调用聚合函数,该函数总是返回同类型的值。例如,计算一组整数型数值的总和或者平均值,结果将同样会返回整数型的数值。该函数在和GROUPBY子句一起使用时显示出其强大功能,但聚合函数的使用也不是只限于分组查询。如果查询语句中使用了聚合函数,而没有用GROUPBY子句,则聚合函数是用于聚合整个结果集(匹配WHERE子句的所有行)例如,。不使用GROUPBY子句,SELECT列表中AVG只能和SUM对应,但不能对应特定列。SQLServer2008中提供了大量的聚合函数,表4-8中列出了一些常用聚合函数。表4-8聚合函数
    函数名称AVGCHECKSUMCHECKSUM_AGGCOUNTCOUNT_BIG含义返回组中各值的平均值,如果为空将被忽略用于生成哈希索引,返回按照表的某一行或一组表达式计算出来的校验和值返回组中各值的校验和,如果为空将被忽略返回组中项值的数量,如果为空也将计数返回组中项值的数量。与COUNT函数唯一的差别是他们的返回值。COUNT_BIG始终返回bigint数据类型值。COUNT始终返回int数据类型值GROUPING当行由CUBE或ROLLUP运算符添加时,该函数将导致附加列的输出值为1;当行不由CUBE或ROLLUP运算符添加时,将导致附加列的输出值为0MAXMINSUMSTDEVSTDEVPVARVARP返回组中值列表的最大值返回组中值列表的最小值返回组中各值的总和返回指定表达式中所有值的标准偏差返回指定表达式中所有值的总体标准偏差返回指定表达式中所有值的方差返回指定表达式中所有值的总体方差
     在SQLServer2008提供的所有聚合函数中提供的所有聚合函数中,除了COUNT函数以外,聚合函数都会忽略空值聚合函数都会忽略空值。
    下面通过示例演示下聚合函数的具体应用下面通过示例演示下聚合函数的具体应用。例如,下面的语句按【体育场管理系统】数据库中【管理员信息管理员信息】表的“管理员名称”进行分组,并统计该管理员负责场馆的个数,并且统计该管理员负责的场馆的平均单价并且统计该管理员负责的场馆的平均单价,具体代码如下所示:
    SELECTB.管理员名称,COUNT(A.管理员编号AS管理员编号)管理员负责场馆数,AVG(A.单位价格AS平均价格单位价格)FROM场馆信息A,管理员信息BWHEREA.管理员编号=B.管理员编号管理员编号ANDB.管理员名称='李玺'GROUPBYB.管理员名称
    执行上述语句,可以查询出管理员为询出管理员为“李玺”所负责的场馆个数及平均单价,如图4-9所示。
    图4-
    9
    使用聚合函数
    4.4.2
    数学函数
    数学函数用于对数字表达式进行数学运算并返回运算结果在SQLServer对数字表达式进行数学运算并返回运算结果。2008中,数学函数可以对系统提供的数字数据进行运算decimal、对系统提供的数字数据进行运算:integer、float、real、money、smallmoney、smallint和tinyint。默认情况下,float对数据类型数据的内置运算的精度为六个小数位数SQLServer提供了20多个数据类型数据的内置运算的精度为六个小数位数。用于处理整数与浮点值的数学函数。。下面表4-9列出了部分常用的数学函数。表4-9数学函数
    函数描述
     ABSEXPCEILINGFLOORLNLOGPOWERROUNDSIGNSQUARESQRTSELECT
    返回数值表达式的绝对值返回指定表达式以e为底的指数返回大于或等于数值表达式的最小整数返回小于或等于数值表达式的最大整返回数值表达式的自然对数返回数值表达式以10为底的对返回对数值表达式进行幂运算的结果返回舍入到指定长度或精度的数值表达式返回数值表达式的正号(+)、负号(-)或零(0)返回数值表达式的平方返回数值表达式的平方根
    例如,下面创建一个使用ROUND函数的示例,具体代码如图所示:
    ROUND(12345.34567,2)精确小数点后2位,ROUND(12345.34567,-2)精确小数点前2位GO
    执行上述代码,结果如图5-6所示。
    图4-10
    使用ROUND函数
    数学函数(例如ABS、CEILING、DEGREES、FLOOR、POWER、RADIANS和SIGN)返回与输入值具有相同数据类型的值。三角函数和其他函数(包括EXP、LOG、LOG10、SQUARE和SQRT)将输入值转换为float并返回float值。
     4.4.3
    字符串函数
    字符串函数用于计算、格式化和处理字符串参数,或将对象转换为字符串。与数学函数一样,SQLServer2008为了方便用户进行字符型数据的各种操作和运算提供了功能全面的字符串函数。字符串函数也是经常使用的一种函数,常见的字符串函数如表4-10所示。表4-10字符串函数
    字符串函数ASCIICHARLEFTLENLOWERLTRIMREPLACEREPLICATERIGHTRTRIMSPACESTRSUBSTRINGUPPER描述ASCII函数,返回字符表达式中最左侧的字符的ASCII代码值ASCII代码转换函数,返回指定ASCII代码的字符左子串函数,返回字符串中从左边开始指定个数的字符字符串函数,返回指定字符串表达式的字符(而不是字节)数,其中不包含尾随空格小写字母函数,将大写字符数据转换为小写字符数据后返回字符表达式删除前导空格字符串,返回删除了前导空格之后的字符表达式替换函数,用第三个表达式替换第一个字符串表达式中出现的所有第二个指定字符串表达式的匹配项复制函数,以指定的次数重复字符
    表达式右子串函数,返回字符串中从右边开始指定个数的字符删除尾随空格函数,删除所有尾随空格后返回一个字符串空格函数,返回由重复的空格组成的字符串数字向字符转换函数,返回由数字数据转换来的字符数据子串函数,返回字符表达式、二进制表达式、文本表达式或图像表达式的一部分大写函数,返回小写字符数据转换为大写的字符表达式
    例如,对于下面的查询演示了如何使用字符串函数:
    SELECTRIGHT(客户编号,2)'客户编号',客户名称,ASCII(性别)'性别',LEN(客户名称)'长度','属于'+SPACE(1)+LTRIM(所在公司)'公司'FROM客户信息WHERESUBSTRING(客户名称,1,1)='王'
    在上述语句中同时使用了RIGHT、ASCII、LEN、SPACE、LTRIM和SUBSTRING共6个字符串函数,返回姓氏为“王”的所有客户信息,其执行结果如图5-7所示。
     图4-11
    使用字符串函数
    4.4.4
    日期和时间函数
    SQLServer2008提供了9个日期和时间处理函数。其中的一些函数接受datepart变元,这个变元指定函数处理日期与时间所使用的时间粒度。表5-11列出了datepart变元的可能设置。表4-11SQLServerdatepart常量常量含义常量含义
    yy或yyyyqq或qmm或mwk或wwdw或wms年季月周周日期毫秒dy或ydd或dHhmi或nss或s年日期到366)(1日时分秒
    在表4-12中列出了SQLServer2008提供的9个日期和时间函数。表4-12日期和时间函数日期函数描述
    DATEADDDATEDIFFDATENAMEDATEPARTDAYGETDATEGETUTCDATE返回给指定日期加上一个时间间隔后的新datetime值。返回跨两个指定日期的日期边界数和时间边界数。返回表示指定日期的指定日期部分的字符串。返回表示指定日期的指定日期部分的整数。返回一个整数,表示指定日期的天DATEPART部分。以datetime值的SQLServer2008标准内部格式返回当前系统日期和时间。返回表示当前的UTC时间(通用协调时间或格林尼治标准时间)
     的datetime值。当前的UTC时间得自当前的本地时间和运行MicrosoftSQLServer2008实例的计算机操作系统中的时区设置。MONTHYEAR返回表示指定日期的“月”部分的整数。返回表示指定日期的年份的整数。
    上述日期函数中,DATENAME、GETDATE和GETUTCDATE具有不确定性。而DATEPART除了用作DATEPART(dw,date)外都具有确定性。其虽dw是weekday的日期部分,取决于设置每周的第一天的SETDATEFIRST所设置的值。除此之外的上述日期函数都具有确定性。为了有助于读者更好的掌握日期和时间函数的用法,下面举出DATEPART()和DATEDIFF()函数的应用实例,具体代码及执行结果如图5-8所示。
    图4-12
    使用日期函数
    4.4.5
    自定义函数
    除了使
    用系统函数外,用户还可以创建自定义函数,以实现更独特的功能。自定义函数可以接受零个或多个输入参数,其返回值可以是一个数值,也可以是一个表,但是自定义函数不支持输出参数。SQLServer2008中,在使用CREATEFUNCTION语句来创建自定义函数,根据函数返回值形式的不同,可以创建三类自定义函数,分别是标量值自定义函数、内联表值自定义函数和多语句表值自定义函数。1.标量值函数标量值自定义函数返回一个确定类型的标量值,其返回的值类型为除text、ntext、image、cursor、timestamp和table类型外的其他数据类型。也就是说,标量值自定义函数返回的是一个数值。标量值自定义函数的语法结构如下所示:CREATEFUNCTIONfunction_name([{@parameter_namescalar_parameter_data_type[=default]}[,…n]])RETURNSscalar_return_data_type
     [WITHENCRYPTION][AS]BEGINfunction_bodyRETURNscalar_expressionEND语法中各参数含义如下:
    function_name自定义函数的名称;输入参数名;输入参数的数据类型;该子句定义了函数返回值的数据类型,该@parameter_name
    scalar_parameter_data_type
    RETURNSscalar_return_data_typeWITH
    数据类型不能是text、ntext、image、cursor、timestamp和table类型;该子句指出了创建函数的选项。如果指定了ENCRYPTION参数,则
    创建的函数是被加密的,函数定义的文本将以不可读的形式存储在syscomments表中,任何人都不能查看该函数的定义,包括函数的创建者和系统管理员;BEGIN…END该语句块内定义了函数体(function_body)以及包含,RETURN语句,用于返回值。
    了解了语法格式及参数含义之后,下面来创建一个标量值函数,他使用一个整形参数指定订单号,返回该订单的客户的。
    CREATEFUNCTIONGetName4(@idINT)RETURNSvarchar(50)ASBEGINDECLARE@Namevarchar(50)SELECT@Name=(SELECTB.客户名称FROM场馆预订信息AINNERJOINONA.场馆编号=B.客户编号WHERE订单号=@id)RETURN@NameEND客户信息B
    执行上述语句后在【教务管理系统】数据库中创建一个名称为GetName的标量值函数,在查询中调用该函数,具体的代码及结果如图5-10所示。
     图4-13
    使用自定义标量值函数
    2.内联表值函数内联表值函数以表的形式返回一个返回值,即他返回的是一个表。内联表值自定义函数没有由BEGIN…END语句块中包含的函数体,而是直接使用RETURN子句,其中包含的SELECT语句将数据从数据库中筛选出来形成一个表。使用内联表值自定义函数可以提供参数化的视图功能。内联表值自定义函数的语法结构如下所示:
    CREATEFUNCTIONfunction_name([{@parameter_namescalar_parameter_data_type[=default]}[,…n]]
    )RETURNSTABLE[WITHENCRYPTION][AS]RETURN(select_statement)
    该语法结构中各参数的含义与标量值函数语法机构中参数含义相似。例如创建一个内联表值函数来返回一个管理员负责的所有场馆信息,代码如下所示:
    CREATEFUNCTIONGetPalaestra(@PidINT)RETURNSTABLEASRETURN(SELECTA.场馆名称,A.座位,A.状态,B.管理员名称FROM场馆信息AINNERJOIN管理员信息BONA.管理员编号=B.管理员编号WHEREB.管理员编号=@Pid)
    这里创建的函数名称为GetPalaestra,他的字符串参数@Pid指定要查询的班级编号,RETURNSTABLE指定这是一个内联表值函数。创建完成后,使用SELECT语句来查看管理员编号为102所负责的所有场馆信息,如图5
     -11所示。
    图4-14
    使用内联表值函数
    3.多语句表值函数多语句表值自定义函数可以看作标量型和内联表值型函数的结合体。该类函数的返回值是一个表,但他和标量值自定义函数一样,有一个用BEGIN…END语句块中包含起来的函数体,返回值的表中的数据是由函数体中的语句插入的。由此可见,他可以进行多次查询,对数据进行多次筛选与合并,弥补了内联表值自定义函数的不足。
    4.5
    事务
    在SQLServer2008中,事务是一个很重要的概念。事务在SQLServer中相当于一个工作单元,使用事务可以确保同时发生的行为与数据有效性不发生冲突,并且维护数据的完整性,确保SQL数据的有效性。
    4.5.1
    事务概述
    事务的概念是现代数据库理论的核心概念之一。事务是单个的工作单元,是数据库中不可再分的基本部分。所谓事务就是用户对数据库进行的一系列操作的集合。对于事务中的操作要么全部完成,要么全部不完成。SQL-Server系统具有事务处理功能,能够保证数据库操作的一致性和完整性。例如由于数据库是可共享的信息资源,当出现多个用户同时在某一时刻访问和修改同一数据库中的同一部分数据内容时,可能由于一个用户的行为,造成多个用户使用的数据可能变得无效。为了解决这种问题,SQLServer使用事务可以确保同时发生的行为与数据有效性不发生冲突,而且这些数据同进也可以被其他用户看到。事务中一旦发生任何问题,整个事务就会重新开始,数据库也将返回到
     事务开始前的状态。先前发生的任何操作都会被取消,数据也恢复到原始状态。事务完成的话,便会将操作结果应用到数据库。所以无论事务是否完成或是否重新开始,事务总是确保数据库的完整性。
    在MicrosoftSQLServer2008中,SQLServer可以将事务以下列4种模式运行,主要有:自动提交事务:每条单独的语句都是一个事务。它是SQL默认的事务管理模式,每
    个T-SQL语句完成时,都被提交或回滚。显示事务:每个事务均以BEGINTRANSACTION语句显示开始,COMMIT以或ROLLBACK语句显示结束隐式事务:在前一个事务完成时新事务隐式启动,但每个事务仍以COMMIT或ROLLBACK语句显示完成批处理级事务:只能应用于多个活动结果集(MARS),在MARS会话中启动的Transact-SQL显示或隐式事务变为批处理级事务。当批处理完成时没有提交或回滚的批处理级事务将自动由SQLServer进行回来
    例如使用T-SQL语言的UPDATE语句插入表数据,就可以被看作SQLServer的单个事务来运行,例如下面语句所示:
    UPDATE[BookDateBase].[dbo].[Books]SET[bigClass]='文学',[SmallClass]='纪实文学',[Bcount]=-12WHEREBnum='9787512500983'GO
    当运行该更新语句时,SQLServer认为用户的意图是在单个事务中同时修改行“大类(BigClass)、”“小类(SmallClass)”和“库存量(Bcount)”的数据。假设,在“库存量(Bcount)”列上不允许值小于0的约束,那么更新列“库存量(Bcount)”的操作就会失败,这样全部更新操作都无法实现。由于三条插入语句同在一个UPDATE语句中,所以SQLServer将这三个更新操作作为同一个事务来执行,当一个更新败后,其他操作便一起失败。如果用户希望三个更新能够被独立地执行,则可以将上述语句改写成为如下所示的形式:
    UPDATE[BookDateBase].[dbo].[Books]SET[Bcount]=-12WHEREBnum='9787512500983'UPDATE[BookDateBase].[dbo].[Books]SET[SmallClass]='纪实文学'WHEREBnum='9787512500983'
     UPDATE[BookDateBase].[dbo].[Books]SET[bigClass]='文学'WHEREBnum='9787512500983'
    这样做的目的是,即使对约束列的更新失败,也对其他列的更新没有影响,因为这是三个不同的事务处理操作。
    4.5.2
    ACID属性
    SQLServer中,ACID属性用来标识事务的特性。事务是作为单个逻辑工作单元执行的一系列操作。一个逻辑工作单元必须有四个属性,称为原子性、一致性、隔离性和持久性(ACID)属性,只有这样才能成为一个事务。1.原子性.原子性(Atomicity)
    原子性是用于描述事务的必须工作单元;当事务结束时,对于事务内的所有数据操作,要么全都执行,要么都不执行。例如银行转账,转帐的过程中出现错误,整个事务将会回滚。只有当事务中的所有部分都成功执行了,才将事务写入数据库并使变化永久化。
    2.一致性(Consistency).一致性事务在系统完整性中实施一致性,保证系统的任何事务最后都处于有效状态来实现。再看一下银行转帐的例子,在帐户资金转移前,帐户处于有效状态。如果事务成功地完成,并且提交事务,则帐户处于新的有效的状态。如果事务
    出错,终止后,帐户返回到原先的有效状态。即当许多用户同时使用和修改同样的数据时,事务必须保持其数据的完整性和一致性。3.隔离性.隔离性(Isolation)在隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。如果有两个事务,运行在相同的时间内,执行相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。这种属性有时称为串行化,为了防止事务操作间的混淆,必须串行化或序列化请求,使得在同一时间仅有一个请求用于同一数据。
    从理论上说,一个事务绝不会遇到另一个事务内的状态,但实际上,SQLServer允许通过选择隔离级来改变这种状态
    4.持久性(Durability).持久性持久性意味着一旦事务执行成功,在系统中产生的所有变化将是永久的。持久性的概念允许开发者认为不管系统以后发生了什么变化,完成的事务是系统永久的部分。
     4.5.3
    管理事务
    SQLServer提供很多与事务处理相关的语句,使用这些语句可以开始和终止事务、设置事务属性、推迟约束执行、在从新开的位置设置断点等。TSQL使用下列四种语句来管理事务:
    BEGINTRAN:设置起始点。COMMITTRAN:使事务成为数据库中永久的、不可逆转的一部分。ROLLBACKTRAN:本质上说想要忘记它曾经发生过。SAVETRAN:创建一个特定标记符,只允许作部分回滚。
    在将它们组合成一个事务之前,先分别看一下它们各自的内容1.BEGINTRAN语句BEGINTRAN核心目的在于表示这一点是事务的起点。如果因为某些原因不能或不想提交事务,那么这一点就是将所有数据库操作回滚到起点。也就是说,就数据而言,任何超出该点范围的没有被提交的事务本质上都会被忘记。其语法结构如下所示:
    BEGIN{TRAN|TRANSACTION}[{transaction_name|@tran_name_variable}[WITHMARK['description']]][;]
    该语法中各参数的含义如下所示。
    Transaction_name表示事务的名称。Transaction_name必须符合标识规则,但标识符所包含的字符数不能大于32。仅在最外在面的BEGIN…COMMIT或BEGIN…ROLLBACK嵌套语句对中使用事务名。@tran_name_variable用户定义的、含有有效事务名称的变量的名称。必须用char、varchar、nchar或nvarchar数据类型声明变量。如果传递给该变量的字符多于32位个,则仅使用前面的32个字符;其余的字符将被截断。WITHMARK['description']
    指定在日志中标记事务。Description是描述该标记的字符串。如果description是Unicode字符串,那么在将长于255个字符的值存储到msdb.dbo.logmarkhistory表之前,先将其截断为255个字符。如果description为非Unicode字符串,则长于510
    个字符的值将被截断为510个字符。BEGINTRANSACTION语句用于声明开始一个本地事务。如果遇上错误,在BEGINTRANSACTION之后的所有数据改动都能进行回滚,以将数据返回到已知的一致状态。另外,事务还可以嵌套使用,例如下面语句所示:
    USEBookDateBase
     BEGINTRANINSERTINTO[BookDateBase].[dbo].[Books]VALUES('9787512500983','1988--我想和你谈谈这个世界','韩寒','国际文化出版公司','2010-09-01','20.00','小说','中国当代小说',20,'韩寒写过的最好的小说')COMMITTRANSACTIONROLLBACKTRANSACTION
    提交一个嵌套事务并不会将来自该事务的修改永久地写入到数据库中,只是让那些修改可供外层事务使用。2.COMMITTRAN.COMMITTRAN表示完整的事务结束。在发生COMMITTRAN时,系统就认为事务是持久的,也就是说,事务的影响现在是永久的,而且即使系统失败也持续下去。
    COMMIT[TRAN|TRANSACTION][transaction_name|@tran_name_varable]COMMIT[WORK]
    语句中各参数的作用如下所示:
    Transaction_name该参数可忽略。Transaction_name指定由前面的BEGINTRANSACTION分配的事务名称。@tran_name_variable用户定义的、含有有效事务名称的变量的名称。必须用char、varchar、nchar或nvarchar数据类型声明变量。如果传递给该变量的字符多于32位个,则仅使用前面的32个字符;其余的字符将被截断。“撤消”事务的唯一方法是执行一条新事务,从功能上来说,该事务是第一个事务的反转。3.ROLLBACKTRAN.ROLLBACKTRANSACTION语句用于当事务发生错误时进行回滚操作,
    从而恢复数据库至原始状态。其语法结构为:
    ROLLBACK[TRAN|TRANSACTION][transaction_name|@tran_name_variable|savepoint_name|@savepoint_variable]
     ROLLBACK[WORK]
    各参数及语句说明如下:
    Transaction_name要回滚的事务名称。@tran_name_variable用户定义的、包含有效事务名称的变量的名称。必须用char、varchar、nchar或nvarchar数据类型声明变量。Savepoint_name当条件回滚只影响事务的一部分时,可使用savepoint_name.@savepoint_variable用户定义的、包含有效保存点名称的变量的名称。必须用char,varchar,nchar或nvarchar数据类型声明变量。ROLLBACKWORK语句外层事务)。总是回退到嵌套事务系列当中的第一个事务(最
    从相关的BEGIN语句开始发生的所有事情本质上都会被忘记。
    4.SAVETRAN.
    SAVETRAN语句允许部分地提交一个事务,同时仍能回滚这个事务的其余部分。其语法格式为:
    SAVE{TRAN|TRANSACTION}{savepoint_name|@savepoint_variable}
    各参数的含义如下:
    Savepoint_name分配给保存点的名称。保存点名称必须符合标识符的规则,但长度不能超过32个字符。@savepoint_variable包含
    有效保存点名称的用户定义变量的名称。必须用char、varchar、nchar或nvarchar数据类型声明变量。如果长度超过32个字符,也可以传递到变量,但只使用前32个字符。
    用户可以在事务内设置保存点或标记。保存点可以定义在按条件取消某个事务的一部分后该事务可以返回到的一个位置。记住,回滚时清除保存点-也就是说,即使有5个保存点,一旦执行了ROLLBACK,那么这5个保存点也都会消失。可以重新设置新的保存点,并回滚到那些点上,但无论是哪个保存点都会在回滚时消失。
    4.5.4
    分布式事务
    SQLServer不仅支持本地事务,而且还支持分布式事务。所谓分布式事务,是指对多个数据库中的数据进行修改操作的事务。这些数据库可以是本地的SQLServer数据库,也要以是其他链接服务器上的数据库。分布式事务由一个称为分布式事务协调程序的SQLServer构件来管理。在Transact-SQL中启动的分布式事务的结构相对比较简单:
    Transact-SQL脚本或应用程序连接执行启动分布式事务的Transact-SQL语句。执行该语句的MicrosoftSQLServer成为事务中的主控服务器。
     然后脚本或应用程序对链接的服务器执行分布式查询,或对远程服务器执行远程存储过程。当执行了分布式查询或远程过程调用后,主控服务器将自动调用MSDTC以便登记分布式事务中链接的服务器和远程服务器。当脚本或应用程序发出COMMIT或ROLLBACK语句时,主控SQLServer将调用MSDTC管理两阶段提交过程,或者通知链接的服务器和远程服务器回滚其事务。
    4.6
    锁
    并发性(concurrency)是任何数据库系统中的一个主要问题。它描述了两个或多个用户都想在同一时间里对某一数据修改时,会产生一定的并发问题。使用事务便可以解决用户存取数据时出现的这个问题,从而保持数据库的完整性和一致性。然而如果希望防止其他用户修改另一个还没完成的事务中的数据,就必须在事务中使用锁。
    4.6.1并发问题
    当多个用户同时访问同一数据库,并且他们的事务同时使用的数据,则就可能发生并发问题。锁能阻止4种主要问题包括:脏读、丢失更新、幻读、不一致的分析。1.脏读.脏读是指当事务在读取一条仍处于被更改状态的数据时,就会出现这个问题。比如,事务A访问到一条数据,并对该数据进行修改,当这种修改还未提交到数据库时,事务B也访问了这条数据,并使用了事务A修改后的数据,由于该数据未提交,所以事务B使用这个数据就是脏数据,就可能产生错误的操作结果。2.丢失更新.丢失更新丢失更新是指事务A、事务B同理对一数据
    进行修改。当事务A把修改结果成功提交到数据以后,事务B也成功提交到数据中,那么数据库中保存则是事务B修改后的数据,而事务A修改的数据丢失。3.幻读.幻读是指当事务不是独立执行时发生的一种现象。比如,事务A对一个表的数据进行修改,这种修改涉及到表中的全部数据行。同时,事务B也修改了这个表中的数据,但是只向表中插入了一行数据,那么,以后就会发生这样的情况:操作事务B的用户更新后,却发现表中还有尚未修改的数据行,
     这就是幻读。4.不一致的分析.不一致的分析与脏读问题有关,不一致的分析是由不可重复的读取造成的。比如,编辑人员两次读取同一文档,但在两次读取之间,作者重写了该文档。当编辑人员第二次读取文档时,文档已更改。这样就发生了编辑人员两次读取的数据是不一样的情形。
    4.6.2锁模式
    在SQLServer数据库中加锁时,除了可以对不同的资源加锁,还可以使用不同程度的加锁方式。SQLServer中提供了多种锁方式,主要包括:共享锁、排它锁、更新锁、意向锁、模式修改锁、模式稳定锁和大容量更新锁。1.共享锁.在SQLServer中,共享锁用于所有的只读数据操作。共享锁是非独占的,允许多个并发事务读取其锁定的资源。默认情况下,数据被读取后,SQLServer立即释放共享锁。例如,执行查询“SELECT*FROMAUTHORS”时,首先锁定第一页,读取之后,释放对第一页的锁定,然后锁定第二页。这样,就允许在读操作过程中,修改未被锁定的第一页。但是,事务隔离级别连接选项设置和SELECT语句中的锁定设置都可以改变SQLServer的这种默认设置。例如,SELECT*FROMAUTHORSHOLDLOCK”就要求“在整个查询过程中,保持对表的锁定,直到查询完成才释放锁定。2.排它锁.排它锁是为修改数据而保留的。它所锁定的资源,其他事务不能读取也不能修改。3.更新锁.更新锁在修改操作的初始化阶段用来锁定可能要被修改的资源,这样可以避免使用共享锁造成的死锁现象。因为使用共享锁时,修改数据的操作分为两步,首先获得一个共享锁,读取数据,然后将共享锁升级为排它锁,然后再执行修改操作。这样如果同时有两个或多个事务同时对一个事务申请了共享锁,在修改数据的时候,这些事务都要将共享锁升级为排它锁。这时,这些事务都不会释放共享锁而是一直等待对方释放,这样就造成了死锁。如果一个数据在修改前直接申请更新锁,在数据修改的时候再升级为排它锁,就可以避免死锁。4.意向锁.意向锁说明SQLServer有在资源的低层获得共
    享锁或排它锁的意向。例如,表级的共享意向锁说明事务意图将排它锁释放到表中的页或者行。意向
     锁又可以分为共享意向锁、独占意向锁和共享式独占意向锁。共享意向锁说明事务意图在共享意向锁所锁定的低层资源上放置共享锁来读取数据。独占意向锁说明事务意图在共享意向锁所锁定的低层资源上放置排它锁来修改数据。共享式排它锁说明事务允许其他事务使用共享锁来读取顶层资源,并意图在该资源低层上放置排它锁。
    模式修改锁
    执行表的数据定义语言操作时使用模式修改锁
    模式稳定锁
    当编译查询时,使用模式稳定锁。模式稳定锁不阻塞任何事务锁,包括排它锁。因此在编译查询时,其他事务都能继续运行,但不能在表中执行DDL操作。
    大容量更新锁
    当将数据大容量复制到表,且指定了TABLOCK提示或者使用sp_tableoption设置了tablelockonbulk表选项时,将使用大容量更新锁。大容量更新锁允许进程将数据并发地大容量复制到同一表,同时防止其它不进行大容量复制数据的进程访问该表。
    4.6.3查看锁
    对于数据管理员来说,了解服务器上正处于使用状态的锁的情况是非常必要的。SQLServer提供了几个有用的工具,可以来了解SQLServer加锁系统上正在发生的事情。比如,使用sys.dm_tran_locks动态管理视图和使用SQLServerManagementStudio的查看加锁情况。1.使用sys.dm_tran_locks视图.使用sys.dm_tran_locks视图可以快速了解SQLServer内的加锁情况。在默认情况下,任何一个拥有VIEWSERVERSTATE权限的用户均可以查询sys.dm_tran_locks视图。sys.dm_tran_locks视图有两个主要用途。第一个用途是帮助数据库管理员查看服务器上的锁,如果sys.dm_tran_locks视图的输出包含许多状态为WAIT或CONVERT的锁,就应该怀疑存在死锁问题。例如,在查询窗口中输入下列语句:
    select*fromsys.dm_tran_locks
    执行该语句,运行结果如图4-15所示
     图4-15使用sys.dm_tran_locks视图第二个用途是sys.dm_tran_locks视图可以帮助了解一条特定SQL语句所置的实际锁,因为用户可以检索一个特定进程的锁。例如,执行下面的一个事务操作语句:
    USEBookDateBaseBEGINTRANINSERTINTO[BookDateBase].[dbo].[Books]VALUES('9787512500983','1988--我想和你谈谈这个世界','韩寒','国际文化出版公司','2010-09-01','20.00','小说','中国当代小说',20,'韩寒写过的最好的小说')SELECT*FROMsys.dm_tran_locksROLLBACKTRANSACTION
    在上述语句中,在设置了要使用的数据库之后,这个批处理首先开始一个事务,因为锁只有在当前事务运行期间才能被保持住。通过让事务保持执行,可以在SQLServer释放这前检查它们
    。下一条语句INSERT是实际请
     求锁的语句。随后一条语句是sys.dm_tran_locks视图显示当前事务的锁而使用的形式。最后的语句是回滚事务,不对数据库执行修改。执行上述语句,执行结果如图4-16所示。
    图4-16执行特定进程2.使用SQLServerManagementStudio.使用SQLServerManagementStudio可以实现图形化显示加锁信息。启动SQLServerManagementStudio,展开【管理】节点,在该节点下双击【活动监视器】节点。打开【活动监视器】窗口,如图4-17所示。
     图4-17【活动监视器】窗口
    4.7游标
    迄今为止,我们已经讨论了如何处理数据集。这是背离过程化驱动语言处理事情的方法。实际上,当数据到达客户端的时候,大部分客户端总是不得不接受我们提供的数据集,然后逐行处理。它们要处理的是游标(Cursor)。游标
    4.7.1
    游标概述
    游标是提取数据集的一种方法,而且可以与该集合中的单条记录交互。它不像人们想像的那样频繁出现,但实际有时通过修改或选择整个集合中的数据并不能得到所期望的结果。该集合是由一些具有共性的行产生(例如由SELECT语句定义),但随后基本上都需要逐行处理这些数据。游标中的结果集与正常的SELECT语句之间有许多不同之处:
    声明游标与实际执行游标是相互分开的。游标和结果集在声明中命名,然后通过名字引用游标。在游标中设置结果,一旦打开,就一直开放到关闭为止。游标有一组用于操纵记录集的特殊命令。
    虽然SQLServer具有处理游标的方法,但实际上SQLServer中也有一些对象库可以创建游标:
     OLEDB(被ADO使用)ODBC(被RDO、DAO使用,在某些情况下,也可以被OLEDB/ADO使用)DB-Lib(被VB-SQL使用)
    客户端应用程序总是使用这些库访问单独记录。每一个库都提供操纵结果集和管理游标的语法。所以一旦学会了游标的一个对象模型,就学会了操纵所有游标的大部分方法
    4.7.2
    使用游标
    使用游标有四种基本步骤:声明游标、打开游标、提取数据、关闭游标。1.声明游标.声明游标的语法结构如下所示:
    DECLAREcursor_name[INSENSITIVE][SCROLL]CURSORFORquery_expression[FOR{READONLY|UPDATE[OFcolumn_name[,…n]]}]
    该语句中各参数的含义如下所示:
    Cursor_name指定游标的名称INSENSITIVE定义一个游标,以创建将由该游标使用的数据的临时复本。SCROLL指定滚动式游标,即所有的提取选项(FIRST,LAST,PRIOR,NEXT,RELATIVE,ABSOLUTE,ABSOLUTE)均可用。Query_expression查询表达式,一般为SELECT语句。READONLY禁止通过该游标进行更新。UPDATE[OFcolumn_name[,...n]]定义游标中可更新的列。例如,声明一个游标,
    用来指向【读者信息(Reader)和】【借阅信息(BorrowORreturn)】表中的每一行数据。声明语句如下:USEBookDateBaseDECLAREReader_curFORSELECT*FROMReaderWHERER,BorrowORreturnBB.Rcert=’10010’andB.Rcert=R.RcertSCROLLCURSOR
    该语句中,声明了一个名为Reader_cur的滚动式游标并定义了一个SELECT语句。这个SELECT语句返回读者信息表和借阅信息表中卡号是10010的所有信息。2.打开游标.声明了游标这后在作其它操作之前,发布打开他。打开游标的语句的语法结构如下所示:
     OPNECursor_name
    由于打开游标是对数据库进行一些SQLSELECT的操作,它将耗费一段时间,主要取决于您使用的系统性能和这条语句的复杂程序。如果执行的时间较长,可以考虑将屏幕上显示的鼠标改为hourglass。3.提取数据.当用OPEN语句打开了游标并在数据库中执行了查询后,你不能立即利用在查询结果集中的数据。你必须用FETCH语句来取得数据。一条FETCH语句一次可以将一条记录放入程序员指定的变量中。FETCH其语法结构如下所示:
    FETCH[[fetch_orientation]from]Cursor_name[intohost_variables]
    其中,fetch_orientation表示游标的取数方向。host_variables表示允许将提取操作的列数据放到局部变量中。当游标为滚动式游标时,游标的取数方向有如下6种可以使用:
    NEXT返回紧跟当前行之后的结果行。PRIOR返回当前行的前一结果行。FIRST返回游标中的第一行并将其作为当前行。LAST返回游标中的最后一行并将其作为当前行。检索n值指定的行。如果N为正数,则返回从游标开始的第nABSOLUTEn
    行,并将返回行变成新的当前行。如果N为负数,则返回从游标末尾开始的第n行,并将返回行变成新的当前行。如果n为0,则不返回行。n必须是整数常量。RELATIVEn检索相对于当前游标位置的行。如果n为正数,则返回从当前行开始第n行,并将返回行变成新的当前行。如果n为负数则返回当前行之前的第n行,并将返回行变成新的当前行。
    例1,对表【读者信息(Reader)】和【借阅信息(BorrowORreturn)】中列【读者级别(rleve)】进行修改。
    FETCHReader_curUPDATEReader,BorrowORreturnSETrleve='高级'WHERECURRENTOFReader_cur
    上述语句中,首先使用FETCH语句提取数据行,然后使用UPDATE语句进行更新操作。首次执行操作语句,将更新结果集中的第一行,再次执行该语句,则FETCH语句会自动提取下一行数据,并进行更新。例2,对游标“Reader_cur”返回结果集中的数据行进行删除,语句如下所示:
    FETCHReader_cur
     DELETEReader,BorrowORreturnWHERECURRENTOFReader_cur
    首先运行该语句,将删除
    游标“Reader_cur”返回结果集中的第一行数据,如果再次运行该语句,将删除下一行数据。3.关闭游标.在游标使用完成后,为了节省系统资源,必须将游标关闭。关闭游标语句的语法结构如下所示:
    CLOSEcursor_name
    例如:关闭游标“Reader_cur”的语句如上所示:
    CLOSEReader_cur
    4.8
    扩展练习
    扩展练习4-1:声明用于插入操作的事务:事务是对数据库操作的集合,使用事务可以保持数据库的完整性,在本实验指导中将声明一个用于插入的事务。这里向数据库BookDateBase的表Reader中插入一条记录。(1)启动MicrosoftSQLServerManagementStudio后,新建查询窗口。(2)指定要使用的BookDateBase数据库,再声明事务。语句如下:USEBookDateBaseBEGINTRANSACTION(3)向Reader表中插入一条记录,语句如下:INSERTINTO[BookDateBase].[dbo].[Reader]([Rcert],[Rpwd],[Rname],[Rsex],[Rphone],[rleve])VALUES('10018','shihoho','会牛牛','男','15236985412','高级')GO(4)提交事务,将插入操作应用到数据库。COMMITTRANSACTION(5)执行上述操作如图4-18所示。
     图4-18
    执行事务
    扩展练习4-2:声明并使用可更新游标:可更新游标可以指定要更新的列,并对其进行修改操作。在BookDateBase数据库中创建一个名为“Reader_cur“的可更新游标,并更新其密码列数据。(1)启动MicrosoftSQLServerManagementStudio后,新建查询窗口。(2)声明“Reader_cur”的游标,并指定SELECT语句的结果集。useBookDateBasedeclareReader_curSCROLLCURSORFORSELECT*FROMReaderForupdateofRpwd(3)找开游标。OPENReader_cur(4)检索数据,并使用定位UPDATE语句更新数据列密码。FETCHReader_curUPDATEReadersetRpwd='123'WHERECURRENTOFReader_cur
    
    
  • 上一篇资讯: Sqlserver2008分页存储过程
  • 下一篇资讯: SQLServer2005的安装与配置
  • 设为首页 | 加入收藏 | 网学首页 | 原创论文 | 计算机原创
    版权所有 网学网 [Myeducs.cn] 您电脑的分辨率是 像素
    Copyright 2008-2020 myeducs.Cn www.myeducs.Cn All Rights Reserved 湘ICP备09003080号 常年法律顾问:王律师