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;
原文地址:https://www.cnblogs.com/yangpeng-jingjing/p/4710721.html