oracle系列(一)-- 常用脚本汇总--过程、函数、流程控制、触发器

  1 select  *  from emp;
  2 
  3 --分页查询
  4 select rownum,empno from  emp where rownum>0;
  5 select *  from(
  6        select  empno,rownum r from emp 
  7 )e where r>10 and r<13
  8 
  9                   ---PL/SQL入门--声明-type-rowtype-record-view-table
 10 
 11 /*
 12   PL/SQL语言
 13 */
 14 
 15 declare  --定义部分
 16    v_name varchar2(20);--变量的 声明: 变量名 变量类型
 17    v_sal number(10,2);
 18 begin--执行部分
 19   v_name := 'lxm'; --变量
 20   select ename ,sal into v_name,v_sal from emp where empno=&eno;--这里empno不写死的话,后边可以自己输入值
 21   dbms_output.put_line(v_name||v_sal);
 22 end;
 23 select  *  from emp where empno=&eno;
 24 
 25 
 26 
 27 /*
 28   万能类型
 29   将一个字段的类型作为一个数据类型
 30 */
 31 declare
 32     v_name emp.job%type; --定义v_name的数据类型和emp里的job字段类型相同
 33 begin
 34 
 35   select job  into v_name from emp  where empno=7788;
 36   dbms_output.put_line(v_name);
 37 end;
 38 
 39 
 40 /*
 41   万能类型
 42   将一行数据分别对应的类型作为一个打的数据类型
 43 */
 44 declare
 45    v_rowdemo emp%rowtype; --定义变量的数据类型和emp整行的数据类型
 46                           --那么emp有几个字段,v_rowdemo就会有几个字段
 47 begin
 48    select * into v_rowdemo from emp where empno=7788;
 49    dbms_output.put_line(v_rowdemo.ename||v_rowdemo.sal);--输出时使用变量.列名,直接输出整个变量会报错
 50  end;
 51 
 52 
 53 
 54 
 55 /*
 56  record,是自己声明的一种一行多列的数据类型
 57   使用一个变量,存储员工姓名和员工所在的部门名称
 58 
 59 */
 60 
 61 declare
 62  --emp_info_record 是一个类型  相当于varchar
 63    type emp_info_record is record(
 64         v_ename varchar(30),
 65         v_dname varchar2(30)
 66    );
 67   v_emp_info  emp_info_record;
 68 begin
 69  
 70 
 71 /*
 72   视图,
 73   相当于一个虚表,查询结果被放在视图里。下次查东西可以直接从这里边查
 74   scott默认没有创建视图的权限,所以要先以管理员身份登录给他赋权限
 75   grant create view to scott
 76   授权之后,scott用户就有了创建视图的权限
 77 */
 78 create view myview --create view  视图名
 79 as
 80 select empno,ename,sal from emp;
 81 --视图创建成功,可以从其中查数据
 82 select  empno  from  myview
 83 
 84 
 85 /*
 86    %record
 87 */
 88 declare
 89    type emp_record_type is record( --定义record
 90         ename emp.ename%type,
 91         sal emp.sal%type,
 92         comm emp.comm%type,
 93         total_sal emp.sal%type
 94    );
 95    v_emp_record emp_record_type; --声明一个record
 96 begin 
 97    select ename,sal,nvl(comm,0),sal+nvl(comm,0) --执行查询
 98    into v_emp_record
 99    from emp where empno=7369;
