Oracle下Cursor的使用

前端之家收集整理的这篇文章主要介绍了Oracle下Cursor的使用前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

总结下Cursor 各种用法


首先创建一个表

  1. createtableemp
  2. (
  3. empnovarchar2(8),enamevarchar2(8),jobvarchar2(8),salvarchar2(8)
  4. )

然后插入几行数据 ,就可以运行以下存储过程了 。

  1. --声明游标;CURSORcursor_nameISselect_statement
  2.  
  3. --For循环游标
  4. --(1)定义游标
  5. --(2)定义游标变量
  6. --(3)使用for循环来使用这个游标
  7. SETSERVEROUTPUTON
  8. declare
  9. --类型定义
  10. cursorc_job
  11. is
  12. selectempno,ename,job,sal
  13. fromemp
  14. wherejob='MANAGER';
  15. --定义一个游标变量v_cinfoc_emp%ROWTYPE,该类型为游标c_emp中的一行数据类型
  16. c_rowc_job%rowtype;
  17. begin
  18. forc_rowinc_jobloop
  19. dbms_output.put_line(c_row.empno||'-'||c_row.ename||'-'||c_row.job||'-'||c_row.sal);
  20. endloop;
  21. end;
  22.  
  23. --运行结果:
  24. 111-aaaa-MANAGER-running
  25. 333-ccc-MANAGER-swimming
  26. 444-ddd-MANAGER-running
  27. 1000-fff-MANAGER-swimming
  28. 888-hhh-MANAGER-swimming
  29. 777-iii-MANAGER-running
  30.  
  31. PL/sqlproceduresuccessfullycompleted
  32.  
  33. --oralce的%rowtype解释:表示该类型为行数据类型,存储的是一行数据,一行数据里可以有多列,类似于表里的一行数据,也可以是游标里的一行数据,如:
  34. --vs_row1表%rowtype;
  35. --vs_row2游标%rowtype;
  36.  
  37. --dbms_output.put_line的使用方法
  38. setserveroutputon
  39. begin
  40. DBMS_OUTPUT.PUT_LINE('HELLO,THISISLUOSEA');
  41. END;
  42. /
  43.  
  44. --Fetch游标
  45. --使用的时候必须要明确的打开和关闭
  46.  
  47. declare
  48. --类型定义
  49. cursorc_job
  50. is
  51. selectempno,sal
  52. fromemp
  53. wherejob='MANAGER';
  54. --定义一个游标变量
  55. c_rowc_job%rowtype;
  56. begin
  57. openc_job;
  58. loop
  59. --提取一行数据到c_row
  60. fetchc_jobintoc_row;
  61. --判读是否提取到值,没取到值就退出
  62. --取到值c_job%notfoundfalse
  63. --取不到值c_job%notfoundtrue
  64. exitwhenc_job%notfound;
  65. dbms_output.put_line(c_row.empno||'-'||c_row.ename||'-'||c_row.job||'-'||c_row.sal);
  66. endloop;
  67. --关闭游标
  68. closec_job;
  69. end;
  70.  
  71. --1:任意执行一个update操作,用隐式游标sql属性%found,%notfound,%rowcount,%isopen观察update语句的执行情况。
  72. begin
  73. updateempsetENAME='ALEARK'WHEREEMPNO=888;
  74. ifsql%isopenthen
  75. dbms_output.put_line('Openging');
  76. else
  77. dbms_output.put_line('closing');
  78. endif;
  79. ifsql%foundthen
  80. dbms_output.put_line('游标指向了有效行');--判断游标是否指向有效行
  81. else
  82. dbms_output.put_line('Sorry');
  83. endif;
  84. ifsql%notfoundthen
  85. dbms_output.put_line('AlsoSorry');
  86. else
  87. dbms_output.put_line('Haha');
  88. endif;
  89. dbms_output.put_line(sql%rowcount);
  90. exception
  91. whenno_data_foundthen
  92. dbms_output.put_line('SorryNodata');
  93. whentoo_many_rowsthen
  94. dbms_output.put_line('TooManyrows');
  95. end;
  96. declare
  97. empNumberemp.EMPNO%TYPE;
  98. empNameemp.ENAME%TYPE;
  99. begin
  100. ifsql%isopenthen
  101. dbms_output.put_line('Cursorisopinging');
  102. else
  103. dbms_output.put_line('CursorisClose');
  104. endif;
  105. ifsql%notfoundthen
  106. dbms_output.put_line('NoValue');
  107. else
  108. dbms_output.put_line(empNumber);
  109. endif;
  110. dbms_output.put_line(sql%rowcount);
  111. dbms_output.put_line('-------------');
  112.  
  113. selectEMPNO,ENAMEintoempNumber,empNamefromempwhereEMPNO=7499;
  114. dbms_output.put_line(sql%rowcount);
  115.  
  116. ifsql%isopenthen
  117. dbms_output.put_line('Cursorisopinging');
  118. else
  119. dbms_output.put_line('CursorisClosing');
  120. endif;
  121. ifsql%notfoundthen
  122. dbms_output.put_line('NoValue');
  123. else
  124. dbms_output.put_line(empNumber);
  125. endif;
  126. exception
  127. whenno_data_foundthen
  128. dbms_output.put_line('NoValue');
  129. whentoo_many_rowsthen
  130. dbms_output.put_line('toomanyrows');
  131. end;
  132.  
  133.  
  134.  
  135. --2,使用游标和loop循环来显示所有部门的名称
  136. --游标声明
  137. declare
  138. cursorcsr_dept
  139. is
  140. --select语句
  141. selectDNAME
  142. fromDepth;
  143. --指定行指针,这句话应该是指定和csr_dept行类型相同的变量
  144. row_deptcsr_dept%rowtype;
  145. begin
  146. --for循环
  147. forrow_deptincsr_deptloop
  148. dbms_output.put_line('部门名称:'||row_dept.DNAME);
  149. endloop;
  150. end;
  151.  
  152.  
  153. --3,使用游标和while循环来显示所有部门的的地理位置(用%found属性
  154. declare
  155. --游标声明
  156. cursorcsr_TestWhile
  157. is
  158. --select语句
  159. selectLOC
  160. fromDepth;
  161. --指定行指针
  162. row_loccsr_TestWhile%rowtype;
  163. begin
  164. --打开游标
  165. opencsr_TestWhile;
  166. --给第一行喂数据
  167. fetchcsr_TestWhileintorow_loc;
  168. --测试是否有数据,并执行循环
  169. whilecsr_TestWhile%foundloop
  170. dbms_output.put_line('部门地点:'||row_loc.LOC);
  171. --给下一行喂数据
  172. fetchcsr_TestWhileintorow_loc;
  173. endloop;
  174. closecsr_TestWhile;
  175. end;
  176. select*fromemp
  177.  
  178.  
  179.  
  180.  
  181. --4,接收用户输入的部门编号,用for循环和游标,打印出此部门的所有雇员的所有信息(使用循环游标)
  182. --CURSORcursor_name[(parameter[,parameter],...)]ISselect_statement;
  183. --定义参数的语法如下:Parameter_name[IN]data_type[{:=|DEFAULT}value]
  184.  
  185. declare
  186. CURSOR
  187. c_dept(p_deptNonumber)
  188. is
  189. select*fromempwhereemp.depno=p_deptNo;
  190. r_empemp%rowtype;
  191. begin
  192. forr_empinc_dept(20)loop
  193. dbms_output.put_line('员工号:'||r_emp.EMPNO||'员工名:'||r_emp.ENAME||'工资:'||r_emp.SAL);
  194. endloop;
  195. end;
  196. select*fromemp
  197. --5:向游标传递一个工种,显示此工种的所有雇员的所有信息(使用参数游标)
  198. declare
  199. cursor
  200. c_job(p_jobnvarchar2)
  201. is
  202. select*fromempwhereJOB=p_job;
  203. r_jobemp%rowtype;
  204. begin
  205. forr_jobinc_job('CLERK')loop
  206. dbms_output.put_line('员工号'||r_job.EMPNO||''||'员工姓名'||r_job.ENAME);
  207. endloop;
  208. end;
  209. SELECT*FROMEMP
  210.  
  211. --6:用更新游标来为雇员加佣金:(用if实现,创建一个与emp表一摸一样的emp1表,对emp1表进行修改操作),并将更新前后的数据输出出来
  212. --http://zheng12tian.iteye.com/blog/815770
  213. createtableemp1asselect*fromemp;
  214.  
  215. declare
  216. cursor
  217. csr_Update
  218. is
  219. select*fromemp1forupdateOFSAL;
  220. empInfocsr_Update%rowtype;
  221. saleInfoemp1.SAL%TYPE;
  222. begin
  223. FORempInfoINcsr_UpdateLOOP
  224. IFempInfo.SAL<1500THEN
  225. saleInfo:=empInfo.SAL*1.2;
  226. elsifempInfo.SAL<2000THEN
  227. saleInfo:=empInfo.SAL*1.5;
  228. elsifempInfo.SAL<3000THEN
  229. saleInfo:=empInfo.SAL*2;
  230. ENDIF;
  231. UPDATEemp1SETSAL=saleInfoWHERECURRENTOFcsr_Update;
  232. ENDLOOP;
  233. END;
  234.  
  235. --7:编写一个PL/sql程序块,对名字以‘A’或‘S’开始的所有雇员按他们的基本薪水(sal)的10%给他们加薪(对emp1表进行修改操作)
  236. declare
  237. cursor
  238. csr_AddSal
  239. is
  240. select*fromemp1whereENAMELIKE'A%'ORENAMELIKE'S%'forupdateOFSAL;
  241. r_AddSalcsr_AddSal%rowtype;
  242. saleInfoemp1.SAL%TYPE;
  243. begin
  244. forr_AddSalincsr_AddSalloop
  245. dbms_output.put_line(r_AddSal.ENAME||'原来的工资:'||r_AddSal.SAL);
  246. saleInfo:=r_AddSal.SAL*1.1;
  247. UPDATEemp1SETSAL=saleInfoWHERECURRENTOFcsr_AddSal;
  248. endloop;
  249. end;
  250. --8:编写一个PL/sql程序块,对所有的salesman增加佣金(comm)500
  251. declare
  252. cursor
  253. csr_AddComm(p_jobnvarchar2)
  254. is
  255. select*fromemp1whereJOB=p_jobFORUPDATEOFCOMM;
  256. r_AddCommemp1%rowtype;
  257. commInfoemp1.comm%type;
  258. begin
  259. forr_AddCommincsr_AddComm('SALESMAN')LOOP
  260. commInfo:=r_AddComm.COMM+500;
  261. UPDATEEMP1SETCOMM=commInfowhereCURRENTOFcsr_AddComm;
  262. ENDLOOP;
  263. END;
  264.  
  265. --9:编写一个PL/sql程序块,以提升2个资格最老的职员为MANAGER(工作时间越长,资格越老)
  266. --(提示:可以定义一个变量作为计数器控制游标只提取两条数据;也可以在声明游标的时候把雇员中资格最老的两个人查出来放到游标中。)
  267. declare
  268. cursorcrs_testComput
  269. is
  270. select*fromemp1orderbyHIREDATEasc;
  271. --计数器
  272. top_twonumber:=2;
  273. r_testComputcrs_testComput%rowtype;
  274. begin
  275. opencrs_testComput;
  276. FETCHcrs_testComputINTOr_testComput;
  277. whiletop_two>0loop
  278. dbms_output.put_line('员工姓名:'||r_testComput.ENAME||'工作时间:'||r_testComput.HIREDATE);
  279. --计速器减一
  280. top_two:=top_two-1;
  281. FETCHcrs_testComputINTOr_testComput;
  282. endloop;
  283. closecrs_testComput;
  284. end;
  285.  
  286.  
  287. --10:编写一个PL/sql程序块,对所有雇员按他们的基本薪水(sal)的20%为他们加薪,
  288. --如果增加的薪水大于300就取消加薪(对emp1表进行修改操作,并将更新前后的数据输出出来)
  289. declare
  290. cursor
  291. crs_UpadateSal
  292. is
  293. select*fromemp1forupdateofSAL;
  294. r_UpdateSalcrs_UpadateSal%rowtype;
  295. salAddemp1.sal%type;
  296. salInfoemp1.sal%type;
  297. begin
  298. forr_UpdateSalincrs_UpadateSalloop
  299. salAdd:=r_UpdateSal.SAL*0.2;
  300. ifsalAdd>300then
  301. salInfo:=r_UpdateSal.SAL;
  302. dbms_output.put_line(r_UpdateSal.ENAME||':加薪失败。'||'薪水维持在:'||r_UpdateSal.SAL);
  303. else
  304. salInfo:=r_UpdateSal.SAL+salAdd;
  305. dbms_output.put_line(r_UpdateSal.ENAME||':加薪成功.'||'薪水变为:'||salInfo);
  306. endif;
  307. updateemp1setSAL=salInfowherecurrentofcrs_UpadateSal;
  308. endloop;
  309. end;
  310.  
  311. --11:将每位员工工作了多少年零多少月零多少天输出出来
  312. --近似
  313. --CEIL(n)函数:取大于等于数值n的最小整数
  314. --FLOOR(n)函数:取小于等于数值n的最大整数
  315. --truc用法http://publish.it168.com/2005/1028/20051028034101.shtml
  316. declare
  317. cursor
  318. crs_WorkDay
  319. is
  320. selectENAME,HIREDATE,trunc(months_between(sysdate,hiredate)/12)ASSPANDYEARS,trunc(mod(months_between(sysdate,hiredate),12))ASmonths,trunc(mod(mod(sysdate-hiredate,365),12))asdays
  321. fromemp1;
  322. r_WorkDaycrs_WorkDay%rowtype;
  323. begin
  324. forr_WorkDayincrs_WorkDayloop
  325. dbms_output.put_line(r_WorkDay.ENAME||'已经工作了'||r_WorkDay.SPANDYEARS||'年,零'||r_WorkDay.months||'月,零'||r_WorkDay.days||'天');
  326. endloop;
  327. end;
  328.  
  329. --12:输入部门编号,按照下列加薪比例执行(用CASE实现,创建一个emp1表,修改emp1表的数据),并将更新前后的数据输出出来
  330. --deptnoraise(%)
  331. --105%
  332. --2010%
  333. --3015%
  334. --4020%
  335. --加薪比例以现有的sal为标准
  336. --CASEexprWHENcomparison_exprTHENreturn_expr
  337. --[,WHENcomparison_exprTHENreturn_expr]...[ELSEelse_expr]END
  338. declare
  339. cursor
  340. crs_caseTest
  341. is
  342. select*fromemp1forupdateofSAL;
  343. r_caseTestcrs_caseTest%rowtype;
  344. salInfoemp1.sal%type;
  345. begin
  346. forr_caseTestincrs_caseTestloop
  347. case
  348. whenr_caseTest.DEPNO=10
  349. THENsalInfo:=r_caseTest.SAL*1.05;
  350. whenr_caseTest.DEPNO=20
  351. THENsalInfo:=r_caseTest.SAL*1.1;
  352. whenr_caseTest.DEPNO=30
  353. THENsalInfo:=r_caseTest.SAL*1.15;
  354. whenr_caseTest.DEPNO=40
  355. THENsalInfo:=r_caseTest.SAL*1.2;
  356. endcase;
  357. updateemp1setSAL=salInfowherecurrentofcrs_caseTest;
  358. endloop;
  359. end;
  360.  
  361. --13:对每位员工的薪水进行判断,如果该员工薪水高于其所在部门的平均薪水,则将其薪水减50元,输出更新前后的薪水,员工姓名,所在部门编号。
  362. --AVG([distinct|all]expr)over(analytic_clause)
  363. ---作用:
  364. --按照analytic_clause中的规则求分组平均值。
  365. --分析函数语法:
  366. --FUNCTION_NAME(<argument>,<argument>...)
  367. --OVER
  368. --(<Partition-Clause><Order-by-Clause><WindowingClause>)
  369. --PARTITION子句
  370. --按照表达式分区(就是分组),如果省略了分区子句,则全部的结果集被看作是一个单一的组
  371. select*fromemp1
  372. DECLARE
  373. CURSOR
  374. crs_testAvg
  375. IS
  376. selectEMPNO,ENAME,JOB,SAL,DEPNO,AVG(SAL)OVER(PARTITIONBYDEPNO)ASDEP_AVG
  377. FROMEMP1forupdateofSAL;
  378. r_testAvgcrs_testAvg%rowtype;
  379. salInfoemp1.sal%type;
  380. begin
  381. forr_testAvgincrs_testAvgloop
  382. ifr_testAvg.SAL>r_testAvg.DEP_AVGthen
  383. salInfo:=r_testAvg.SAL-50;
  384. endif;
  385. updateemp1setSAL=salInfowherecurrentofcrs_testAvg;
  386. endloop;
  387. end;

猜你在找的Oracle相关文章