ORACLE PL/SQL基础编程

时间:2021-03-13 22:59:44

--初次打开会话要运行的(否则就不能输出数据)

SET SERVEROUTPUT ON

--变量赋值(赋值符号default、:=)    /  代表执行

DECLARE 

    sname VARCHAR(10) := '张三';

BEGIN

    dbms_output.put_line(sname);

END;

/

------------------------

 

--声明常量

DECLARE

    pi CONSTANT NUMBER := 3.14;

    r NUMBER DEFAULT 3;

    area NUMBER;

BEGIN

    area := pi*r*r;

    dbms_output.put_line(area);

END;

/

------------------------

 

--宿主常量

VAR emp_name VARCHAR(30);

BEGIN

    SELECT ename INTO :emp_name FROM emp WHERE empno=7499;

end;

/

 

print emp emp_name;

------------------------

 

--属性数据类型

--%rowtype  表示引入数据库中的一行作为数据类型(实体对象)

--%type  表示引用某个变量或者数据库的列的类型作为变量的数据类型(引用类型)

--%ROWTYPE(实体)

DECLARE

  mydept dept%ROWTYPE;

BEGIN

  SELECT * INTO mydept FROM dept WHERE deptno=10;

  dbms_output.put_line(mydept.dname||'----'||mydept.loc);

END;

/

-------------------

 

--%TYPE(引用类)

DECLARE

  e_job emp.job%TYPE;

  my_job varchar2(10);

  your_job my_job%TYPE;

BEGIN

  SELECT job INTO e_job FROM emp WHERE empno=7934;

  my_job := e_job;

  your_job := e_job;

  dbms_output.put_line('emp:'||e_job||'     '||'my:my_'||my_job||'     '||'your:yout_'||your_job);

END;

-------------------

 

--PL/SQL条件控制和循环控制

--if then

DECLARE

 newSal emp.sal%TYPE;

BEGIN

  SELECT sal INTO newSal FROM emp WHERE empno=7369;

  IF newSal<1500 THEN

    UPDATE emp SET comm=1000 WHERE empno=7369;

  END IF;

  COMMIT;

END;

-------------------

 

--if then elsif

DECLARE

 newSal emp.sal%TYPE;

BEGIN

  SELECT sal INTO newSal FROM emp WHERE empno=7369;

  IF newSal>1500 THEN

    UPDATE emp SET comm=1000 WHERE empno=7369;

  ELSIF newSal<1500 THEN

    UPDATE emp SET comm=500 WHERE empno=7369;

  ELSE

    UPDATE emp SET comm=400 WHERE empno=7369;

  END IF;

  COMMIT;

END;

-------------------

--case

DECLARE

 v_grade CHAR(1):=UPPER('&p_grade');

BEGIN

  CASE

    WHEN v_grade='A' THEN

      dbms_output.put_line('Excellent');

    WHEN v_grade='B' THEN

      dbms_output.put_line('Very Good');

    WHEN v_grade='C' THEN

      dbms_output.put_line('Good');

    ELSE

      dbms_output.put_line('No such grade');

  END CASE;

END;

 

--case[selector]

DECLARE

 v_grade CHAR(1):=UPPER('&p_grade');

BEGIN

  CASE v_grade

    WHEN 'A' THEN

      dbms_output.put_line('Excellent');

    WHEN 'B' THEN

      dbms_output.put_line('Very Good');

    WHEN 'C' THEN

      dbms_output.put_line('Good');

    ELSE

      dbms_output.put_line('No such grade');

    END CASE;

END;

-------------------

 

DECLARE

 v_grade CHAR(1):=UPPER('&p_grade');   --&:输入

 p_grade varchar2(10);

BEGIN

  p_grade :=

  CASE v_grade

    WHEN 'A' THEN

      'Excellent'

    WHEN 'B' THEN

      'Very Good'

    WHEN 'C' THEN

      'Good'

    ELSE

      'No such grade'

  END;

  dbms_output.put_line('Grade:'||v_grade||',the result is'||p_grade);

END;

-------------------------------

--decode

DECLARE

  v_grade CHAR(1) := UPPER('&p_grade');

  p_grade VARCHAR2(20);

BEGIN

  SELECT DECODE(v_grade,'A','Excellent','B','Very Good','C','Good','No such grade') INTO p_grade

  FROM dual;

  dbms_output.put_line(p_grade);

END;

-------------------------------

 

--循环结构

DECLARE

  pnum NUMBER := 1;