100    dbms_output.put_line('姓名:'||v_emp_record.ename);
101    dbms_output.put_line('薪水:'||v_emp_record.sal);
102    dbms_output.put_line('奖金:'||v_emp_record.comm);
103    dbms_output.put_line('总薪水:'||v_emp_record.total_sal);
104 end;
105 
106 
107 /*
108    table数据类型
109 */
110 declare --定义一个table类型
111    type dept_table_type is table of dept%rowtype--type table名字 is table of table类型 
112    index by binary_integer; --将主键定义为二进制
113    v_dept_table dept_table_type;
114 begin
115   select * into v_dept_table(0) from dept where deptno=10; --每次将一行主句赋值给table的另一行
116   select * into v_dept_table(1) from dept where deptno=20;                              
117   dbms_output.put_line('部门编号: '||v_dept_table(0).deptno||'  部门名称:'
118                        ||v_dept_table(0).dname||'  位置:'||v_dept_table(0).loc);
119   dbms_output.put_line('部门编号: '||v_dept_table(1).deptno||'  部门名称:'
120                        ||v_dept_table(1).dname||'  位置:'||v_dept_table(1).loc);
121   end;
122 
123 
124 /*
125   批量赋值 
126   bulk:体积、大块
127   collect:搜集、收集
128   bulk collect into 相当于批量赋值
129 */
130 declare
131   type v_dept_table is table of dept%rowtype
132   index by binary_integer;
133   v_dept v_dept_table;
134 begin
135   --select *  bulk collect into 表明 from 表名
136   select *  bulk collect into v_dept from dept; --将所有的数据赋值给v_dept
137   dbms_output.put_line(v_dept(2).dname); --取的时候,取自己想要的
138 end;
139 
140 
141 
142                               --------------流程控制-----------------------
143 /*
144   if循环
145   相当于 if循环
146   if(n==5)
147       输出n
148       
149   ---
150   if 
151      条件1 then
152          执行语句1;
153      elsif 条件2 then
154          执行语句2;
155      else
156        执行语句;  
157    end if;
158 */
159 declare
160    v_n number := 4;
161 begin
162   if v_n=5 then
163     dbms_output.put_line(v_n);
164   elsif v_n=4 then  --注意oracle里没有else if,只有elsif,不要错误写成elseif
165     dbms_output.put_line('44444is'||v_n);
166    else
167      dbms_output.put_line('未知数');
168   end if;
169 end;
170 
171 
172 
173 /*
174   case循环
175   case 变量
176     when 条件 then 执行语句;
177     when 条件 then 执行语句;
178     else 执行语句
179    end case
180 */
181 
182 declare
183   v_deptno dept.deptno%type:=&deptno;
184 begin
185   case v_deptno
186     when 10 then dbms_output.put_line('我的部门是:  '||v_deptno);
187     when 20 then dbms_output.put_line('我的部门是:  '||v_deptno);
188     when 30 then dbms_output.put_line('我的部门是:  '||v_deptno);
189     when 40 then dbms_output.put_line('我的部门是:  '||v_deptno);
190     else dbms_output.put_line('不存在该部门');
191   end case;
192  end;
193 
194 
195 /*
196  loop循环
197  loop
198    [exit when 条件]
199  end loop;
200  
201  相当于do while循环,先执行一次,再判断是否满足条件
202 */
203 declare
204  v_n number := 10;
205 begin
206   loop
207     v_n := v_n-1; --oracle中没有 v_n--;没有自减
208     dbms_output.put_line(v_n);
209     --exit when v_n=0;
210     if v_n=0 then exit;
211     end if;
212    end loop;
213 end;
214 
215 
216 /*
217    loop 循环和for循环嵌套
218    for n in 1..10表明n在[1,10]之间
219    reverse 表示降序排列,
220 */
221 
222 
223 begin
224  -- for n in 1..10 
225     for n in reverse 1..10 --inverse代表逆序
226     loop
227       dbms_output.put_line(n);
228      end loop;
229   end;
230 
231 
232 /*
233 `相当于while循环
234   while 条件 loop
235     执行语句
236   end loop
237 */
238 declare 
239   v_n number := 10;
240 begin
241   while v_n>0 loop
242     v_n := v_n-1;
243     dbms_output.put_line('n是: '||v_n);
244   end loop;
245 end;
246 
247 
248                                         --游标--
249 /*
250    定义游标:cursor 游标名字 is select_statement
251    打开游标:open  游标名字
252   提取游标数据:fetch 游标名字 into 
253   关闭游标:close 游标名字
254   
255   显式游标:处理select语句返回的多行数据
256           1):显示游标属性:
257              %ISOPEN:游标是否打开,打开为true,关闭为false
258              %FOUND:检查是否从结果集中提取到数据,提取到为true,没有提取到为false
259              %NOTFOUND:与%FOUND相反,此外 还可以用这个属性退出循环
260              %ROWCOUNT返回当前位置已经提取到的实际行数
261              属性使用方法 游标名+属性
262              
263            2):带有参数的游标,多处使用游标,传入不同的参数时,获得不同的结果
264              cursor 游标名字 (参数名字,参数类型) is select_statement
265              定义时必须声明参数的数据类型,而不能定义参数的长度
266   隐式游标:用来处理select into 和DML语句
267 */
268 
269 --显示游标
270 --eg1:
271 declare
272   v_dept dept%rowtype;
273   cursor cur_dept is select  *  from dept where deptno>10; --声明游标
274 begin
275   open cur_dept;  --打开游标
276   loop
277     fetch cur_dept into v_dept; --提取数据
278     exit when cur_dept%NOTFOUND;
279     dbms_output.put_line('编号:'||v_dept.deptno||' 名字:'||v_dept.dname||'  位置:'||v_dept.loc);
280   end loop;
281   close cur_dept;
282 end;
283 
284 
285 --eg2:用table结构提取游标数据
286   declare
287       type v_dept is table of dept%rowtype 
288       index by binary_integer;  --声明表结构
289       cursor cur_dept is select  *  from dept;--声明游标
290       v_dept_table v_dept;--声明一个变量是v_dept类型的
291   begin
292      open cur_dept;
293      fetch cur_dept bulk collect into v_dept_table;--将游标中的数据批块放入到表里
294      close cur_dept; --数据已经拿到,就可以关闭游标
295      for i in v_dept_table.first..v_dept_table.last loop--遍历一个表结构就用 for in
296        dbms_output.put_line('位置:' ||v_dept_table(i).loc);--循环输出,就用下表
297      end loop;
298   end;
299 
300 --eg3:带参数的游标
301   declare
302      cursor cur_dpet(para_deptno number) is  --定义有参数的游标
303      select dname, loc  from dept where deptno=para_deptno;--将参数作为查询条件
304      dept_record cur_dpet%rowtype; --定义一个变量,类型和游标的行类型一直
305   begin
306     open cur_dpet(20); --打开游标,同时把参数传进去
307     loop
308         fetch cur_dpet into dept_record; --提取数据,放到dept_record里
309         exit when cur_dpet%notfound;
310         dbms_output.put_line(dept_record.dname||'  '||dept_record.loc);  
311     end loop;
312     close cur_dpet; --关闭游标
313   end;
314   
315   
316 
317 --eg4:for循环简化游标遍历,
318   --用for循环时,oracle会隐式打开游标并且提取数据后关闭,
319   declare 
320     cursor cur_dept is select *  from dept; 
321   begin
322     for cur_row in cur_dept loop --n相当于游标中存储的数据,所对应的一个个的行数据的对象
323       dbms_output.put_line('行编号是'||cur_dept%rowcount||'   部门名字是:'||cur_row.dname);
324     end loop;
325   end;
326   
327 --eg5:使用for循环时,游标可以更简化,声明、打开、关闭、都可以省略
328 
329   begin
330     for dept_row in(select dname,loc from dept) loop
331       dbms_output.put_line('部门位置是--:'||dept_row.loc);
332     end loop;
333   end;
334   
335  --游标变量--  
336  /*
337   游标和游标变量的区别
338     1):游标是数据库中一个命名的工作区,与固定的SQL语句相关联,在编译时是已知的,
339         是静态的,永远指向一个相同的查询工作区
340                  ---简而言之,对应的SELECT语句,在游标定义的时候,在declare声明部分就已经写好了
341     2):游标变量
342          A:语法
343                  type ref_type_name IS REF CURSOR; --先定义一个游标变量
344                  v_ref ref_type_name; 再声明一个变量,这个变量的类型是 上边定义好的游标变量的类型
345          B:游标变量在运行时可不同的SQL语句先关联,这样运行不同的SQL语句就可以引用不同的工作空间
346  */ 
347   
348  --eg:游标变量
349  declare
350          type ref_type_name is ref cursor;--定义
351          cur_emp ref_type_name; --定义游标的类型,是个游标变量
352          v_row emp%rowtype; --后边用,用来存储游标中的一行数据
353  begin
354    open cur_emp for select  *  from emp where empno=7369; --open for ,打开
355   loop
356     fetch cur_emp into v_row ;
357     exit when cur_emp%notfound;
358     dbms_output.put_line('行号:'||cur_emp%rowcount||'   部门编号:'||v_row.empno||';部门名字:'||v_row.ename);
359   end loop;
360  end;
361  
362  /*
363   隐式游标
364       跟显示游标不同的是,游标的定义,打开,数据提取,关闭,都是由数据库隐式来操作的
365       属性只有两个  SQL%FOUND, SQL%NOTFOUND
366  */
367  
368  declare
369       v_empno number(10) := 7369;
370  begin
371    update emp set ename='小绿绿' where empno=v_empno;
372    if sql%found then  --判断隐含游标sql是否有影响行数
373      dbms_output.put_line('修改成功');
374     else
375         dbms_output.put_line('修改失败,员工不存在');
376     end if;
377  end;
378 
379  
380                               ------触发器---
381 /*
382   create or replace trigger 触发器名字
383   before[after]
384   事件[update or delete or insert]
385   on 表名
386 
387   :new表和:old表
388   只有用了 for  each  row 才能用new ,old
389   new和old 相当于虚表
390   insert:新增,把新数据存到:new,再执行新增
391   delete:删除,把老数据存到:old,再执行删除
392   update:修改,把老数据存到:old,把新数据存到:new,判断:old和:new表中数据是否一样,
393                 一样不执行任何修改,不一样执行修改
394   
395   create or replace  trigger 触发器名字
396   before[after] --触发时机
397   update [delete、insert、select]操作的动作
398   on 表名
399   for each row --没触发一行就触发一次 触发器
400   begin
401     if(updating) then
402         执行语句
403     end if; 
404   end;
405 */
406 create or replace trigger  tri_dept
407 after --触发时机,before为之前,after为之后
408 update or delete  or insert  --哪些事件会触发 触发器
409 on dept  --对哪张表操作
410 for each row --每一行操作时都出发,如果不写,比如对整个表都进行修改,但只触发一次,
411              --写了这一句,sql语句设计到几行,就出发几次事件
412 begin
413    if(updating) then 
414        dbms_output.put_line('你出发的操作是update旧数据是: '||:old.loc);--old是原表中的数据
415        dbms_output.put_line('你出发的操作是update新数据是: '||:new.loc);--new是修改后的新数据
416    end if;
417     if(deleting) then
418        dbms_output.put_line('触发器触发delete...');
419     end if;
420     if(inserting) then
421        dbms_output.put_line('触发器触发insert');
422     end if;
423 end;
424 
425 
426 
427                                                  --存储过程--procedure
428 /*
429                  第一种 无参数的过程,
430     
431     语法:
432     create or repalace procedure 名字
433     is
434            声明部分
435     begin
436       执行部分
437       exception
438         异常处理部分
439      end;
440 */
441 
442 --一个没有exception的无参存储过程
443  create or replace  procedure pro_emp_sal--注意这里,过程名字后边没有()
444  is
445  begin
446    update dept set loc='sahgnhai' where deptno = 20;--
447   end;
448 
449 --一个有exception的无参存储过程  
450  create or replace procedure pro_sel_sal
451  is
452     v_sal number(10);
453  begin
454    select sal into v_sal from emp where deptno=70;
455    dbms_output.put_line(v_sal);
456    exception
457      when no_data_found then
458        dbms_output.put_line('员工编号不存在');
459  end;
460  
461  drop procedure pro_sel_sal; --删除 存储过程 drop procedure 过程名字
462  --调用无参过程的三种方法
463   call pro_sel_sal();--call 过程名字();
464   exec pro_emp_sal; --exec 过程名字;  但是这种方式只有再sqlplus 或者命令窗口中可以用,再plsql中不可以用
465   begin             --begin 过程名字; end;
466        pro_sel_sal;
467   end;
468 select *  from emp;
469 update dept set loc='aa' where deptno='40'
470 
471 
472 /*
473             有参的存储过程(如果不指定参数模式,默认为输入参数)
474             
475   有三种参数形式:
476     1):in传参 ,定义被in,输入参数,这个in可以不写,默认就是输入传参
477     2):out传参,该参数是用来输出的
478     3):in out 传参  该参数既用来输入,也用来输出
479    
480   有三种参数传递的形式
481    1):按照参数顺序依次放入参数
482    2):用=>传递参数 eg: pro_emp_sal(v_no=>'7369'); 注意,变量在前边,传过来的值在后边
483    3):混合方式传参,参数1,放在第一个位置,后边的参数用 =>传递参数
484    不管是哪种传参方式,被in,或者out,或者 inout修饰的参数,在调用的时候一定要声明
485 */
486 
487 /*
488   in传参 创建存储过程
489 */
490  create or replace procedure pro_emp_sal(v_no in emp.empno%type)
491  is
492   v_sal number(10);
493  begin
494    select sal into v_sal from emp where empno=v_no;
495    dbms_output.put_line(v_no ||' 的工资是:'||v_sal);
496     exception  
497       when no_data_found  then
498         dbms_output.put_line('请输入正确的员工编号');
499  end;
500      --调用 存储过程
501 declare
502  v_no number(10);    
503 begin
504  v_no := &empno;
505  pro_emp_sal(v_no);
506 end;
507 
508 
509 /*
510  out 传递参数的存储过程
511 */
512 create or replace procedure pro_sel_al(v_sal out emp.sal%type)
513 is
514 begin
515   select sal into v_sal  from emp where empno=7369;
516   dbms_output.put_line(v_sal);
517 end;
518    
519 --调用存储过程
520 declare
521  v_sals number(10);
522 begin
523   pro_sel_al(v_sal=>v_sals);-- =>传递参数
524 end;
525 
526 /*
527   in,out分别传递参数,的存储过程
528 */
529 create or replace procedure pro_emp_sal(v_no in emp.empno%type, v_sal out emp.sal%type)
530 is
531 begin
532   select sal into v_sal from emp where empno=v_no;
533   dbms_output.put_line('工资是: '||v_sal);
534 end;
535 
536 --调用 存储过程
537 declare
538    v_no emp.empno%type;
539    v_sal emp.sal%type;
540 begin
541   v_no := &no; --输入的变量一定要在执行的时候定义出输入
542  pro_emp_sal(v_no,v_sal); --按照参数位置传参
543 
544 end;
545 
546 /*
547   in out传递参数
548   在这里 in out 修饰同一个变量,则这个变量既是输入变量也是输出变量
549 */
550 create or replace procedure pro_emp_sal(empnum in out number)
551    is
552  begin
553    select  sal into empnum from emp where empno=empnum;
554  --  dbms_output.put_line(v_no ||'的工资是: '|| empnum);
555  end;
556 
557 --调用存储过程
558 declare
559  in_outnum emp.empno%type;
560 begin
561   in_outnum := &no;
562   pro_emp_sal(in_outnum);
563   dbms_output.put_line('工资是: '||in_outnum);
564 end;
565 
566                          
567 
568                              ----开发函数----
569 /*
570    create or replace function 名字()
571       return 返回值类型; --一定要有的
572      is[as]
573        变量声明部分
574     begin
575              执行语句
576              return 语句;  --一定要有
577        exception
578     end;
579 */
580 
581 create or replace function getsum(m number , n number)
582   return number
583   is
584   mn number;
585 begin
586   mn := m+n;
587   return mn;
588 end;
589        
590 --调用function
591 declare
592   m number;
593   n number;
594   mn number;
595 begin
596   m := &m;
597   n := &n;
598   mn := getsum(m,n);
599   dbms_output.put_line(mn);
600 end;
601 
602                             ---过程与函数的异同-------
603 /*
604     1:相同点
605         1):都用in模式传入数据,都用out模式传出数据
606         2):参数的传递都可以用位置传递法和名称传递法
607         3):输入参数时都可以有默认值,都可以传值
608         4):都有声明部分、执行部分、异常部分
609      2:不同点
610         1):没有返回值,或者只输出一个值时用function
611         2):输出多个值时用存储过程
612         3):输出多个值时也可以用function,但是这被认为是不规范的写作习惯
613         4):一般存储过程用来完成某个动作,function用来计算或者返回一个值
614 */
615                         --包--
616 /*
617   包存在的意义:满足oracle种模块化的需求,在大型项目中,每个模块有很多的过程和函数,不便于管理和维护
618   甚至造成误删,所以分包后便于管理,
619   解决了命名的问题,不同包里的函数或者过程可以命名相同
620   
621   
622   包头--语法:  --包头规范相当于java中的接口
623         create or replace package 包名 is
624                function 函数名() return 返回类型;
625                  procedure 过程名();
626         end 包名;
627    
628   包体--语法:   --包体规范相当于java中的接口实现
629   create or replace package body 包名 is
630          写function; (这里直接写,没有create or  replace 这句话)
631          写过程;(这里直接写,没有create or  replace 这句话)
632   end 包名
633   
634   --调用方法:
635   decalre
636     声明部分
637    begin
638      包名.函数名;
639      包名.过程名;
640    end;
641 */
642 --包头
643 create or replace package my_package is
644        function plus(m number, n number)  return number;
645        procedure cheng(x number, y number, xy out number);
646 end my_package;
647 
648 --包体
649 create or replace package body my_package is
650        function plus(m number, n number) return number
651          is  nm number;
652           begin
653                nm := m+n;
654            return nm;
655           end;
656        procedure cheng(x number, y number, xy out number)
657            is 
658            begin
659               xy := x+y;
660               dbms_output.put_line(xy);        
661            end;
662 end my_package;
663 --调用包里的方法
664 declare
665     cc number(10);
666 begin
667    -- cc:= my_package.plus(11,22);
668     --dbms_output.put_line('两个数的和是:'||cc);
669     my_package.cheng(11,2,xy=>cc);
670 end;
671 
672 /*
673     数据字典:user_source
674     跟用户相关的子程序和和源代码被存在里边
675     假如要查看 包名为my_package,的源代码
676     select  text  from user_source  where name='my_package';
677     删除子程序 :drop procedure proce_anme
678     删除包体: drop package body 包名
679     删除包头和包体 drop pacakge 包名
680 */
681 select text from user_source where name='MY_PACKAGE';
682 
683                   --------游标--------
684 
685 /*
686 
687    1:游标是啥?
688 
689     游标是指向上下文区的指针,它为应用提供了一种对具有多行查询结果集的数据,中
690 
691     的每一行分别进行单独处理的方法
692 
693 */
694 
695 declare
696 
697   v_dept dept%rowtype;
698 
699   cursor dept_cursor is select * from dept where deptno>10;  --定义游标
700 
701 begin
702 
703     open dept_cursor;  --打开游标
704 
705     loop
706 
707       fetch dept_cursor into v_dept;  --提取数据
708 
709       exit when dept_cursor%notfound;  --判断循环退出条件
710 
711       dbms_output.put_line('编号:'||v_dept.deptno
712 
713    ||'  名称:'||v_dept.dname||'  地址:'||v_dept.loc);
714 
715     end loop;
716 
717     close dept_cursor;  --关闭游标
718 
719 end;
720 
721  

猜你喜欢

转载自www.cnblogs.com/coisini/p/9768740.html