zoukankan      html  css  js  c++  java
  • sql 游标

      1 Ø 事务 
      2 
      3 在数据库中有时候需要把多个步骤的指令当作一个整体来运行,这个整体要么全部成功,要么全部失败,这就需要用到事务。 
      4 
      5     1、 事务的特点 
      6 
      7         事务有若干条T-SQL指令组成,并且所有的指令昨晚一个整体提交给数据库系统,执行时,这组指令要么全部执行完成,要么全部取消。因此,事务是一个不可分割的逻辑单元。 
      8 
      9   
     10 
     11         事务有4个属性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)以及持久性(Durability),也称作事务的ACID属性。 
     12 
     13         原子性:事务内的所有工作要么全部完成,要么全部不完成,不存在只有一部分完成的情况。 
     14 
     15         一致性:事务内的然后操作都不能违反数据库的然后约束或规则,事务完成时有内部数据结构都必须是正确的。 
     16 
     17         隔离性:事务直接是相互隔离的,如果有两个事务对同一个数据库进行操作,比如读取表数据。任何一个事务看到的所有内容要么是其他事务完成之前的状态,要么是其他事务完成之后的状态。一个事务不可能遇到另一个事务的中间状态。 
     18 
     19         持久性:事务完成之后,它对数据库系统的影响是持久的,即使是系统错误,重新启动系统后,该事务的结果依然存在。 
     20 
     21   
     22 
     23     2、 事务的模式 
     24 
     25         a、 显示事务 
     26 
     27         显示事务就是用户使用T-SQL明确的定义事务的开始(begin transaction)和提交(commit transaction)或回滚事务(rollback transaction) 
     28 
     29         b、 自动提交事务 
     30 
     31         自动提交事务是一种能够自动执行并能自动回滚事务,这种方式是T-SQL的默认事务方式。例如在删除一个表记录的时候,如果这条记录有主外键关系的时候,删除就会受主外键约束的影响,那么这个删除就会取消。 
     32 
     33         可以设置事务进入隐式方式:set implicit_transaction on; 
     34 
     35         c、 隐式事务 
     36 
     37         隐式事务是指当事务提交或回滚后,SQL Server自动开始事务。因此,隐式事务不需要使用begin transaction显示开始,只需直接失业提交事务或回滚事务的T-SQL语句即可。 
     38 
     39         使用时,需要设置set implicit_transaction on语句,将隐式事务模式打开,下一个语句会启动一个新的事物,再下一个语句又将启动一个新事务。 
     40 
     41   
     42 
     43     3、 事务处理 
     44 
     45         常用T-SQL事务语句: 
     46 
     47         a、 begin transaction语句 
     48 
     49         开始事务,而@@trancount全局变量用来记录事务的数目值加1,可以用@@error全局变量记录执行过程中的错误信息,如果没有错误可以直接提交事务,有错误可以回滚。 
     50 
     51         b、 commit transaction语句 
     52 
     53         回滚事务,表示一个隐式或显示的事务的结束,对数据库所做的修改正式生效。并将@@trancount的值减1; 
     54 
     55         c、 rollback transaction语句 
     56 
     57         回滚事务,执行rollback tran语句后,数据会回滚到begin tran的时候的状态 
     58 
     59   
     60 
     61     4、 事务的示例 
     62 
     63 --开始事务
     64 begin transaction tran_bank;
     65 declare @tran_error int;
     66     set @tran_error = 0;
     67     begin try
     68         update bank set totalMoney = totalMoney - 10000 where userName = 'jack';        
     69         set @tran_error = @tran_error + @@error;
     70         update bank set totalMoney = totalMoney + 10000 where userName = 'jason';
     71         set @tran_error = @tran_error + @@error;
     72     end try
     73     begin catch        
     74         print '出现异常,错误编号:' + convert(varchar, error_number()) + ', 错误消息:' + error_message(); 
     75         set @tran_error = @tran_error + 1;
     76     end catch
     77 if (@tran_error > 0)
     78     begin
     79         --执行出错,回滚事务
     80         rollback tran;
     81         print '转账失败,取消交易';
     82     end
     83 else
     84     begin
     85         --没有异常,提交事务
     86         commit tran;
     87         print '转账成功';
     88     end
     89 go
     90 
     91  
     92 
     93 Ø 异常 
     94 
     95      在程序中,有时候完成一些Transact-SQL会出现错误、异常信息。如果我们想自己处理这些异常信息的话,需要手动捕捉这些信息。那么我们可以利用try catch完成。 
     96 
     97 TRY…CATCH 构造包括两部分:一个 TRY 块和一个 CATCH 块。如果在 TRY 块中所包含的 Transact-SQL 语句中检测到错误条件,控制将被传递到 CATCH 块(可在此块中处理该错误)。 
     98 
     99      CATCH 块处理该异常错误后,控制将被传递到 END CATCH 语句后面的第一个 Transact-SQL 语句。如果 END CATCH 语句是存储过程或触发器中的最后一条语句,控制将返回到调用该存储过程或触发器的代码。将不执行 TRY 块中生成错误的语句后面的 Transact-SQL 语句。 
    100 
    101      如果 TRY 块中没有错误,控制将传递到关联的 END CATCH 语句后紧跟的语句。如果 END CATCH 语句是存储过程或触发器中的最后一条语句,控制将传递到调用该存储过程或触发器的语句。 
    102 
    103      TRY 块以 BEGIN TRY 语句开头,以 END TRY 语句结尾。在 BEGIN TRY 和 END TRY 语句之间可以指定一个或多个 Transact-SQL 语句。CATCH 块必须紧跟 TRY 块。CATCH 块以 BEGIN CATCH 语句开头,以 END CATCH 语句结尾。在 Transact-SQL 中,每个 TRY 块仅与一个 CATCH 块相关联。 
    104 
    105      # 错误函数 
    106 
    107 TRY...CATCH 使用错误函数来捕获错误信息。
    108     ERROR_NUMBER() 返回错误号。
    109     ERROR_MESSAGE() 返回错误消息的完整文本。此文本包括为任何可替换参数(如长度、对象名称或时间)提供的值。
    110     ERROR_SEVERITY() 返回错误严重性。
    111     ERROR_STATE() 返回错误状态号。
    112     ERROR_LINE() 返回导致错误的例程中的行号。
    113     ERROR_PROCEDURE() 返回出现错误的存储过程或触发器的名称。
    114 
    115 
    116 
    117 
    118 
    119 
    120      示例 
    121 
    122 --错误消息存储过程
    123 if (object_id('proc_error_info') is not null)
    124     drop procedure proc_error_info
    125 go
    126 create proc proc_error_info
    127 as
    128     select 
    129         error_number() '错误编号',
    130         error_message() '错误消息',
    131         error_severity() '严重性',
    132         error_state() '状态好',
    133         error_line() '错误行号',
    134         error_procedure() '错误对象(存储过程或触发器)名称';
    135 go
    136 
    137 
    138 
    139   
    140 
    141      # 示例:用异常处理错误信息 
    142 
    143 --简单try catch示例
    144 begin try
    145     select 1 / 0;
    146 end try
    147 begin catch
    148     exec proc_error_info; --调用错误消息存储过程
    149 end catch
    150 go
    151 
    152 
    153 
    154   
    155 
    156      # 示例:异常能处理的错误信息 
    157 
    158 --
    159 --简单try catch示例,无法处理错误
    160 begin try
    161     select * * from student;
    162 end try
    163 begin catch
    164     exec proc_error_info;
    165 end catch
    166 go
    167 --
    168 --简单try catch示例,不处理错误(不存在的表对象)
    169 begin try
    170     select * from st;
    171 end try
    172 begin catch
    173     exec proc_error_info;
    174 end catch
    175 go
    176 --
    177 --异常处理,能处理存储过程(触发器)中(不存在表对象)的错误信息
    178 if (object_id('proc_select') is not null)
    179     drop procedure proc_select
    180 go
    181 create proc proc_select
    182 as
    183     select * from st;
    184 go
    185 begin try
    186     exec proc_select;
    187 end try
    188 begin catch    
    189     exec proc_error_info;
    190 end catch
    191 go
    192 
    193 
    194 
    195 
    196 
    197 
    198 
    199 
    200 
    201      异常不能处理编译期的错误,如语法错误。以及重编译造成部分名称对象得不到正确解析的时候所出现的错误。 
    202 
    203   
    204 
    205      # 示例:无法提交的事务 
    206 
    207 --创建临时用表
    208 if (object_id('temp_tab', 'u') is not null)
    209     drop table temp_tab
    210 go
    211 create table temp_tab(
    212     id int primary key identity(100000, 1),
    213     name varchar(200)
    214 )
    215 go
    216 
    217 begin try
    218     begin tran;
    219     --没有createTime字段
    220     alter table temp_tab drop column createTime;
    221     commit tran;
    222 end try
    223 begin catch
    224     exec proc_error_info;--显示异常信息
    225     if (xact_state() = -1)
    226     begin
    227         print '会话具有活动事务,但出现了致使事务被归类为无法提交的事务的错误。'
    228             + '会话无法提交事务或回滚到保存点;它只能请求完全回滚事务。'
    229             + '会话在回滚事务之前无法执行任何写操作。会话在回滚事务之前只能执行读操作。'
    230             + '事务回滚之后,会话便可执行读写操作并可开始新的事务。';
    231     end
    232     else if (xact_state() = 0)
    233     begin
    234         print '会话没有活动事务。';
    235     end
    236     else if (xact_state() = 1)
    237     begin
    238         print '会话具有活动事务。会话可以执行任何操作,包括写入数据和提交事务。';
    239     end
    240 end catch
    241 go
    242 
    243 
    244 
    245   
    246 
    247      # 示例:处理异常日志信息 
    248 
    249 --
    250 ---异常、错误信息表
    251 if (object_id('errorLog', 'U') is not null)
    252     drop table errorLog
    253 go
    254 create table errorLog(
    255     errorLogID int primary key identity(100, 1),    --ErrorLog 行的主键。
    256     errorTime datetime default getDate(),            --发生错误的日期和时间。
    257     userName sysname default current_user,            --执行发生错误的批处理的用户。
    258     errorNumber int,                                --发生的错误的错误号。
    259     errorSeverity int,                                --发生的错误的严重性。
    260     errorState int,                                    --发生的错误的状态号。
    261     errorProcedure nvarchar(126),                    --发生错误的存储过程或触发器的名称。
    262     errorLine int,                                    --发生错误的行号。
    263     errorMessage nvarchar(4000)
    264 )
    265 go
    266 --
    267 --存储过程:添加异常日志信息
    268 if (object_id('proc_add_exception_log', 'p') is not null)
    269     drop proc proc_add_exception_log
    270 go
    271 create proc proc_add_exception_log(@logId int = 0 output)
    272 as
    273 begin
    274     set nocount on;
    275     set @logId = 0;
    276     begin try
    277         if (error_number() is null)
    278             return;
    279         
    280         if (xact_state() = -1)
    281         begin
    282             print '会话具有活动事务,但出现了致使事务被归类为无法提交的事务的错误。'
    283                 + '会话无法提交事务或回滚到保存点;它只能请求完全回滚事务。'
    284                 + '会话在回滚事务之前无法执行任何写操作。会话在回滚事务之前只能执行读操作。'
    285                 + '事务回滚之后,会话便可执行读写操作并可开始新的事务。';
    286         end
    287         else if (xact_state() = 0)
    288         begin
    289             print '会话没有活动事务。';
    290         end
    291         else if (xact_state() = 1)
    292         begin
    293             print '会话具有活动事务。会话可以执行任何操作,包括写入数据和提交事务。';
    294         end
    295         
    296         --添加日志信息
    297         insert into errorLog values(getDate(), 
    298             current_user, error_number(), 
    299             error_severity(), error_state(), 
    300             error_procedure(), 
    301             error_line(), error_message());
    302         --设置自增值
    303         select @logId = @@identity;
    304     end try
    305     begin catch
    306         print '添加异常日志信息出现错误';
    307         exec proc_error_info;--显示错误信息
    308         return -1;
    309     end catch
    310 end
    311 go
    312 --
    313 ---处理异常信息示例
    314 declare @id int;
    315 begin try
    316     begin tran;
    317     --删除带有外键的记录信息
    318     delete classes where id = 1;
    319     commit tran;
    320 end try
    321 begin catch
    322     exec proc_error_info;--显示错误信息
    323     if (xact_state() <> 0)
    324     begin
    325         rollback tran;
    326     end
    327     exec proc_add_exception_log @id output
    328 end catch
    329 select * from errorLog where errorLogID = @id;
    330 go
    331 
    332 
    333   
    334 
    335 Ø 游标 
    336 
    337      游标可以对一个select的结果集进行处理,或是不需要全部处理,就会返回一个对记录集进行处理之后的结果。 
    338 
    339      1、游标实际上是一种能从多条数据记录的结果集中每次提取一条记录的机制。游标可以完成: 
    340 
    341           # 允许定位到结果集中的特定行 
    342 
    343           # 从结果集的当前位置检索一行或多行数据 
    344 
    345           # 支持对结果集中当前位置的进行修改 
    346 
    347      由于游标是将记录集进行一条条的操作,所以这样给服务器增加负担,一般在操作复杂的结果集的情况下,才使用游标。SQL Server 2005有三种游标:T-SQL游标、API游标、客户端游标。 
    348 
    349   
    350 
    351      2、游标的基本操作 
    352 
    353           游标的基本操作有定义游标、打开游标、循环读取游标、关闭游标、删除游标。 
    354 
    355      A、 定义游标 
    356 
    357 declare cursor_name    --游标名称
    358 cursor [local | global]    --全局、局部
    359 [forward only | scroll]    --游标滚动方式
    360 [read_only | scroll_locks | optimistic]    --读取方式
    361 for select_statements                    --查询语句
    362 [for update | of column_name ...]        --修改字段
    363 
    364 
    365 
    366      参数: 
    367 
    368      forward only | scroll:前一个参数,游标只能向后移动;后一个参数,游标可以随意移动 
    369 
    370      read_only:只读游标 
    371 
    372      scroll_locks:游标锁定,游标在读取时,数据库会将该记录锁定,以便游标完成对记录的操作 
    373 
    374      optimistic:该参数不会锁定游标;此时,如果记录被读入游标后,对游标进行更新或删除不会超过 
    375 
    376   
    377 
    378      B、 打开游标 
    379 
    380           open cursor_name; 
    381 
    382           游标打开后,可以使用全局变量@@cursor_rows显示读取记录条数 
    383 
    384   
    385 
    386      C、 检索游标 
    387 
    388           fetch cursor_name; 
    389 
    390           检索方式如下: 
    391 
    392              fetch first; 读取第一行 
    393 
    394              fetch next; 读取下一行 
    395 
    396              fetch prior; 读取上一行 
    397 
    398              fetch last; 读取最后一行 
    399 
    400              fetch absolute n; 读取某一行 
    401 
    402                 如果n为正整数,则读取第n条记录 
    403 
    404                 如果n为负数,则倒数提取第n条记录 
    405 
    406                 如果n为,则不读取任何记录 
    407 
    408              fetch pelative n 
    409 
    410                 如果n为正整数,则读取上次读取记录之后第n条记录 
    411 
    412                 如果n为负数,则读取上次读取记录之前第n条记录 
    413 
    414                 如果n为,则读取上次读取的记录 
    415 
    416   
    417 
    418      D、 关闭游标 
    419 
    420           close cursor_name; 
    421 
    422   
    423 
    424      E、 删除游标 
    425 
    426           deallocate cursor_name; 
    427 
    428   
    429 
    430      3、游标操作示例 
    431 
    432 --创建一个游标
    433 declare cursor_stu cursor scroll for
    434     select id, name, age from student;
    435 --打开游标
    436 open cursor_stu;
    437 --存储读取的值
    438 declare @id int,
    439         @name nvarchar(20),
    440         @age varchar(20);
    441 --读取第一条记录
    442 fetch first from cursor_stu into @id, @name, @age;
    443 --循环读取游标记录
    444 print '读取的数据如下:';
    445 --全局变量
    446 while (@@fetch_status = 0)
    447 begin
    448     print '编号:' + convert(char(5), @id) + ', 名称:' + @name + ', 类型:' + @age;
    449     --继续读取下一条记录
    450     fetch next from cursor_stu into @id, @name, @age;
    451 end
    452 --关闭游标
    453 close area_cursor;
    454 
    455 --删除游标
    456 --deallocate area_cursor;
  • 相关阅读:
    Base64编码与图片互转
    YUI Compressor–另一款压缩JS/CSS的小工具
    布局和展现相关的建议──给用户体验设计者
    实现左右边框的最低碳代码~~
    三角的一个特殊做法(一个奇技淫巧~)
    数组指针和指针数组
    vs2008建win32基本项目
    vs2008快捷键
    (转)HTML特殊字符
    (转)html5 Placeholder属性兼容IE6、7方法
  • 原文地址:https://www.cnblogs.com/yangpeng-jingjing/p/4710721.html
Copyright © 2011-2022 走看看