Oracle数据库之开发PL/SQL子程序和包
2015-07-08 21:32
411 查看
Oracle数据库之开发PL/SQL子程序和包
PL/SQL块分为匿名块与命名块,命名块又包含子程序、包和触发器。过程和函数统称为PL/SQL子程序,我们可以将商业逻辑、企业规则写成过程或函数保存到数据库中,以便共享。
过程和函数均存储在数据库中,并通过参数与其调用者交换信息。过程和函数的唯一区别是函数总向调用者返回数据,而过程不返回数据。
1.存储过程概念
存储过程(StoredProcedure)是在大型数据库系统中,一组为了完成特定功能的SQL语句集,存储在数据库中。经过第一次编译后再次调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。
存储过程是数据库中的一个重要对象,任何一个设计良好的数据库应用程序都应该用到存储过程。
2.创建过程
语法:
1CREATE[ORREPLACE]PROCEDURE[schema.]procedure_name 2[(parameter_declaration[,parameter_declaration]...)] 3[invoker_rights_clause] 4{IS|AS} 5{[declare_section]body|call_spec|EXTERNAL};
说明:
procedure_name:过程名称。
parameter_declaration:参数声明,格式如下:
parameter_name[[IN]datatype[{:=|DEFAULT}expression] |{OUT|INOUT}[NOCOPY]datatype
IN:输入参数。
OUT:输出参数。
INOUT:输入输出参数。
invoker_rights_clause:这个过程使用谁的权限运行,格式:
AUTHID{CURRENT_USER|DEFINER}
declare_section:声明部分。
body:过程块主体,执行部分。
一般只有在确认procedure_name过程是新过程或是要更新的过程时,才使用ORREPALCE关键字,否则容易删除有用的过程。
示例1:
1CREATEPROCEDUREremove_emp(employee_idNUMBER)AS 2tot_empsNUMBER; 3BEGIN 4DELETEFROMemployees 5WHEREemployees.employee_id=remove_emp.employee_id; 6tot_emps:=tot_emps-1; 7END;
示例2:
1CREATEORREPLACEPROCEDUREinsert_emp( 2v_empnoinemployees.employee_id%TYPE, 3v_firstnameinemployees.first_name%TYPE, 4v_lastnameinemployees.last_name%TYPE, 5v_deptnoinemployees.department_id%TYPE 6) 7AS 8empno_remainingEXCEPTION; 9PRAGMAEXCEPTION_INIT(empno_remaining,-1); 10BEGIN 11INSERTINTOEMPLOYEES(EMPLOYEE_ID,FIRST_NAME,LAST_NAME,HIRE_DATE,DEPARTMENT_ID) 12VALUES(v_empno,v_firstname,v_lastname,sysdate,v_deptno); 13DBMS_OUTPUT.PUT_LINE('插入成功!'); 14EXCEPTION 15WHENempno_remainingTHEN 16DBMS_OUTPUT.PUT_LINE('违反数据完整性约束!'); 17DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM); 18WHENOTHERSTHEN 19DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM); 20END;
3.使用过程参数
当建立过程时,既可以指定过程参数,也可以不提供任何参数。
过程参数包括输入参数、输出参数和输入输出参数,其中输入参数(IN)用于接收调用环境的输入数据,输出参数(OUT)用于将输出数据传递到调用环境,而输入输出参数(INOUT)不仅要接收输入数据,而且还要输出数据到调用环境。
3.1带有输入参数的过程
通过使用输入参数,可以将应用程序数据传递到过程。当定义过程参数时,默认参数模式是输入参数,另外可以使用IN关键字显式定义输入参数。
示例:
1CREATEORREPLACEPROCEDUREinsert_emp( 2empnoemployee.empno%TYPE, 3enameemployee.ename%TYPE, 4jobemployee.job%TYPE, 5salemployee.sal%TYPE, 6commINemployee.comm%TYPE, 7deptnoINemployee.deptno%TYPE 8) 9IS 10BEGIN 11INSERTINTOemployeeVALUES(empno,ename,job,sal,comm,depno); 12END;
3.2带有输出参数的过程
通过在过程中使用输出参数,可以将数据或消息传递到调用环境和应用程序。当定义输出参数时,需要指定参数模式OUT。
示例:
1CREATEORREPLACEPROCEDUREupdate_sal( 2enoNUMBER, 3salaryNUMBER, 4nameoutVARCHAR2) 5IS 6BEGIN 7UPDATEemployeeSETsal=salaryWHEREempno=eno 8RETURNINGenameINTOname; 9END;
3.3带有输入输出参数的过程
通过在过程中使用输入输出参数,可以在调用过程时输入数据到过程,在调用结束后输出数据到调用环境和应用程序。当定义输入输出参数时,需要指定参数模式为INOUT。
示例:
1CREATEORREPLACEPROCEDUREdivide( 2num1INOUTNUMBER, 3num2INOUTNUMBER) 4IS 5v1NUMBER; 6v2NUMBER; 7BEGIN 8v1:=trunc(num1/num2); 9v2:=mod(num1,num2); 10num1:=v1; 11num2:=v2; 12END;
4.调用过程
当在SQL*PLUS中调用过程时,需要使用CALL或者EXECUTE命令,而在PL/SQL块中过程可以直接引用。
ORACLE使用EXECUTE语句来调用存储过程语法:
1EXEC[UTE]procedure_name(parameter1,parameter2,…);
示例:
1--调用删除员工的过程 2EXECremove_emp(1); 3 4--调用插入员工的过程 5EXECUTEinsert_emp(1,'tommy','lin',2);
示例:
1DECLARE 2v_nameemployee.ename%type; 3BEGIN 4update_sal(&eno,&salary,v_name); 5dbms_output.put_line('姓名:'||v_name); 6END;
5.函数介绍
函数是一段独立的PL/SQL程序代码,它执行某个特定的、明确的任务。通常,函数将处理从程序的调用部分传递给它的信息,然后返回单个值。信息通过称为参数的特殊标识符传递给函数,然后通过RETURN语句返回。
6.创建函数
语法:
1CREATE[ORREPLACE]FUNCTION[schema.]function_name 2[(parameter_declaration[,parameter_declaration]...) 3] 4RETURNdatatype 5[{invoker_rights_clause 6|DETERMINISTIC 7|parallel_enable_clause 8|RESULT_CACHE[relies_on_clause] 9}... 10] 11{{AGGREGATE|PIPELINED}USING[schema.]implementation_type 12|[PIPELINED]{IS|AS}{[declare_section]body 13|call_spec 14|EXTERNAL 15} 16};
示例:
1CREATEFUNCTIONget_bal(acc_noINNUMBER) 2RETURNNUMBER 3IS 4acc_balNUMBER(11,2); 5BEGIN 6SELECTorder_totalINTOacc_balFROMorders 7WHEREcustomer_id=acc_no; 8RETURN(acc_bal); 9END;
函数参数也有输入、输出、输入输出三种模式:IN、OUT、INOUT是形参的模式。若省略,则为IN模式。
和过程一样,IN模式的形参只能将实参传递给形参,进入函数内部,但只能读不能写,函数返回时实参的值不变。
OUT模式的形参会忽略调用时的实参值(或说该形参的初始值总是NULL),但在函数内部可以被读或写,函数返回时形参的值会赋予给实参。
INOUT具有前两种模式的特性,即调用时,实参的值总是传递给形参,结束时,形参的值传递给实参。
调用时,对于IN模式的实参可以是常量或变量,但对于OUT和INOUT模式的实参必须是变量。
示例:
1CREATEORREPLACEFUNCTIONget_salary( 2dept_noINNUMBERDEFAULT1, 3emp_countOUTNUMBER) 4RETURNNUMBER 5IS 6V_sumNUMBER; 7BEGIN 8SELECTSUM(SALARY),count(*)INTOV_sum,emp_countFROMEMPLOYEES 9WHEREDEPARTMENT_ID=dept_no; 10RETURNv_sum; 11EXCEPTION 12WHENNO_DATA_FOUNDTHEN 13DBMS_OUTPUT.PUT_LINE('数据不存在'); 14WHENOTHERSTHEN 15DBMS_OUTPUT.PUT_LINE('其它异常:'); 16DBMS_OUTPUT.PUT_LINE('错误号:'||SQLCODE||',错误消息:'||SQLERRM); 17ENDget_salary;
7函数调用
语法:
1function_name([[parameter_name1=>]value1[,[parameter_name2=>]value2,...]]);
示例1:
1DECLARE 2v_numNUMBER; 3v_sumNUMBER; 4BEGIN 5v_sum:=get_salary(27,v_num); 6DBMS_OUTPUT.PUT_LINE('部门27的工资总和:'||v_sum||',人数为:'||v_num); 7END;
示例二:
1DECLARE 2v_numNUMBER; 3v_sumNUMBER; 4BEGIN 5v_sum:=get_salary(dept_no=>27,emp_count=>v_num); 6DBMS_OUTPUT.PUT_LINE('部门27的工资总和:'||v_sum||',人数为:'||v_num); 7END;
示例3:
1DECLARE 2v_numNUMBER; 3v_sumNUMBER; 4BEGIN 5v_sum:=get_salary(emp_count=>v_num); 6DBMS_OUTPUT.PUT_LINE('部门27的工资总和:'||v_sum||',人数为:'||v_num); 7END;
8.删除过程或函数
删除过程语法:
DROPPROCEDURE[schema.]procudure_name;
删除函数语法:
DROPFUNCTION[schema.]function_name;
9.过程与函数比较
过程 | 函数 |
---|---|
作为PL/SQL语句执行 | 作为表达式的一部分执行 |
在规范中不包含RETURN子句 | 必须在规范中包含RETURN子句 |
不返回任何值 | 必须返回单个值 |
可以RETURN语句,但是与函数不同,它不能用于返回值 | 必须包含至少一条RETURN语句 |
都使用IN模式的参数传入数据、OUT模式的参数返回数据。
输入参数都可以接受默认值,都可以传值或传引导。
调用时的实际参数都可以使用位置表示法、名称表示法或组合方法。
都有声明部分、执行部分和异常处理部分。
其管理过程都有创建、编译、授权、删除、显示依赖关系等。
--包
1.简介
包(PACKAGE)是一种数据对象,它是一组相关过程、函数、变量、常量和游标等PL/SQL程序设计元素的组合,作为一个完整的单元存储在数据库中,用名称来标识。
包类似于JAVA或C#语言中的类,包中的变量相当于类中的成员变量,过程和函数相当于类方法。
通过使用包,可以简化应用程序设计,提高应用性能,实现信息隐藏、子程序重载等面向对象语言所具有的功能。
与高级语言中的类相同,包中的程序元素也分为公用元素和私用元素两种,这两种元素的区别是他们允许访问的程序范围不同。公用元素不仅可以被包中的函数、过程所调用,也可以被包外的PL/SQL程序访问,而私有元素只能被包内的函数和过程序所访问。
一般是先编写独立的过程与函数,待其较为完善或经过充分验证无误后,再按逻辑相关性组织为程序包。
2.包的优点
模块化:使用包,可以封装相关的类型、对象和子程序。把一个大的功能模块划分成多个小的功能模块,分别完成各自的功能,这样组织的程序易于编写,理解和管理。
更轻松的应用程序设计:包规范部分和包体部分可以分别创建并编译。换言之,我们可以在没有编写包体的情况下编写包规范的代码并进行编译。
信息隐藏:包中的元素可以分为公有元素和私有元素,公有元素可被程序包内的过程、函数等访问,还可以被包外的PL/SQL访问。但对于私有元素只能被包内的过程、函数等访问。对于用户,只需知道包规范,不用了解包体的具体细节。
性能更佳:应用程序第一次调用程序包中的某个元素时,就将整个程序包加载到内存中,当第二次访问程序包中的元素时,ORACLE将直接从内在中读取,而不需要进行磁盘I/O操作而影响速度,同时位于内存中的程序包可被同一会话期间的其它应用程序共享。因此,程序包增加了重用性并改善了多用户、多应用程序环境的效率。
3.包的定义
PL/SQL中的包由包规范和包体两部分组成。建立包时,首先要建立包规范,然后再建立对包规范的实现–包体。
包规范用于声明包的公用组件,如变量、常量、自定义数据类型、异常、过程、函数、游标等。包规范中定义的公有组件不仅可以在包内使用,还可以由包外其他过程、函数使用。但需要说明与注意的是,为了实现信息的隐藏,建议不要将所有组件都放在包规范处声明,只应把公共组件放在包规范部分。
包体是包的具体实现细节,它实现在包规范中声明的所有公有过程、函数、游标等。也可以在包体中声明仅属于自己的私有过程、函数、游标等。
3.1建立包规范
语法:
1CREATE[ORREPLACE][EDITIONABLE|NONEDITIONABLE] 2PACKAGE[schema.]package_name 3[invoker_rights_clause] 4{IS|AS}item_list_1END[package_name];
item_list_1:声明包的公用组件列表
1{type_definition--数据类型 2|cursor_declaration--游标 3|item_declaration--变量、常量等 4|function_declaration--函数 5|procedure_declaration--过程 6} 7[{type_definition 8|cursor_declaration 9|item_declaration 10|function_declaration 11|procedure_declaration 12|pragma 13} 14]...
示例:
1CREATEORREPLACEPACKAGEemp_mgmtAS 2--函数 3FUNCTIONhire(last_nameVARCHAR2,job_idVARCHAR2, 4manager_idNUMBER,salaryNUMBER, 5commission_pctNUMBER,department_idNUMBER) 6RETURNNUMBER; 7FUNCTIONcreate_dept(department_idNUMBER,location_idNUMBER) 8RETURNNUMBER; 9--过程 10PROCEDUREremove_emp(employee_idNUMBER); 11PROCEDUREremove_dept(department_idNUMBER); 12PROCEDUREincrease_sal(employee_idNUMBER,salary_incrNUMBER); 13PROCEDUREincrease_comm(employee_idNUMBER,comm_incrNUMBER); 14--异常 15no_commEXCEPTION; 16no_salEXCEPTION; 17ENDemp_mgmt;
3.2建立包体 语法:
1CREATE[ORREPLACE]PACKAGEBODY[schema.]package_name 2{IS|AS} 3BEGINstatement[statement|pragma]... 4[EXCEPTIONexception_handler[exception_handler]...] 5[initialize_section] 6END[package_name];
示例:
1CREATEORREPLACEPACKAGEBODYemp_mgmtAS 2tot_empsNUMBER; 3tot_deptsNUMBER; 4FUNCTIONhire 5(last_nameVARCHAR2,job_idVARCHAR2, 6manager_idNUMBER,salaryNUMBER, 7commission_pctNUMBER,department_idNUMBER) 8RETURNNUMBERISnew_empnoNUMBER; 9BEGIN 10SELECTemployees_seq.NEXTVAL 11INTOnew_empno 12FROMDUAL; 13INSERTINTOemployees 14VALUES(new_empno,'First','Last','first.example@example.com', 15'(415)555-0100','18-JUN-02','IT_PROG',90000000,00, 16100,110); 17tot_emps:=tot_emps+1; 18RETURN(new_empno); 19END; 20FUNCTIONcreate_dept(department_idNUMBER,location_idNUMBER) 21RETURNNUMBERIS 22new_deptnoNUMBER; 23BEGIN 24SELECTdepartments_seq.NEXTVAL 25INTOnew_deptno 26FROMdual; 27INSERTINTOdepartments 28VALUES(new_deptno,'departmentname',100,1700); 29tot_depts:=tot_depts+1; 30RETURN(new_deptno); 31END; 32PROCEDUREremove_emp(employee_idNUMBER)IS 33BEGIN 34DELETEFROMemployees 35WHEREemployees.employee_id=remove_emp.employee_id; 36tot_emps:=tot_emps-1; 37END; 38PROCEDUREremove_dept(department_idNUMBER)IS 39BEGIN 40DELETEFROMdepartments 41WHEREdepartments.department_id=remove_dept.department_id; 42tot_depts:=tot_depts-1; 43SELECTCOUNT(*)INTOtot_empsFROMemployees; 44END; 45PROCEDUREincrease_sal(employee_idNUMBER,salary_incrNUMBER)IS 46curr_salNUMBER; 47BEGIN 48SELECTsalaryINTOcurr_salFROMemployees 49WHEREemployees.employee_id=increase_sal.employee_id; 50IFcurr_salISNULL 51THENRAISEno_sal; 52ELSE 53UPDATEemployees 54SETsalary=salary+salary_incr 55WHEREemployee_id=employee_id; 56ENDIF; 57END; 58PROCEDUREincrease_comm(employee_idNUMBER,comm_incrNUMBER)IS 59curr_commNUMBER; 60BEGIN 61SELECTcommission_pct 62INTOcurr_comm 63FROMemployees 64WHEREemployees.employee_id=increase_comm.employee_id; 65IFcurr_commISNULL 66THENRAISEno_comm; 67ELSE 68UPDATEemployees 69SETcommission_pct=commission_pct+comm_incr; 70ENDIF; 71END; 72ENDemp_mgmt;
4.调用包的组件
包的名称是唯一的,但对于两个包中的公有组件的名称可以相同,用“包名.公有组件名“加以区分。
示例:
1DECLARE 2new_dnoNUMBER;--部门编号 3BEGIN 4--调用emp_mgmt包的create_dept函数创建部门: 5new_dno:=emp_mgmt.create_dept(85,100); 6DBMS_OUTPUT.PUT_LINE('部门编号:'||new_dno); 7 8--调用emp_mgmt包的increase_sal过程为员工加薪: 9emp_mgmt.increase_sal(23,800); 10END;
5.包中的游标
在包中使用无参游标,示例:
1--定义包规范 2CREATEORREPLACEPACKAGEPKG_STUIS 3CURSORgetStuInfoRETURNstuInfo%ROWTYPE; 4ENDPKG_STU; 5 6--定义包体 7CREATEORREPLACEPACKAGEBODYPKG_STUAS 8CURSORgetStuInfoRETURNstuInfo%ROWTYPEIS 9SELECT*FROMstuInfo; 10ENDPKG_STU; 11 12--调用包组件 13BEGIN 14FORstu_RecordINPKG_STU.getStuInfoLOOP 15DBMS_OUTPUT.PUT_LINE('学员姓名:'||stu_Record.name||',学号:'||stu_Record.id||',年龄:'||stu_Record.age); 16ENDLOOP; 17END;
在包中使用有参数的游标,示例:
1--定义包规范 2CREATEORREPLACEPACKAGEPKG_STUIS 3CURSORgetStuInfo(studentNoVARCHAR2)RETURNstuInfo%ROWTYPE; 4ENDPKG_STU; 5 6--定义包体 7CREATEORREPLACEPACKAGEBODYPKG_STUAS 8CURSORgetStuInfo(studentNoVARCHAR2)RETURNstuInfo%ROWTYPEIS 9SELECT*FROMstuInfoWHEREid=studentNo; 10ENDPKG_STU; 11 12--调用包组件 13BEGIN 14FORstu_RecordINPKG_STU.getStuInfo(2)LOOP 15DBMS_OUTPUT.PUT_LINE('学员姓名:'||stu_Record.name||',学号:'||stu_Record.id||',年龄:'||stu_Record.age); 16ENDLOOP; 17END;
由于游标变量是一个指针,其状态是不确定的,因此它不能随同包存储在数据库中,即不能在PL/SQL包中声明游标变量。但在包中可以创建游标变量参照类型,并可向包中的子程序传递游标变量参数。
示例:
1--创建包规范 2CREATEORREPLACEPACKAGECURROR_VARIBAL_PKGAS 3TYPEdept_cur_typeISREFCURSORRETURNdept%ROWTYPE;--强类型 4 5TYPEcur_typeISREFCURSOR;--弱类型 6 7PROCEDUREproc_open_dept_var( 8dept_curINOUTdept_cur_type, 9choiceINTEGERDEFAULT0, 10dept_noNUMBERDEFAULT50, 11dept_nameVARCHARDEFAULT'%'); 12END; 13 14--创建包体 15CREATEORREPLACEPACKAGEBODYCURROR_VARIBAL_PKG 16AS 17PROCEDUREproc_open_dept_var( 18dept_curINOUTdept_cur_type, 19choiceINTEGERDEFAULT0, 20dept_noNUMBERDEFAULT50, 21dept_nameVARCHARDEFAULT'%') 22IS 23BEGIN 24IFchoice=1THEN 25OPENdept_curFORSELECT*FROMdeptWHEREdeptno=dept_no; 26ELSIFchoice=2THEN 27OPENdept_curFORSELECT*FROMdeptWHEREdnameLIKEdept_name; 28ELSE 29OPENdept_curFORSELECT*FROMdept; 30ENDIF; 31ENDproc_open_dept_var; 32ENDCURROR_VARIBAL_PKG;
1定义一个过程,打开弱类型的游标变量:
2
3--定义过程
4CREATEORREPLACEPROCEDUREproc_open_cur_type(
5curINOUTCURROR_VARIBAL_PKG.cur_type,
6first_cap_in_table_nameCHAR)
7AS
8BEGIN
9IFfirst_cap_in_table_name='D'THEN
10OPENcurFORSELECT*FROMdept;
11ELSE
12OPENcurFORSELECT*FROMemp;
13ENDIF;
14ENDproc_open_cur_type;
1测试包中游标变量类型的使用:
2
3DECLARE
4dept_recDept%ROWTYPE;
5emp_recEmp%ROWTYPE;
6dept_curCURROR_VARIBAL_PKG.dept_cur_type;
7curCURROR_VARIBAL_PKG.cur_type;
8BEGIN
9DBMS_OUTPUT.PUT_LINE('游标变量强类型:');
10CURROR_VARIBAL_PKG.proc_open_dept_var(dept_cur,1,30);
11FETCHdept_curINTOdept_rec;
12WHILEdept_cur%FOUNDLOOP
13DBMS_OUTPUT.PUT_LINE(dept_rec.deptno||':'||dept_rec.dname);
14FETCHdept_curINTOdept_rec;
15ENDLOOP;
16CLOSEdept_cur;
17
18DBMS_OUTPUT.PUT_LINE('游标变量弱类型:');
19CURROR_VARIBAL_PKG.proc_open_dept_var(cur,2,dept_name=>'A%');
20FETCHcurINTOdept_rec;
21WHILEcur%FOUNDLOOP
22DBMS_OUTPUT.PUT_LINE(dept_rec.deptno||':'||dept_rec.dname);
23FETCHcurINTOdept_rec;
24ENDLOOP;
25
26DBMS_OUTPUT.PUT_LINE('游标变量弱类型—dept表:');
27proc_open_cur_type(cur,'D');
28FETCHcurINTOdept_rec;
29WHILEcur%FOUNDLOOP
30DBMS_OUTPUT.PUT_LINE(dept_rec.deptno||':'||dept_rec.dname);
31FETCHcurINTOdept_rec;
32ENDLOOP;
33
34DBMS_OUTPUT.PUT_LINE('游标变量弱类型—emp表:');
35proc_open_cur_type(cur,'E');
36FETCHcurINTOemp_rec;
37WHILEcur%FOUNDLOOP
38DBMS_OUTPUT.PUT_LINE(emp_rec.empno||':'||emp_rec.ename);
39FETCHcurINTOemp_rec;
40ENDLOOP;
41CLOSEcur;
42END;
6.子程序重载
所谓重载时指两个或多个子程序有相同的名称,但拥有不同的参数变量、参数顺序或参数数据类型。
在调用重载子程序时,主程序将根据实际参数的类型和数目,自动确定调用哪个子程序。
PL/SQL允许对包内子程序和本地子程序进行重载。
示例:
1--定义包规范
2CREATEORREPLACEPACKAGEPKG_EMPAS
3FUNCTIONget_salary(enoNUMBER)RETURNNUMBER;
4FUNCTIONget_salary(empnameVARCHAR2)RETURNNUMBER;
5ENDPKG_EMP;
6
7--定义包体
8CREATEORREPLACEPACKAGEBODYPKG_EMPAS
9FUNCTIONget_salary(enoNUMBER)RETURNNUMBER
10IS
11v_salaryNUMBER(10,4);
12BEGIN
13SELECTsalINTOv_salaryFROMempWHEREempno=eno;
14RETURNv_salary;
15END;
16
17FUNCTIONget_salary(empnameVARCHAR2)RETURNNUMBER
18IS
19v_salaryNUMBER(10,4);
20BEGIN
21SELECTsalINTOv_salaryFROMempWHEREename=empname;
22RETURNv_salary;
23END;
24ENDPKG_EMP;
1测试:
2
3DECLARE
4v_salNUMBER(10,4);
5BEGIN
6v_sal:=PKG_EMP.get_salary(7499);
7DBMS_OUTPUT.PUT_LINE('工资:'||v_sal);
8v_sal:=PKG_EMP.get_salary('MARTIN');
9DBMS_OUTPUT.PUT_LINE('工资:'||v_sal);
10END;
分类:
相关文章推荐
- Oracle EM错误,java.lang.Exception: Exception in sending Request :: null
- Oracle EM错误,java.lang.Exception: Exception in sending Request :: null 分类: Oracle 2015-07-08 21:24 44人阅读 评论(0) 收藏
- 完全卸载干净Oracle11g
- 完全卸载干净Oracle11g
- 【原创】遇到的若干MySQL与Oracle的区别小记(逐渐增加)
- oracle创建表空间、创建用户、赋权限命令
- Oracle Solaris 与 pci dss
- 关于支付卡行业数据安全标准pci dss 与 oracle database
- 八、Oracle事务
- oracle archivelog模式与非archivelog模式转换
- 七、Oracle分页
- conn system/orcl as sysdba ERROR: ORA-01031: insufficient privileges
- oracle schema object
- 六、Oracle表查询二
- 五、Oracle表查询一
- 四、Oracle 表的管理
- 三、Oracle用户管理二
- 二、Oracle用户管理一
- 一、Oracle sql*plus常用命令
- oracle exp(dmp)命令带过滤条件?