BEGIN

  WHILE pnum < 10 LOOP

    dbms_output.put(pnum);

    pnum := pnum + 1;

  END LOOP;

END;

--------------

 

DECLARE

  pnum NUMBER DEFAULT 1;

BEGIN

  LOOP

  EXIT WHEN pnum > 10;

    dbms_output.put_line(pnum);

    pnum := pnum + 1;

  END LOOP;

END;

-------------

--范围循环

DECLARE

BEGIN

  FOR pnum IN 1..5 LOOP

  dbms_output.put_line(pnum);

  END LOOP;

END;

---------------

--游标loop

DECLARE

  --定义一个实体类用于打印相关字段

  temp_emp emp%ROWTYPE;

  --类似于Java中的ResultSet

  CURSOR mycursor IS SELECT * FROM emp WHERE sal>1600;

BEGIN

  --打开游标

  OPEN mycursor;

  --遍历ResultSet

  LOOP

    FETCH mycursor INTO temp_emp;

    EXIT WHEN mycursor%NOTFOUND;

    dbms_output.put_line(temp_emp.empno||'----'||temp_emp.ename);

  END LOOP;

END;

----------------

 

--异常(exception)

--(1)系统例外no_data_found

DECLARE

  pname emp.ename%TYPE;

BEGIN

  SELECT ename INTO pname FROM emp WHERE empno=1234;

EXCEPTION

  WHEN no_data_found THEN dbms_output.put_line('没有找到该员工');

  WHEN OTHERS THEN dbms_output.put_line('其他意外');

END;

-------------------------

--(2)系统例外too_many_rows

DECLARE

  pname emp.ename%TYPE;

BEGIN

  SELECT ename INTO pname FROM emp WHERE deptno=10;

EXCEPTION

  WHEN too_many_rows THEN dbms_output.put_line('匹配了多行');

  WHEN OTHERS THEN dbms_output.put_line('其他例外');

END;

-------------------------

--(3)系统例外zero_divide

DECLARE

  pnum NUMBER;

BEGIN

  pnum := 1/0;

EXCEPTION

  WHEN zero_divide THEN dbms_output.put_line('0不能做除数');

  WHEN OTHERS THEN dbms_output.put_line('其他例外');

END;

------------------------

--(4)系统例外value_error 算数或类型转换错误

DECLARE

  pnum NUMBER;

BEGIN

  pnum := 'asd';

EXCEPTION

  WHEN value_error THEN dbms_output.put_line('算数或转换错误');

  WHEN OTHERS THEN dbms_output.put_line('其他例外');

END;

------------------------

--(5)自定义例外 可以当成一个变量 可抛出

DECLARE

  CURSOR cemp IS SELECT ename FROM emp WHERE deptno=500;

  pname emp.ename%TYPE;

  no_emp_found EXCEPTION;

BEGIN

  OPEN cemp;

  FETCH cemp INTO pname;

  IF cemp%NOTFOUND THEN

     RAISE no_emp_found;

  END IF;

