問題的發生有時候是偶然的,也許你從來沒有關注,但並不代表你以後不會遇到同樣(類似)的問題。有關SQL中游標的示例很多,這裡我也結合實例來講解SQL的應用技巧,文中主要是利用游標的實現對多個記錄的添加。
問題的提出:
如下三個有關安排課程的表:
<!--
课程表: T_KCB
XueN, XueQ, BanJ, XingQ, JieC,KeCh
调课表: T_TK
XueN, XueQ, BanJ, ZhouC, XingQ, JieC,YuanKCh, ShiJKCh, TiaoKYY
实时課表: T_SSKB
XueN, XueQ, BanJ, ZhouC, XingQ, JieC,KeCh, BeiZh
-->
课程表是一开学就维护好的,不用改变。调课表是记录中途课程变动的。实时课表是根据上述两表自动生成的。
需進行如下操作來設置課程:
在选择好学年(XueN), 学期(XueQ),班级(BanJ), 周次(ZhouC)后,先从临时课表中读数据,如为空,则把课程表数据插入实时课表中,并加上周次(ZhouC);若不为空,则把对应星期(XingQ),节次(JieC)的那门课换成临时调课后的实际课程(ShiJKCh),然后再备注(BeiZh)里面加上调课原因(TiaoKYY)
需要输入的XueN,XueQ,BanJ,ZhouC。
<!--
课程表: T_KCB
XueN, XueQ, BanJ, XingQ, JieC,KeCh
调课表: T_TK
XueN, XueQ, BanJ, ZhouC, XingQ, JieC,YuanKCh, ShiJKCh, TiaoKYY
实时課表: T_SSKB
XueN, XueQ, BanJ, ZhouC, XingQ, JieC,KeCh, BeiZh
-->
课程表是一开学就维护好的,不用改变。调课表是记录中途课程变动的。实时课表是根据上述两表自动生成的。
需進行如下操作來設置課程:
在选择好学年(XueN), 学期(XueQ),班级(BanJ), 周次(ZhouC)后,先从临时课表中读数据,如为空,则把课程表数据插入实时课表中,并加上周次(ZhouC);若不为空,则把对应星期(XingQ),节次(JieC)的那门课换成临时调课后的实际课程(ShiJKCh),然后再备注(BeiZh)里面加上调课原因(TiaoKYY)
需要输入的XueN,XueQ,BanJ,ZhouC。
問題的解決方法如下,文中有詳細注解,此處不再詳述。
create procedure foo
@XueN int, --外部輸入
@XueQ int,
@banj int,
@Zhouc int
as
declare @JieC int, --內部變量
@XingQ int,
@KeCh char(200)
begin
--先嚐試從調課表中搜索資料並對實時課表進行更新操作
update T_SSKB set kech=TK.shijkch,BeiZh=TK.TiaoKYY from T_SSKB KB,T_TK TK where
TK.XueN=@XueN and TK.XueQ=@XueQ and TK.banj=@Banj and TK.ZhouC=@ZhouC
and KB.XueN=TK.XueN and KB.XUEQ=TK.XueQ and KB.banJ=TK.banJ and KB.ZhouC=TK.zhouC
and KB.XingQ=T_SSKB.XingQ and KB.JieC=T_SSKB.JieC
--如果返回結果為0,說明調課表中沒有相關記錄,這時就從課程表中搜尋相關記錄進行插入操作
if @@RowCount=0
begin
DECLARE my_cursor CURSOR FOR --定義一個游標,用於循環處理
select XingQ,JieC,KeCh from T_KCB where
XueN=@XueN and XueQ=@XueQ and banj=@Banj and ZhouC=@ZhouC
OPEN my_cursor --打開游標
FETCH NEXT FROM my_cursor --將查尋結果存放在變量中以便處理
INTO @XingQ, @JieC,@KeCH
WHILE @@FETCH_STATUS = 0 --Fetch語句順利執行時循環處理
BEGIN
--執行插入操作
Insert Into T_SSKB ( XueN,xueQ,BanJ,ZhouC,xingQ,JieC,KeCh) values
(@XueN,@XueQ,@Banj,@ZhouC,@XingQ,@jieC,@KeCH)
if @@error<>0
begin
raiserror('error',16,1) --異常處理
rollback transaction
end
FETCH NEXT FROM my_cursor --繼續處理下一條記錄
INTO @XingQ, @JieC,@KeCH
end
CLOSE my_cursor --關閉遊標
DEALLOCATE my_cursor --釋放遊標
end
end
@XueN int, --外部輸入
@XueQ int,
@banj int,
@Zhouc int
as
declare @JieC int, --內部變量
@XingQ int,
@KeCh char(200)
begin
--先嚐試從調課表中搜索資料並對實時課表進行更新操作
update T_SSKB set kech=TK.shijkch,BeiZh=TK.TiaoKYY from T_SSKB KB,T_TK TK where
TK.XueN=@XueN and TK.XueQ=@XueQ and TK.banj=@Banj and TK.ZhouC=@ZhouC
and KB.XueN=TK.XueN and KB.XUEQ=TK.XueQ and KB.banJ=TK.banJ and KB.ZhouC=TK.zhouC
and KB.XingQ=T_SSKB.XingQ and KB.JieC=T_SSKB.JieC
--如果返回結果為0,說明調課表中沒有相關記錄,這時就從課程表中搜尋相關記錄進行插入操作
if @@RowCount=0
begin
DECLARE my_cursor CURSOR FOR --定義一個游標,用於循環處理
select XingQ,JieC,KeCh from T_KCB where
XueN=@XueN and XueQ=@XueQ and banj=@Banj and ZhouC=@ZhouC
OPEN my_cursor --打開游標
FETCH NEXT FROM my_cursor --將查尋結果存放在變量中以便處理
INTO @XingQ, @JieC,@KeCH
WHILE @@FETCH_STATUS = 0 --Fetch語句順利執行時循環處理
BEGIN
--執行插入操作
Insert Into T_SSKB ( XueN,xueQ,BanJ,ZhouC,xingQ,JieC,KeCh) values
(@XueN,@XueQ,@Banj,@ZhouC,@XingQ,@jieC,@KeCH)
if @@error<>0
begin
raiserror('error',16,1) --異常處理
rollback transaction
end
FETCH NEXT FROM my_cursor --繼續處理下一條記錄
INTO @XingQ, @JieC,@KeCH
end
CLOSE my_cursor --關閉遊標
DEALLOCATE my_cursor --釋放遊標
end
end
以上示例的插入过程其实可以用Insert into语句来代替,更显得简洁高效,之所以我用游标,是随手拿过来举了个游标应用的例子而已,既然有人提出疑问,那我就再把另外一种解法写出来吧。(2005.1.31)
create procedure foo
@XueN int, --外部輸入
@XueQ int,
@banj int,
@Zhouc int
as
declare @JieC int, --內部變量
@XingQ int,
@KeCh char(200)
begin
--先嚐試從調課表中搜索資料並對實時課表進行更新操作
update T_SSKB set kech=TK.shijkch,BeiZh=TK.TiaoKYY from T_SSKB KB,T_TK TK where
TK.XueN=@XueN and TK.XueQ=@XueQ and TK.banj=@Banj and TK.ZhouC=@ZhouC
and KB.XueN=TK.XueN and KB.XUEQ=TK.XueQ and KB.banJ=TK.banJ and KB.ZhouC=TK.zhouC
and KB.XingQ=T_SSKB.XingQ and KB.JieC=T_SSKB.JieC
--如果返回結果為0,說明調課表中沒有相關記錄,這時就從課程表中搜尋相關記錄進行插入操作
if @@RowCount=0
begin
--// 这里是直接用insert into 的方法
insert into T_SSKB select XueN, XueQ, BanJ, @ZhouC, XingQ, JieC, KeCh,Space(1) from T_KCB
where XueN=@XueN and XueQ=@XueQ and banj=@Banj
--//
if @@error=0
begin
raiserror('error',16,1)
rollback transaction
end
end
end
@XueN int, --外部輸入
@XueQ int,
@banj int,
@Zhouc int
as
declare @JieC int, --內部變量
@XingQ int,
@KeCh char(200)
begin
--先嚐試從調課表中搜索資料並對實時課表進行更新操作
update T_SSKB set kech=TK.shijkch,BeiZh=TK.TiaoKYY from T_SSKB KB,T_TK TK where
TK.XueN=@XueN and TK.XueQ=@XueQ and TK.banj=@Banj and TK.ZhouC=@ZhouC
and KB.XueN=TK.XueN and KB.XUEQ=TK.XueQ and KB.banJ=TK.banJ and KB.ZhouC=TK.zhouC
and KB.XingQ=T_SSKB.XingQ and KB.JieC=T_SSKB.JieC
--如果返回結果為0,說明調課表中沒有相關記錄,這時就從課程表中搜尋相關記錄進行插入操作
if @@RowCount=0
begin
--// 这里是直接用insert into 的方法
insert into T_SSKB select XueN, XueQ, BanJ, @ZhouC, XingQ, JieC, KeCh,Space(1) from T_KCB
where XueN=@XueN and XueQ=@XueQ and banj=@Banj
--//
if @@error=0
begin
raiserror('error',16,1)
rollback transaction
end
end
end
最后说明:需要注意的是,在使用“Insert into table1 select * from table2”句式做插入查询的时候,如果两个表定义的字段不一样,必须在select中使用显示的字段以满足table1的字段定义来代替“ * ”号。
轉載請注明出版:cnblogs(Bonny.Wong) 2005.1.27