--oracle 练习; /**************************************************PL/SQL编程基础***************************************************************/ --firstday --》》》数据类型 -- Create table create table T_CSCUSTOMER ( CUST_NO VARCHAR2(12) primary key not null, PERSON_ID VARCHAR2(12), GROUP_NO VARCHAR2(12), CUST_ADDRESS_ID VARCHAR2(20), ORGANISEID VARCHAR2(10), CUST_NAME VARCHAR2(128), CUST_TYPE VARCHAR2(2), SERVE_PASSWORD VARCHAR2(128), REGIONCODE VARCHAR2(4), OPERATOR VARCHAR2(16), OPENDATE DATE, REMARK VARCHAR2(500), ADDRESS VARCHAR2(256), CUST_KIND VARCHAR2(4), LINKMAN VARCHAR2(64), LINKPHONE VARCHAR2(64), LINKMOBILE VARCHAR2(64), COMPANY_ID VARCHAR2(10), INSTALL_ADDRESS VARCHAR2(256) ) set serveroutput on --%TYPE类型 --SQL> declare var_ename t_cscustomer.cust_name%type; var_phone t_cscustomer.linkphone%type; begin SELECT cust_name,linkphone into var_ename,var_phone from t_cscustomer where cust_no=‘0061121890‘; dbms_output.put_line(var_ename||‘的电话是:‘||var_phone); end; / --SQL> declare var_ename varchar2(200); var_phone varchar2(200); begin SELECT cust_name,linkphone into var_ename,var_phone from t_cscustomer where cust_no=‘0061121890‘; dbms_output.put_line(var_ename||‘的电话是:‘||var_phone); end; / --record类型 --SQL> declare type emp_type is record ( var_ename varchar2(20), var_phone varchar2(20), var_sal varchar2(200) ); empinfo emp_type; begin select cust_name,linkphone,address into empinfo from t_cscustomer where cust_no=‘0110542709‘; dbms_output.put_line(‘雇员‘||empinfo.var_ename||‘的电话是‘||empinfo.var_phone||‘、地址是‘||empinfo.var_sal); end; / --%rowtype类型 --SQL> declare rowVar_emp t_cscustomer%rowtype; begin SELECT * into rowVar_emp FROM t_cscustomer where cust_no=‘0110542709‘; /*输出信息*/ dbms_output.put_line(‘雇员‘||rowVar_emp.cust_name||‘的电话是‘||rowVar_emp.linkphone||‘、地址是‘||rowVar_emp.address); end; / --变量 、常量 var_countryname varchar2(50):=‘中国‘; con_day constant integer:=365; --secondday --》》》流程控制 --if --SQL> declare var_name1 varchar2(20); var_name2 varchar2(20); begin var_name1:=‘East‘; var_name2:=‘xiaoke‘; if length(var_name1) < length(var_name2) then dbms_output.put_line(‘字符串“‘||var_name1||‘”的长度比字符串“‘||var_name2||‘”的长度小‘); end if; end; / --if elseif --SQL> declare num_age int :=55; begin if num_age>=56 then dbms_output.put_line(‘您可以申请退休了‘); elsif num_age<56 then dbms_output.put_line(‘您小于56岁,不可以申请退休!‘); else dbms_output.put_line(‘对不起,年龄不合法!‘); end if; end; / --SQL> declare num_age int :=55; aboutinfo varchar2(50); begin if num_age>=56 then aboutinfo:=‘您可以申请退休了‘; elsif num_age<56 then aboutinfo:=‘您小于56岁,不可以申请退休!‘; else aboutinfo:=‘对不起,年龄不合法!‘; end if; dbms_output.put_line(aboutinfo); end; / --case when --SQL> declare season int:=3; aboutinfo varchar2(50); begin case season when 1 then aboutinfo := season||‘季度包括1、2、3 月份‘; when 2 then aboutinfo := season||‘季度包括4、5、6 月份‘; when 3 then aboutinfo := season||‘季度包括7、8、9 月份‘; when 4 then aboutinfo := season||‘季度包括10、11、12 月份‘; else aboutinfo := season||‘季度不合法‘; end case; dbms_output.put_line(aboutinfo); end; / --》》》循环语句 --loop语句 一直运行到exit when end_condition_exp 为true时退出 declare sum_i int:=0; i int:=0; begin loop i:=i+1; sum_i :=sum_i + i; exit when i = 100; end loop; dbms_output.put_line(‘前100个自然数的和是:‘||sum_i); end; / --while 语句 declare sum_i int := 0; i int :=0; begin while i<100 loop i:=i+1; sum_i:=sum_i+i; end loop; dbms_output.put_line(‘前100个自然数的和是:‘||sum_i); end; / --for 语句 declare sum_i int:=0; begin for i in reverse 1..100 loop -- reverse 表示i从100递减 sum_i:= sum_i+i; end loop; dbms_output.put_line(‘前100个自然数的和是:‘||sum_i); end; / --》》》游标 /* 游标属性: cur_tmp%found 至少影响到一行数据为true; cur_tmp%notfound 与%found相反 cur_tmp%rowcount 返回受SQL语句影响的行数 cur_tmp%isopen 游标打开时为true */ --显示cursor set serveroutput on declare cursor cur_emp(var_name in varchar2:=‘lili‘) is select cust_no,cust_name,address from t_cscustomer where cust_name like var_name||‘%‘; type record_emp is record ( var_empno t_cscustomer.cust_no%type, var_empname t_cscustomer.cust_name%type, var_empaddress t_cscustomer.address%type ); emp_row record_emp; begin DBMS_OUTPUT.ENABLE(buffer_size => null); --表示输出buffer不受限制 open cur_emp(‘刘‘); fetch cur_emp into emp_row; while cur_emp%found loop dbms_output.put_line(emp_row.var_empname||‘的编号是‘||emp_row.var_empno||‘,地址是‘||emp_row.var_empaddress); fetch cur_emp into emp_row; end loop; close cur_emp; end; / --for 中使用cursor 不用进行打开游标、读取游标、关闭游标 oracle内部自动完成 declare type emp_type is record ( var_ename t_cscustomer.cust_name%type, var_phone t_cscustomer.linkphone%type, var_sal t_cscustomer.address%type ); empinfo emp_type; cursor cur_emp is select cust_name var_ename,linkphone var_phone,address var_sal from t_cscustomer where address like ‘%招南%0402室%‘; begin DBMS_OUTPUT.ENABLE(buffer_size => null); --表示输出buffer不受限制 --open cur_emp; --fetch cur_emp into empinfo; --dbms_output.put_line(‘共有数据‘||cur_emp%rowcount||‘条‘); for empinfo in cur_emp loop dbms_output.put_line(‘雇员‘||empinfo.var_ename||‘的电话是‘||empinfo.var_phone||‘、地址是‘||empinfo.var_sal); end loop; end; / declare cursor cur_emp is select cust_name var_ename,linkphone var_phone,address var_sal from t_cscustomer where address like ‘%招南%0402室%‘; begin DBMS_OUTPUT.ENABLE(buffer_size => null); --表示输出buffer不受限制 for empinfo in cur_emp loop dbms_output.put_line(‘雇员‘||empinfo.var_ename||‘的电话是‘||empinfo.var_phone||‘、地址是‘||empinfo.var_sal); end loop; end; / begin DBMS_OUTPUT.ENABLE(buffer_size => null); --表示输出buffer不受限制 for empinfo in (select cust_name var_ename,linkphone var_phone,address var_sal from t_cscustomer where address like ‘%招南%0402室%‘) loop dbms_output.put_line(‘雇员‘||empinfo.var_ename||‘的电话是‘||empinfo.var_phone||‘、地址是‘||empinfo.var_sal); end loop; end; / --》》》异常处理 /* 预定义异常 自定义异常 */ --预定义异常 declare var_empno t_cscustomer.cust_no%type; var_empname t_cscustomer.cust_name%type; begin select cust_no,cust_name into var_empno,var_empname from t_cscustomer where cust_no like ‘00%‘; if sql%found then dbms_output.put_line(‘雇员编号:‘||var_empno||‘、名称:‘||var_empname); end if; exception when too_many_rows then dbms_output.put_line(‘返回记录超过一行‘); when no_data_found then dbms_output.put_line(‘无数据记录‘); end; / --自定义异常 declare primary_iterant exception;--定义一个异常变量 pragma exception_init(primary_iterant,-00001);--关联错误号和异常变量名 begin insert into dept_tmp values(‘0‘,‘综合部‘,‘北京‘); dbms_output.put_line(‘采用默认值插入dept_tmp成功!‘); exception when primary_iterant then dbms_output.put_line(‘主键不允许重复!‘); end; / /**************************************************存储过程、函数、触发器、包***************************************************************/ --》》》存储过程 --查看错误 show errors; --创建或替换pro_insertTmp drop table dept_tmp; create table dept_tmp( DEPT_NO VARCHAR2(12) primary key not null, DEPT_NAME VARCHAR2(50), LOCATION VARCHAR2(200) ); create or replace procedure pro_insertTmp is begin insert into dept_tmp values(1,‘市场拓展部‘,‘join‘); commit; dbms_output.put_line(‘插入dept_tmp新记录成功‘); end pro_insertTmp; / --执行pro_insertTmp --execurte pro_insertTmp; exec pro_insertTmp; --程序块中调用pro_insertTmp set serverout on begin pro_insertTmp end; / --third day2015-02-03 /**存储过程参数过程包括:in 输入参数、out 输出参数、in out可被修改的输入参数,并作为输出参数**/ -->>in create or replace procedure pro_insertDept(v_deptno in varchar2,v_deptname in varchar2,v_loc in varchar2) is begin insert into dept_tmp values(v_deptno,v_deptname,v_loc); commit; dbms_output.put_line(‘通过in参数插入dept成功!‘); end pro_insertDept; / --不按顺序传入参数,指定参数值 begin pro_insertDept(v_deptname=>‘采购部‘,v_loc=>‘成都‘,v_deptno=>‘2‘); end; / --按顺序传入参数 begin pro_insertDept(‘3‘,‘市场部‘,‘深圳‘); end; / --混合传入参数 begin pro_insertDept(‘4‘,v_loc=>‘成都‘,v_deptname=>‘工程部‘); end; / -->>out create or replace procedure pro_selectDept(v_deptno in varchar2,v_deptname out dept_tmp.dept_name%type,v_loc out dept_tmp.location%type) is begin select dept_name,location into v_deptname,v_loc from dept_tmp where dept_no=v_deptno; exception when no_data_found then dbms_output.put_line(‘该编号的部门不存在!‘); end pro_selectDept; / set serveroutput on declare v_deptname dept_tmp.dept_name%type; v_loc dept_tmp.location%type; begin pro_selectDept(‘1‘,v_deptname,v_loc); --if v_deptname = ‘‘ then dbms_output.put_line(v_deptname||‘位于:‘||v_loc); --end if; end; / --执行 variable v_deptname varchar2(50); variable v_loc varchar2(50); exec pro_selectDept(‘2‘,:v_deptname,:v_loc); print v_deptname v_loc; select :v_deptname,:v_loc from dual; -->> in out create or replace procedure pro_square(num in out number,flag in boolean) is i int:=2; begin if flag then num := power(num,i); --计算平方 else num := sqrt(num); --计算平方根 end if; end pro_square; / declare n_number number; n_tmp number; b_flag boolean; begin b_flag:=false; n_tmp:=3; n_number:=n_tmp; pro_square(n_number,b_flag); if b_flag then dbms_output.put_line(n_tmp||‘的平方是:‘||n_number); else dbms_output.put_line(n_tmp||‘的平方根是:‘||n_number); end if; end; / --in 参数默认值 create or replace procedure pro_insertDeptDefault(v_deptno in varchar2,v_deptname in varchar2 default ‘综合部‘,v_loc in varchar2 default ‘北京‘) is primary_iterant exception;--定义一个异常变量 pragma exception_init(primary_iterant,-00001);--关联错误号和异常变量名 begin insert into dept_tmp values(v_deptno,v_deptname,v_loc); commit; dbms_output.put_line(‘采用默认值插入dept_tmp成功!‘); exception when primary_iterant then dbms_output.put_line(‘主键不允许重复!‘); end pro_insertDeptDefault; / --指定名称传值 declare row_dept dept_tmp%rowtype; begin pro_insertDeptDefault(‘5‘,v_loc => ‘太原‘); select * into row_dept from dept_tmp where dept_no=‘5‘; dbms_output.put_line(‘部门名称:‘||row_dept.dept_name||‘,位于:‘||row_dept.location); exception when no_data_found then dbms_output.put_line(‘未找到相关的数据!‘); end; / drop table t_emp; create table t_emp( emp_no number primary key not null, emp_name varchar2(20), age number, sal number, job varchar2(20), dept_no number, address varchar2(200), hiredate date ); insert into t_emp values(1,‘王力‘,22,9000,‘会计‘,3,‘深圳市北京路奥巴马号‘,sysdate); --》》》函数 create or replace function get_avg_pay(num_deptNo number) return number is num_avg_pay number; begin select avg(sal) into num_avg_pay from t_emp where dept_no=num_deptNo; return(round(num_avg_pay,2)); exception when no_data_found then dbms_output.put_line(‘该部门编号的员工不存在‘); return(0); end get_avg_pay; / --程序块中调用函数 declare avg_pay number; begin avg_pay:=get_avg_pay(3); dbms_output.put_line(‘编号为3的部门,平均工资是:‘||avg_pay); end; / --删除函数 drop function get_avg_pay; --》》》触发器 --语法格式 create or replace trigger tri_name [before|after|instead of] tri_event on table_name|view_name|user_name|db_name [for each row][when tri_condition] begin plsql_sentences; end tri_name; / create table dept_log( operate_tag varchar2(10), operate_time date ); --语句级触发器 create or replace trigger tri_dept before insert or update or delete on dept_tmp declare v_tag varchar2(20); begin if inserting then v_tag:=‘插入‘; elsif updating then v_tag:=‘修改‘; elsif deleting then v_tag:=‘删除‘; end if; insert into dept_log values(v_tag,sysdate); end tri_dept; / insert into dept_tmp values(6,‘业务咨询部‘,‘长春‘); update dept_tmp set location=‘沈阳‘ where dept_no=‘6‘; delete from dept_tmp where dept_no=‘6‘; --行级触发器 create table t_goods( id int primary key not null, good_name varchar2(50) ); create sequence seq_goods_id; --:new.id--列标识符,新值标识符用于标识当前行某个列的新值“:new.column_name”,通常在insert和update语句中使用 --:old.id--列标识符,原值标识符用于标识当前行某个列的原始值“:new.column_name”,通常在delete和update语句中使用 create or replace trigger tri_insert_goods before insert on t_goods for each row begin select seq_goods_id.nextval into :new.id from dual; end; / insert into t_goods(good_name) values(‘苹果‘); insert into t_goods(id,good_name) values(9,‘桃子‘); --替换触发器 --替换触发器定义在视图(一种数据库对象)上,而不是定义在表上。 create view view_emp_dept as select emp_no,emp_name,dept_tmp.dept_no,dept_name,job,hiredate from t_emp,dept_tmp where t_emp.dept_no=dept_tmp.dept_no; create or replace trigger tri_insert_view instead of insert on view_emp_dept for each row declare row_dept dept_tmp%rowtype; begin select * into row_dept from dept_tmp where dept_no=:new.dept_no; if sql%notfound then insert into dept_tmp(dept_no,dept_name) values(:new.dept_no,:new.dept_name); end if; insert into t_emp(emp_no,emp_name,dept_no,job,hiredate) values (:new.emp_no,:new.emp_name,:new.dept_no,:new.job,:new.hiredate); end tri_insert_view; / --rollback不能再触发器中使用 create or replace trigger tri_insert_view2 instead of insert on view_emp_dept for each row declare row_dept dept_tmp%rowtype; begin select * into row_dept from dept_tmp where dept_no=:new.dept_no; if sql%notfound then insert into dept_tmp(dept_no,dept_name) values(:new.dept_no,:new.dept_name); end if; insert into t_emp(emp_no,emp_name,dept_no,job,hiredate) values (:new.emp_no,:new.emp_name,:new.dept_no,:new.job,:new.hiredate); exception --when no_data_found then --dbms_output.put_line(‘部门表中未找到相对应的部门编号‘); --rollback; end tri_insert_view; / --若部门中没有编号10,会报错 insert into view_emp_dept(emp_no,emp_name,dept_no,dept_name,job,hiredate) values (8888,‘东方‘,10,‘ACCOUNTING‘,‘CASHIER‘,sysdate); commit; select * from view_emp_dept where emp_no=8888; --用户事件触发器 create table t_ddl_oper_log( db_obj_name varchar2(20), db_obj_type varchar2(20), oper_action varchar2(20), oper_user varchar2(20), oper_date date ); create or replace trigger tri_ddl_oper before create or drop or alter on liulei.schema begin insert into t_ddl_oper_log values(ora_dict_obj_name,ora_dict_obj_type,ora_sysevent,ora_login_user,sysdate); end; / create table t_test(id number); create view view_test as select emp_no,emp_name from t_emp; drop view view_test; select * from t_ddl_oper_log; --》》》程序包 --语法 规范 create or replace package pack_name is [declare_variable]; [declare_type]; [declare_cursor]; [declare_function]; [declare_procedure]; end [pack_name]; --创建一个程序包的“规范”,不包声明体的主体部分 create or replace package pack_emp is function fun_avg_sal(num_deptno number) return number;--获取指定部门的平均工资 procedure pro_regulate_sal(var_job varchar2,num_proportion number);--按照指定比例上调指定职务的工资 end pack_emp; / --语法 程序包主体 create or replace package body pack_name is [inner_variable] [cursor_body] [function_title] { begin fun_plsql; [exception] [dowith_sentences;] end [fun_name] } [procedure_title] { begin pro_plsql; [exception] [dowith_sentences;] end [pro_name] } ... end [pack_name] create or replace package body pack_emp is function fun_avg_sal(num_deptno number) return number is num_avg_sal number; begin select avg(sal) into num_avg_sal from t_emp where dept_no=num_deptno; return(num_avg_sal); exception when no_data_found then dbms_output.put_line(‘该部门编号不存在雇员记录!‘); return 0; end fun_avg_sal; procedure pro_regulate_sal(var_job varchar2,num_proportion number) is begin update t_emp set sal=sal*(1+num_proportion) where job=var_job; end pro_regulate_sal; end pack_emp; / --调用包 set serveroutput on declare num_deptno t_emp.dept_no%type; var_job t_emp.job%type; num_avg_sal t_emp.sal%type; num_proportion number; begin num_deptno:=5; num_avg_sal:=pack_emp.fun_avg_sal(num_deptno); dbms_output.put_line(num_deptno||‘号部门的平均工资是:‘||num_avg_sal); var_job := ‘SALEMAN‘; num_proportion:=0.1; pack_emp.pro_regulate_sal(var_job,num_proportion); end; /
时间: 2024-11-07 14:30:55