CLOSE cemp;--(不用担心没有关闭光标,系统会启动一个进程pmon(progress monitor来关闭它)

  EXCEPTION

     WHEN no_emp_found THEN dbms_output.put_line('没有找到该部门的员工');

     WHEN OTHERS THEN dbms_output.put_line('其他例外');

END;

---------------------------------------

--创建存储过程例子:
CREATE OR REPLACE PROCEDURE proc1(
p_para1 VARCHAR2,
p_para2 OUT VARCHAR2,
p_para3 IN OUT VARCHAR2
)AS
v_name VARCHAR2(20);
BEGIN
v_name := '张三';
p_para3 := v_name;
dbms_output.put_line('p_para3:'||p_para3);
END;
-----------------------
--简单存储过程例子
CREATE OR REPLACE PROCEDURE findEmpJob(myempno IN NUMBER,myename OUT varchar2,myjob OUT varchar2)
AS
BEGIN
SELECT ename,job INTO myename,myjob FROM emp WHERE empno=myempno;
END;
-----------------------


--在初次打开PL/SQL时要运行以下这行代码
set serveroutput on

--返回结果集

--创建一个存储过程包
CREATE OR REPLACE PACKAGE mypack
IS
TYPE mycursor IS REF CURSOR;
END mypack;

--创建存储过程方法
CREATE OR REPLACE PROCEDURE findEmpJob(
myempno IN NUMBER,
myename OUT varchar2,
myjob OUT VARCHAR2,
other_name OUT mypack.mycursor
)
AS
BEGIN
SELECT ename,job INTO myename,myjob FROM emp WHERE empno=myempno;
OPEN other_name FOR
SELECT ename,job FROM emp WHERE empno IN(
SELECT empno FROM emp
MINUS
SELECT empno FROM emp WHERE empno=myempno
);
END;

 

SELECT * FROM emp;
SELECT * FROM dept;

-----------------------------------------

--执行动态SQL
--execute immediate
DECLARE
sql_stmt varchar2(200);
table_name VARCHAR2(20);
BEGIN
table_name:= 'stu_201704';
sql_stmt:= 'create table '||table_name ||'(';
sql_stmt:= sql_stmt ||'id int primary key,';
sql_stmt:= sql_stmt ||'stu_name varchar2(20)';
sql_stmt:= sql_stmt ||')';
dbms_output.put_line(sql_stmt);
EXECUTE IMMEDIATE sql_stmt;
END;

 

--需求
/*
1.查询部门
2.遍历部门结果
a.生成动态create table sql
b.统计对应此部门的收入(工资+奖金)
3.执行动态create sql
4.执行动态insert
5.commit
*/
-- 动态SQL——查询,建表,统计,插入
declare
--定义游标,遍历所有部门
cursor mydept_cur is select * from dept where deptno in (select deptno from emp);
--定义部门实体类
mydept dept%rowtype;
--创建表的sql,需要动态执行
create_str varchar2(100);
--插入表的sql,需要动态执行
insert_str varchar2(200);
--定义查询平均收入
query_avg_income_str varchar2(100);
income_str varchar2(50);
begin
create_str:= 'create table dept_income(';
insert_str:= 'insert into dept_income values (';
query_avg_income_str:= 'select avg(sal)+avg(nvl(comm,0)) from emp where deptno=:1';
--打开游标
open mydept_cur;
loop
-- while (rs.next()) {

--}
--模仿rs.next(),做2件事
fetch mydept_cur into mydept;
exit when mydept_cur%notfound;
-- 追加中间的字段以及类型
create_str:= create_str || mydept.dname||' number,';
execute immediate query_avg_income_str into income_str using mydept.deptno;
insert_str:= insert_str|| income_str||',';
end loop;
--关闭游标
close mydept_cur;
create_str:= create_str||'dt varchar2(200))';
insert_str:= insert_str|| '''201703'')' ; --中间那对引号是表示转义字符
--输出语句
--dbms_output.put_line(create_str);
--dbms_output.put_line(insert_str);
--动态执行语句
execute immediate create_str;
execute immediate insert_str;
--DML语句需要提交
commit;
end;
-----------------------------

--动态PL/SQL捕获异常例子:

declare
--定义游标,遍历所有部门
cursor mydept_cur is select * from dept where deptno in (select deptno from emp);
--定义部门实体类
mydept dept%rowtype;
--创建表的sql,需要动态执行
create_str varchar2(100);
--插入表的sql,需要动态执行
insert_str varchar2(200);
--定义查询平均收入
query_avg_income_str varchar2(100);
income_str varchar2(50);
begin
create_str:= 'create table dept_income(';
insert_str:= 'insert into dept_income values (';
query_avg_income_str:= 'select avg(sal)+avg(nvl(comm,0)) from emp where deptno=:1';
--打开游标
open mydept_cur;
loop
-- while (rs.next()) {

--}
--模仿rs.next(),做2件事
fetch mydept_cur into mydept;
exit when mydept_cur%notfound;
-- 追加中间的字段以及类型
create_str:= create_str || mydept.dname||' date,';
execute immediate query_avg_income_str into income_str using mydept.deptno;
insert_str:= insert_str|| income_str||',';
end loop;
--关闭游标
close mydept_cur;
create_str:= create_str||'dt varchar2(200))';
insert_str:= insert_str|| '''201703'')' ; --中间那对引号是表示转义字符
--输出语句
--dbms_output.put_line(create_str);
--dbms_output.put_line(insert_str);
--动态执行语句
execute immediate create_str;
execute immediate insert_str;
--DML语句需要提交
commit;

--异常捕获
exception
--when 异常名字 then
when others then
dbms_output.put_line('捕获到其它异常:'||SQLCODE||' '||SQLERRM);
end;

 

 

这里是有关PL/SQL的基础代码:

谢谢各位博友的支持!

如需转载请注明出处:http://www.cnblogs.com/ZRJ-boke/p/6600623.html