• 数据库(八)之T-SQL编程


    什么是Transact-SQL?

      结构化查询语言(SQL)是有美国国家标准协会(ANSI)和国际标准化组织(ISO)定义的标准,而Transact-SQL是Microsoft公司对此标准的一个实现。

      transact-SQL语言是结构化查询语言(SQL)的增强版本,与多种ANSI SQL标准兼容,而且在标准的基础上还进行了许多扩展。Transact-SQL代码已成为SQL Server的核心。Transact-SQL在关系数据库管理系统中实现数据的检索,操纵和添加功能。

    分类

      在Microsoft SQL Server 2008系统中,Transact-SQL可以创建,维护,保护数据对象中的数据,所以Transact-SQL语言是一种完整的语言。根据T-SQL语言的执行功能特点,可以将T-SQL语言分为三种基本类型:

    • 数据定义语言
    • 数据操纵语言
    • 数据控制语言

      还有一些其他类型:

    • 数据控制语言
    • 流程控制语言
    • 附加的语言元素

    常量与变量

      变量声明:

    declare
    {@local_variable[as]data_type | @cursor_variable_name CURSOR
    }[,…n]

      赋值:

      要给声明的局部变量赋值,可以使用set或select语句,格式如下:

    set @local_variable = expression
    select @local_variable = expression [,…n]

      例子:

    declare @name nvarchar(50)
    set @name = 'Bob'
    select @name = 'Peter'
    select @name
    print @name

    运算符:

      算术运算符:

            

      位运算符:

            

      比较运算符:

            

      逻辑运算符:

            

           其他运算符:

           

      表达式:

           

      注释:

           

      if…else语句:

      语法格式:

    if boolean_expression
        {sql_statement | statement_block}
    else
        {sql_statement | statement_block} 

    例子:
    declare @num int
    select @num = avg(分数) from 成绩信息
    where 考试编号 = '0802' and 课程编号 = '2'

    if @num > 80
    begin
    print 'good'
    end
    else
    begin
    print 'bad'
    end

    if…else语句嵌套
    declare @num int

    select @num = avg(分数) from 成绩信息
    where 课程编号 = '2' and 考试编号 = '0802'

    if @num >= 60
    begin
    if @num < 70
    print 'just so so'
    else if @num < 80
    print 'mid'
    else if @num < 90
    print 'good'
    else
    print 'wonderful'
    end
    else
    begin
    print 'terrible'
    end

    case 语句
    语法格式:
    case input_expression
    when when_expresion then result_expression
    […n]
    [else else_result_expression]
    end

    例子:
    select 员工姓名,所任职位,员工职称 =
    case 所任职位
    when '经理' then '高级职称;
    when '主管' then '中级职称'
    when '职员' then '初级职称'
    else '其他职称'
    end
    from 员工信息

    while 语句
    while boolean_expression
    {sql_statement | statement_block}
    [break]
    {sql_statement | statement_block}
    [continue]
    {sql_statement | statement_block}

    例子:
    declare @i int, @sum int
    set @i = 1
    set @sum = 0
    while @i <= 10
    begin
    set @sum = @sum + @i
    set @i = @i + 1
    end
    select @sum as result

    例2:
    declare @i int
    declare @j int
    set @i = 3

    while @i <= 100
    begin
    declare @bol int
    set @bol = 1
    set @j = 2
    while @j <= sqrt(@i)
    begin
    if @i % @j = 0
    begin
    set @bol = 0
    break
    end
    set @j = @j + 1
    end
    if @bol = 1 print @i
    set @i = @i + 1
    end

    wati for延迟语句
    语法格式:
    waitfor
    {
    delay time | time time
    }

    例子:
    watifor delay '00:00:05'
    exec sp_helpdb

    例2:
    waitfor time '11:20:00'
    select getdate()

    goto语句
    例子:
    declare @Counter int
    set @Counter = 1
    while @Counter < 10
    begin
    print @Counter
    set @Counter = @Counter + 1
    if @Counter = 1 goto branch_one
    else @counter = 2 goto branch_two
    else goto branch_three
    end
    branch_one:
    print 'Jumping to branch one'
    goto branch_three
    branch_two:
    print 'Jumping to branch two'
    branch_three:
    print 'Jumpint to branch_three'

    try … catch错误处理语句
    begin try
    {sql_statement | statement_block}
    end try
    begin catch
    {sql_statement | statement_block}
    end catch

    例子:
    begin try
    declare @num int
    set @num = 1/0
    select @num
    end try
    begin catch
    select error_line() as '错误行数', error_message() '错误消息'
    end catch

    数学函数
    abs 绝对值
    exp 返回指定表达式以e为底的指数
    ceiling 返回大于或等于数值表达式的最小整数
    floor 返回小于或等于数值表达式的最大整数
    ln 返回数值表达式的自然对数
    log
    power
    round 返回舍入到指定长度或精度的数值表达式
    sign 返回+,-或0
    square 返回数值表达式的平方
    sqrt 返回数值表达式的平方根

    字符串函数
    ascii 返回字符表达式中最左侧的字符的ascii代码值
    char ascii代码转换函数,返回指定ascii代码的字符
    left 左字串函数,返回字符串中从左边开始指定个数的字符
    len 字符串函数,返回指定字符串表达式的字符数,其中不包含尾随空格
    lower 小写字母函数,将大写字符数据转换位小写字符数据后返回字符表达式
    ltrim 删除前导空格字符串,返回删除了前导空格之后的字符表达式
    replace 替换函数,用第三个表达式替换第一个字符串表达式中出现的所有第二个指定字符串表达式的匹配项
    replicate 赋值函数,以指定的词数重复字符表达式
    right 右子串函数,返回字符串中从右边开始指定个数的字符
    rtrim 删除尾随空格函数,删除所有尾随空格后返回一个字符串
    space 空格函数,返回由重复空格组成的字符串
    str 数字向字符转换函数,返回由数字数据转换来的字符数据
    substring 字串函数,返回字符表达式,二进制表达式,文本表达式或图像表达式的一部分
    upper 大写函数,返回小写字符数据转换为大写的字符表达式

    字符串函数
    charindex()
    返回字符串中某个指定的字串出现的开始位置。
    charindex(<'substring_expression'>, <expression>)
    其中substring_expression是所要查找的字符表达式,expression可以为字符串也可为列名表达式。如果没有发现子串,则返回0值
    此函数不能用于test和image数据类型

    patindex()
    返回字符串中某个指定的子串出现的开始位置
    patindex(<'%substring_expression%'>, <column_name>)其中子串表达式前后必须有百分号‘%’否则返回值为0
    与charindex函数不同的是,patindex函数的子串中可以使用通配符,且此函数可用于char,varchar和test数据类型。

    例子:
    declare @str1 nvarchar(20),
    @str2 nvarchar(20),
    @str3 nvarchar(20),
    @str4 nvarchar(20),
    @str5 nvarchar(20)

    set @str1 = '上海分公司经理'
    set @str2 = '北京分公司经理'
    set @str3 = '天津分公司经理'
    set @str4 = '上海分公司财务经理'
    set @str5 = '天津分公司财务经理'

    select charindex('经理', @str4)
    select right(@str4, len(@str4) - charindex('分公司', @str4) + 1)

    聚合函数
    avg 平均值
    count 计数
    max 最大值
    min 最小值
    sum 求和

    例子:
    select avg(分数) as 平均成绩
    from 成绩信息
    where 考试编号 = '0801' and 课程编号 = '2'


    select sum(分数) as 总分数
    from 成绩信息
    where 考试编号 = '0801' and 课程编号 = '2'


    select min(分数) as 最低分
    from 成绩信息
    where 考试编号 = '0801' and 课程编号 = '2'


    select max(分数) as 最高分
    from 成绩信息
    where 考试编号 = '0801' and 课程编号 = '2'


    select count(分数) as 人数
    from 成绩信息
    where 考试编号 = '0801' and 课程编号 = '2'

    日期和时间函数
    dateadd 返回给指定日期加上一个时间间隔后的新datetime值
    datediff 返回跨两个日期的日期边界数和时间边界数
    datename 返回表示指定日期的指定日期部分的字符串
    datepart 返回表示指定日期的指定日期部分的整数
    day 返回一个整数,表示指定日期的天datepart部分。
    getdate 以datetime值得SQL Server 2008标准内部格式返回当前系统日期和时间
    getutcdate 返回表示当前得utc时间得datetime值。
    month 返回表示指定日期得“月”部分的整数
    year 返回表示指定日期的年份的整数。

    例子:
    select GETDATE() as 日期

    select GETutcDATE() as 日期

    select YEAR(getdate())
    select month(getdate())
    select day(getdate())

    select DATEPART(YY, GETDATE())
    select DATEPART(mm, GETDATE())
    select DATEPART(dd, GETDATE())

    select DATEADD(DD, 1, GETDATE())

    标量值函数
    语法格式:
    create function function_name
    ([{@parament_name scalar_parameter_data_type [ = default]}[,…n]])
    returns scalar_return_data_type
    [with encryption]
    [as]
    begin
    function_body
    return scalar_expression
    end

    例子:
    create function sorceAve(@id, nvarchar(50))
    returns int
    as
    begin
    declare @score int
    select @sorce = avg(分数) from 成绩信息
    where 课程编号 = @id
    return @score
    end
    go

    select dbo.sorceAvg('2')

    表值函数
    语法格式:
    create function function_name
    ([{@parameter_name scalar_parameter_data_type [ = default]}[,…n]])
    returns table
    with encryption
    as
    return (select_statement)

    例子:
    create function findSorce(@id varchar(10))
    returns table
    as
    return (
    select 课程名称,姓名,分数 from (
    select B.课程名称, c.姓名, avg(A.分数) 分数
    from 成绩信息 A join 课程信息 B
    on A.课程编号 = B.课程编号
    join 教师信息 c on b.任课教师 = c.教师编号
    where A.考试编号= @id
    group by B.课程编号, C.姓名
    ) a
    where 分数 >= 85
    )

    select * from findcourse('0802')

    游标
    什么是游标?
    游标(Cursor)是一种数据访问机制,它允许用户访问单独的数据行,而不是对整个行集进行操作。
    用户可以通过单独处理每一条逐行收集信息并对数据逐行进行操作,这样可以降低系统开销和潜在的
    阻隔情况。用户也可以使用这些数据生成SQL代码并立即执行或输出。

    游标主要包括以下两个部分:
    (1)游标结果集 由定义游标的select语句返回的行的集合。
    (2)游标位置 指向这个结果集中的某一行的指针。

    游标的特点:
    游标返回一个完整的结果集,但允许程序设计语言只调用集合中的一行。
    允许定位在结果集中的特定行。
    从结果集的当前位置检索一行或多行
    支持对结果集中当前位置的行进行数据修改。
    可以为其他用户对显示在结果集中的数据库数据所做的更改提供不同级别的可见性支持。
    提供脚本,存储过程和触发器中使用的访问结果集中数据的T-SQL语句。

    语法格式:
    declare cursor_name [insensitive] [scroll] cursor
    for select_statement
    [for{read only|update [of column_name [,…n]]}]

    例子:
    declare student_cursor scroll cursor
    for
    select * from 学生信息
    for read only

    declare student_cursor cursor
    for
    select * from 学生信息
    for update

    释放游标
    deallocate student_cursor

    操作有标
    打开游标 open{{[global] cursor_name} | cursor_variable_name}
    检索游标 fetch
    [[next | prior | first | last | absolute { n | @nvar } | relative{n|@nvar}]

    from]
    {{[global] cursor_name} | @cursor_variable_name }
    [into @variable_name[,…n]]

    关闭游标 close {{[global] cursor_name} | @cursor_variable_name}
    释放游标 deallocate {{[global] cursor_name} | @cursor_variable_name}

    例子:
    declare stu_cursor scroll cursor for
    select 姓名 from 学生信息

    declare @name varchar(20)

    open stu_cursor
    fetch next from stu_cursor into @name
    close stu_cursor
    deallocate stu_cursor

    print @name

    游标可选项:next, prior, first, last, absolute

    判断游标提取状态
    @@fetch_statue
    0, fetch 语句成功
    -1, fetch 语句失败或行不在结果集中
    -2 提取的行不存在

    例子:
    declare stu_cursor scroll cursor for
    select 姓名 from 学生信息

    open stu_cursor
    declare @name varchar(20)
    fetch next from stu_cursor into @name

    if @@fetch_status = 0
    print @name
    else
    print 'error'
    close stu_cursor
    deallocate stu_cursor

    游标应用示例
    declare stu_cursor scroll cursor for
    select 学号 from 学生信息

    create table #t(name nvarchar(20), sorce int)

    open stu_cursor

    fetch next from stu_cursor into @name
    while @@fetch_status = 0
    begin
    insert into #t
    select B.姓名, avg(分数) as 分数
    from 成绩信息 A join 学生信息 B
    on A.学生编号 = B.学号
    where A.考试编号 = '0801' and B.学号 = @name
    group by B.姓名

    fetch next from stu_cursor into @name
    end
    close stu_cursor
    deallocate stu_cursor

    select name 姓名, sorce 平均分数 from #t
    drop table #t

    例2
    declare stu_cursor scroll cursor for
    select 姓名from 学生信息

    create table #t_name(姓名 varchar(20))

    declare @name varchar(20)

    open stu_cursor
    fetch next from stu_cursor into @name

    while @@fetch_status = 0
    begin
    insert into #t_name values(@name)
    fetch next from stu_cursor into @name
    end
    close stu_cursor
    deallocate stu_cursor

    select * from #t_name
    drop table #t_name

    事务
    在SQL Server 2008中只要使用下列4条语句管理事务:
    begin transaction
    commit transaction
    rollback transaction
    save transaction

    例子:
    begin transaction

    declare @nation varchar(20)
    set @nation = '汉族'

    insert into 学生信息
    values('2111605165', '小龙', '男', '1999-1-1', @nation, 102, '上海', '111111')

    if @nation = '汉族'
    begin
    commit transaction
    end
    else
    rollback transaction


    所谓锁,就是一个事务可向系统提出请求,对被操作的数据加锁(lock)。其他事务必须
    等到此事务解锁(unlock)之后才能访问该数据。从而,在多个用户并发访问数据库时,
    确保不互相干扰。可封锁的单位是:行,页,表,盘区和数据库。

    锁的类型
    共享锁(S) :用于读操作。
    多个事务可封锁一个共享单位的数据。
    任何事物都不能修改加S锁的数据。
    通常是加S锁的数据被读取完毕,S锁立即被释放。

    独占(X)锁:用于写操作。
    仅允许一个事务封锁此共享数据。
    其他任何事物必须等到X锁被释放才能对该数据进行访问。
    X锁一直到事务结束才能被释放。

    更新(U)锁
    用来预定对此页施加X锁,它允许其他事务读,但不允许再施加U锁或X锁。
    当被读取数据页要被更新时,则升级为X锁。
    U锁一直到事务结束时才能被释放。

    系统与元数据函数
    convert() 讲一种数据类型的数据转变为另一种数据类型的数据。
    current_user() 返回当前用户的名称。
    isdate() 判断它的输入是不是一个有效日期。
    isnull() 用一个指定替换值替换任何空值。
    isnumeric() 判断它的输入是不是一个数值。

    例子:
    declare @str varchar(10), @i int, @j int
    set @str = '12'
    set @i = 10

    if isnumeric(@str) = 1
    begin
    print convert(int, @str) *i
    end

    print isnull(@j, 10) @i

    begin…end语句块
    begin
    {
    sql_statement | statement_block
    }
    end

    例子:
    declare @sex varchar(5)
    if @sex is not null
    begin
    select * from 学生信息 where 性别 = @sex
    print '查询成功'
    end
    else
    begin
    print '查询失败'
    end

    事务模式
    自动提交事务 每条单独的语句都是一个事务
    显示事务 每个事务均以begin transaction开始,以commit或rollback语句显
    式结束。
    隐式事务 在前一个事务完成时新事物隐式启动,但每个事务仍以commit或
    rollback语句显示完成。
    批处理级事务 只能用于多个活动结果集(MARS),在MARS会话中启动的Transact-
    SQL显示或隐式事务变为批处理级事务。当批处理完成时没有提交
    或回滚的批处理级事务自动由SQL Server进行回滚。

    xact_abort选项
    xact_abort选项用于指定当SQL语句出现运行时错误时,SQL Server是否自动回滚当前
    事务。其语法格式如下所示:
    set xact_abort{on | off}
    当set xact_abort为on时,如果执行SQL语句产生运行时错误,则整个事务将终止并回滚
    当set xact_abort为off时,有时只回滚产生错误的SQL语句,而事务将继续进行处理。
    如果错误很严重,那么即使set xact_abort为off,也可能回滚整个事务。

    set xact_abort的设置是在执行或运行时设置,而不是在分析时设置。对于大多数ole db
    提供程序,必须将隐式或显示事务中的数据修改语句中的xact_abort设置为on。唯一不
    需要该选项的情况是在提供程序支持嵌套事务时。

    死锁
    所谓死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待
    的现象,若无外力作用,它们都将无法推进下去,此时称系统处于死锁状态或系统产生
    了死锁,这些永远在互相等待的进程称为死锁进程。

    由于资源占用是互斥的,当某个进程提出申请资源后,使得有关进程在无外力协助下,
    永远分配不到必需的资源而无法继续运行,这就产生了一种特殊现象死锁。

    一种情形,此时执行程序中两个或多个线程发生永久阻塞(等待),每个线程都在等待
    被其他线程占用并阻塞了的资源。例如,如果线程A锁住了记录1并等待记录2,而
    线程B锁住了记录2并等待记录1,这样两个线程就发生了死锁现象。

    必要条件:
    互斥条件 一个资源每次只能被一个进程使用
    请求与保存条件:一个进程因请求资源阻塞,对已获得的资源保持不妨
    不剥夺条件:进程已获得的资源,在未使用完之前,不能强行剥夺。
    循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
    这四个条件是死锁的必要条件,只要系统发送死锁,这些条件必然成立,而只要
    上述条件之一不满足,就不会死锁。

    死锁的解除和预防:
    按同一顺序访问对象
    避免事务中的用户交互
    保持事务简短并在一个批处理中
    使用低隔离级别
    使用绑定连接

    死锁的建议:
    对于频繁使用的表使用集簇化的索引
    设法避免一次性影响大量记录的T-SQL语句,特别是insert和update语句
    设法让update和delete语句使用索引
    使用嵌套事务时,避免提交和回退冲突
    对一些数据不需要及时读取更新值得表在写SQL得时候在表后台加上nolock
    如:select * from tableA(nolock)

    嵌套事务:
    begin transaction t1
    update 班级信息 set 班级名 = '金融管理系1班'
    where 班级编号 = '20180101'

    if exist(select * from 班级信息 where 班级名 = '金融管理系1班')
    begin
    begin transaction t2
    update 班级信息 set 辅导员 = '李民'
    where 班级名 = '金融管理系1班'

    if exist(select * from 辅导员信息 where 姓名 = '李民'
    commit transaction t2
    else
    begin
    rollback transaction t2
    end

    commit transaction t1
    end
    else
    rollback transaction t1

      

  • 相关阅读:
    Visual Studio 2005 ReportViewer 自适应报表大小显示
    【Vegas原创】SharePoint 503 Service Unavailable Error解决方法
    【Vegas改编】用C#实现浏览文件夹功能
    【Vegas2010】最后的g.cn
    【Vegas原创】SQL Server游标的经典使用
    命名规范(变量、控件)
    【Vegas原创】outlook发送时,报550 5.7.1 client does not have permissions to send as this sender解决方法
    【Vegas原创】Winform中使用MaskedTextBox制作IP地址输入框
    【Vegas原创】Apache2.2 + PHP5.3.2 + Oracle 10g配置
    IT职涯路
  • 原文地址:https://www.cnblogs.com/ZGreMount/p/8612241.html
Copyright © 2020-2023  润新知