SQL Server游标语句

SQL Server游标语句

1.声明游标

declare myCursor cursor

[global | local]

[forward_only | scroll]

[static | keyset | dynamic | fast_forward]

[read_only | optimistic | scroll_locks]

for select_statement

[for update [of column_name [,...n] ]]

注解:

global表示全局游标(默认),local表示本地游标

forward_ony表示只进游标,默认方式;scroll表示滚动游标

static表示静态游标(外部更新游标内不体现);keyset表示键集驱动游标(外部更新游标内不体现);dynamic表示动态游标,默认方式;fast_forward表示read_only + forward_only(外部更新游标内体现

read_only表示只读(游标内不支持更新);optimistic表示乐观并发控制;scroll_locks表示悲观并发控制(更新锁)

*static,forward_only和keyset,默认为(有且只能为)read_only,不支持for update

*dynamic,默认为optimistic

 

游标内只要不涉及delete, update操作,就不必考虑并发问题,锁机制;否则必须考虑,乐观并发控制,悲观并发控制。

乐观并发控制:数据被读入游标后,如果游标某行数据已经发生变化,那么游标内的更新、删除操作会失败。

悲观并发控制(事务内):数据被读入游标后,如果游标某行数据已经发生变化,那么游标内的更新、删除操作总会成功。

定义游标变量

declare @myVariable cursor

set @myVariable = myCursor

2.打开游标

open currsor_name 或 @currsor_variable_name

3.读取游标中的数据

fetch [next | prior | first | last | absolute{n} | relative{n}]

from currsor_name 或 @currsor_variable_name

into @variable_name

4.关闭游标

close currsor_name 或 @currsor_variable_name

 

5.释放游标

deallocate currsor_name 或 @currsor_variable_name

例子1:静态游标(默认只读并发)

use test

go

declare @id int

declare @name varchar(20)

declare myCursor cursor

static

for select id, name from t1

open myCursor

fetch next from myCursor into @id, @name

while @@fetch_status = 0

begin

    select @name  --一直未变

    select * from t1

    fetch next from myCursor into @id, @name

    waitfor delay '00:00:10'

end

close myCursor

deallocate myCursor

----------------------------------------------------------

use test

go

update t1 set t1.name = 'tttt'

----------------------------------------------------------

t1(id, name)

97 hello
14 hello
16 hello
111 hello

结果:

hello

hello

hello

hello

说明外部更新的操作在游标中并未体现。

 例子2:静态游标(默认只读并发)

use test

go

declare @id int

declare @name varchar(20)

declare myCursor cursor

static

for select id, name from t1

for update

open myCursor

fetch next from myCursor into @id, @name

update set t1.name = 'oooo' where current of myCursor

while @@fetch_status = 0

begin

    print @name

    update set t1.name = 'oooo' where current of myCursor

    fetch next from myCursor into @id, @name

   

    waitfor delay '00:00:10'

end

close myCursor

deallocate myCursor

结果:出错。

Server: Msg 1048, Level 15, State 1, Line 16
Conflicting cursor options FOR UPDATE and STATIC.

说明静态游标内不允许更新,即不支持for update。

 

 例子3:fast_forward(默认只读并发+只进游标)

use test

go

declare @id int

declare @name varchar(20)

declare myCursor cursor

fast_forward

for select id, name from t1

open myCursor

fetch next from myCursor into @id, @name

while @@fetch_status = 0

begin

    select @name --会因外部改变而改变

    select * from t1

    fetch next from myCursor into @id, @name

    waitfor delay '00:00:10'

end

close myCursor

deallocate myCursor

----------------------------------------------------------

use test

go

update t1 set t1.name = 'tttt'

----------------------------------------------------------

t1(id, name)

97 hello
14 hello
16 hello
111 hello

结果:

hello
hello
hello
tttt

说明外部的更新操作在游标中已体现,同样删除操作也会在游标中体现。

例子4:fast_forward(默认只读并发+只进游标),不支持for update

use test

go

declare @id int

declare @name varchar(20)

declare myCursor cursor

fast_forward

for select id, name from t1

for update

open myCursor

fetch next from myCursor into @id, @name

while @@fetch_status = 0

begin

    print @name

    fetch next from myCursor into @id, @name

    waitfor delay '00:00:10'

end

close myCursor

deallocate myCursor

结果:出错。

Server: Msg 1048, Level 15, State 1, Line 16
Conflicting cursor options FAST_FORWARD and FOR UPDATE.

说明该游标不支持for update;游标外部可以更新。

例子5:键集驱动游标

use test

go

declare @id int

declare @name varchar(20)

declare myCursor cursor

keyset

for select id, name from t1

open myCursor

fetch next from myCursor into @id, @name

while @@fetch_status = 0

begin

    print @name  --从打开游标后,就一直未变

    fetch next from myCursor into @id, @name

    waitfor delay '00:00:10'

end

close myCursor

deallocate myCursor

----------------------------------------------------------

use test

go

update t1 set t1.name = 'tttt'

----------------------------------------------------------

t1(id, name)

97 hello
14 hello
16 hello
111 hello

结果:

hello
hello
hello
hello

说明外部的更新操作在游标中未体现,同样删除操作未体现。

 

例子6:键集驱动游标,不支持for update

use test

go

declare @id int

declare @name varchar(20)

declare myCursor cursor

keyset

for select id, name from t1

for update

open myCursor

fetch next from myCursor into @id, @name

while @@fetch_status = 0

begin

    print @name

   update t1 set t1.name = 'ooo' where current of myCursor

    fetch next from myCursor into @id, @name

    waitfor delay '00:00:10'

end

close myCursor

deallocate myCursor

结果:出错。

Server: Msg 16957, Level 16, State 4, Line 10
FOR UPDATE cannot be specified on a READ ONLY cursor.

例子7:动态游标(默认乐观并发)--特别注意

declare @id int

declare @name varchar(20)

declare myCursor cursor

dynamic

for select id, name from t1

for update

open myCursor

fetch next from myCursor into @id, @name

while @@fetch_status = 0

begin

    select @name 
    select * from t1

    update t1 set t1.name = 'oooo' where current of myCursor

    fetch next from myCursor into @id, @name

    waitfor delay '00:00:10'

end

close myCursor

deallocate myCursor

----------------------------------------------------------

use test

go

update t1 set t1.name = 'tttt'

----------------------------------------------------------

t1(id, name)

97 hello
14 hello
16 hello
111 hello

结果: 出错。

Server: Msg 16934, Level 10, State 1, Line 28
Optimistic concurrency check failed. The row was modified outside of this cursor.
Server: Msg 16947, Level 10, State 1, Line 28
No rows were updated or deleted.
The statement has been terminated.

t1:

97 tttt
14 tttt
16 oooo
111 oooo

例子:动态游标(只读并发),不支持for update

use test

go

declare @id int

declare @name varchar(20)

declare myCursor cursor

dynamic read_only

for select id, name from t1

for update

open myCursor

fetch next from myCursor into @id, @name

while @@fetch_status = 0

begin

    print @name

    fetch next from myCursor into @id, @name

    update t1 set t1.name = 'oooo' where current of myCursor

    waitfor delay '00:00:10'

end

close myCursor

deallocate myCursor

结果:出错。

Server: Msg 1048, Level 15, State 1, Line 16
Conflicting cursor options FOR UPDATE and READ_ONLY.

例子:动态游标(悲观并发)--一定要放在事务中,更新锁在事务内一直有效;否则,update之后就释放更新锁,易造成死锁。

begin tran

declare @id int

declare @name varchar(20)

declare myCursor cursor

dynamic scroll_locks

for select id, name from t1

for update

open myCursor

fetch next from myCursor into @id, @name

while @@fetch_status = 0

begin

    select @name 
    select * from t1

    update t1 set t1.name = 'oooo' where current of myCursor

    fetch next from myCursor into @id, @name

    waitfor delay '00:00:10'

end

close myCursor

deallocate myCursor

commit tran
go

-----------------------------------------------------------------------

use test

go

update t1 set t1.name = 'tttt'

结果:

97 tttt
14 tttt
16 tttt
111 tttt
先执行带有游标的事务,然后再执行更新。串行执行。

例子:省去参数的游标--动态游标

use test

go

declare @id int

declare @name varchar(20)

declare myCursor cursor
for select id, name from t1

open myCursor

fetch next from myCursor into @id, @name

while @@fetch_status = 0

begin

    print @name

    fetch next from myCursor into @id, @name

    waitfor delay '00:00:10'

end

close myCursor

deallocate myCursor

-----------------------------------------------------------

use test

go

update t1 set t1.name = 'tttt'

结果:

hello

hello

tttt

tttt

说明默认为动态游标

转自 http://qiutian110119.blog.163.com/blog/static/54617311201062111113734/

posted @ 2014-04-22 01:11  princessd8251  阅读(426)  评论(0编辑  收藏  举报