- /*
- 授权命令 grant 权限 to 用户
- 授权可以授予多个权限
- grant connect,resource to baidu
- 收回权限 revoke 权限 from 用户
- revoke dba from baidu
-
- 创建用户 分配表空间--指定用户的默认表空间
- create table p(..) 建表存在默认表空间
- --建表时候指定表空间
- create table p(...) talebspace 表空间名
- */
- /*
- PlSql编程语言 procedure language 过程语言
- 是在sql语句中加入一些处理过程的语句
- 常见的条件表达式 if else 还有循环结构
- 基本结构
- declare
- --声明部分 理解为定义
- --声明使用的变量
- begin
- --处理逻辑的代码块
- end;
- */
- --psSql简单示例
- declare
- v_n number := 1; --声明数值变量 赋值使用符号:=
- v_s varchar2(4) :='s'; --声明字符类型变量
- emp_ename emp.ename%type ;-- 引用类型变量
- emp_row emp%rowtype ;-- 记录类型变量
- begin
-
- dbms_output.put_line('v_n====='||v_n); --输出语句相当于sys out
- dbms_output.put_line('v_s====='||v_s);
-
- select ename into emp_ename from emp where empno=7499; --使用into关键字赋值
- dbms_output.put_line('emp_ename====='||emp_ename);
-
- select * into emp_row from emp where empno = 7499; --赋值记录类型变量
- dbms_output.put_line('员工编号=='||emp_row.empno||'员工姓名'||emp_row.ename);
- end;
- /*
- plsql 的条件表达式判断
- if .. 处理语句 else if ..处理语句
- -------------------------
- if .. then
- elsif .. then
- else
- end if;
- */
- ---使用条件表达式判断员工的工资 使用汉字输出
- declare
-
- emp_row emp%rowtype ;-- 记录类型变量
- begin
-
- select * into emp_row from emp where empno = 7499; --赋值记录类型变量
- --使用表达式判断工资
- if emp_row.sal > 3000 then
- dbms_output.put_line('员工工资大于3000=='||emp_row.sal);
- elsif emp_row.sal < 1000 then
- dbms_output.put_line('员工工资小于1000=='||emp_row.sal);
- else
- dbms_output.put_line('员工工资位于1000到3000之间=='||emp_row.sal);
- end if;
-
- end;
- /*
- 循环结构
- 第一种-----
- loop
- exit when 条件
- end loop;
- 第二种 ---
- while 条件 loop
-
- end loop;
- 第三种 ---
- for 变量 in 范围 loop
-
- end loop;
- */
- -------使用循环输出数字 1-----10
- /*
- 第一种
- loop
- exit when 条件
- end loop;
- */
- declare
- v_n number :=1;
- begin
-
- loop
- --只是用来判断退出使用的,并不是相当于if()else{}
- exit when v_n>10 ; --退出条件
- dbms_output.put_line(v_n);
- v_n:=v_n+1; --自增
- end loop;
- end;
- /*
- 第二种
- while 条件 loop
-
- end loop;
- */
- declare
- v_n number :=1;
- begin
-
- while v_n<11 loop
- dbms_output.put_line(v_n);
- v_n:=v_n+1; --自增
- end loop;
- end;
- /*
- 第三种
- for 变量 in 范围 loop 变量的声明和范围的控制是由for循环自动执行
-
- end loop;
- */
- declare
- begin
-
- for i in 1..10 loop
- dbms_output.put_line(i);
- end loop;
- end;
- /*
- 游标 光标 是用于接收查询的记录结果集 ResultSet 提示记录使用.next()
- 游标的使用步骤
- 声明游标 cursor 游标名 is select 语句 指定游标的记录结果集
- 打开游标 open 游标名
- 提取游标 fetch 游标名 into 记录类型变量
- 关闭游标 close cursor
- 游标的两个属性 游标名%found : 判断它有找到
- 游标名%notfound : 判断它没有找到
- if emp_cursor%found then
- dbms_output.put_line('found');
- elsif emp_cursor%notfound then
- dbms_output.put_line('notfound');
- elsif emp_cursor%notfound is null then
- dbms_output.put_line('null');
- end if;
- */
- --使用while循环结构演示游标
- declare
- --声明游标
- cursor emp_cursor is select * from emp;
- --声明记录类型变量 用于接收游标提取的记录
- emp_row emp%rowtype;
- begin
- --打开游标
- open emp_cursor;
- --提取游标(判断下一个是否有值)
- fetch emp_cursor into emp_row ;
- --有值就执行while循环
- while emp_cursor%found loop
- dbms_output.put_line(emp_row.empno||'员工姓名'||emp_row.ename);
- --继续提取游标(并判断下一个是否有值)
- fetch emp_cursor into emp_row ;
- end loop;
- close emp_cursor;
- end;
- /*
- loop
- exit when 游标提取不到
- end loop
- */
- declare
- --声明游标
- cursor emp_cursor is select * from emp;
- --声明记录类型变量 用于接收游标提取的记录
- emp_row emp%rowtype;
- begin
- --打开游标
- open emp_cursor;
- loop
- fetch emp_cursor into emp_row;
- exit when emp_cursor%notfound;
- dbms_output.put_line(emp_row.empno||'员工姓名'||emp_row.ename);
- end loop;
- close emp_cursor;
- end;
- --使用游标提取某个部门的员工信息
- --声明带参数的游标信息
- declare
- --声明游标
- cursor emp_cursor(dno number) is select * from emp where deptno = dno ;
- --声明记录类型变量 用于接收游标提取的记录
- emp_row emp%rowtype;
- begin
- --打开游标 时候传入参数
- open emp_cursor(10);
- loop
- fetch emp_cursor into emp_row;
- exit when emp_cursor%notfound;
- dbms_output.put_line(emp_row.empno||'员工姓名'||emp_row.ename);
- end loop;
- close emp_cursor;
- end;
- /*
- 错误信息开发中的异常
- 数据库中叫做 例外
- 异常的分类 1.系统异常 系统定义好的异常
-
- 2.自定义的异常
- new 自定义类继承Exception 自定义传值(错误代码,提示信息)
- 使用场景
- 不满足某些特定业务场景,抛出自定义异常
- 异常的处理
- java try{}catche(IndexOutOfBoundException e){}catche(Exception e){}
- java try{}catche(Exception e){} catche(IndexOutOfBoundException e){}--报错
- 数据库可以捕捉处理异常
- exception 关键字捕捉异常
- when 异常类型 then 处理语句 判断异常类型 处理异常
-
- */
- --异常的简单示例
- /*
- --除0的异常 除数为0
- --赋值错误
-
- */
- declare
- v_n number :=0;
- v_m number :=1;
-
- begin
- v_m:='s'; --将字符串赋值给数值变量
- v_m:= v_m/v_n;
- exception
-
- when zero_divide then
- dbms_output.put_line('除数不能为0');
- when value_error then
- dbms_output.put_line('赋值有误');
- end;
- ---处理太多记录数异常
- declare
-
- emp_row emp%rowtype ;-- 记录类型变量
- begin
-
- select * into emp_row from emp ; --赋值记录类型
-
- exception
-
- when too_many_rows then
- dbms_output.put_line('太多记录数');
- when others then --others是最大范围的异常 相当于java 的 Exception
- dbms_output.put_line('其他异常');
- end;
- /*
- 需求 :使用游标查询部门下的员工信息
- 如果部门下没有员工 报错提示
- 需要自定义异常
- 变量名 exception --声明自定义异常
-
- */
- declare
-
- cursor emp_cursor is select * from emp where deptno= 40; --游标结果集不存在
- emp_row emp%rowtype ;-- 记录类型变量
- no_dept_emp exception ; --声明自定义异常
- begin
- open emp_cursor; --打开游标
-
- fetch emp_cursor into emp_row;
- if emp_cursor%notfound then
- --没有员工 抛出错误异常
- raise no_dept_emp;
- end if;
- close emp_cursor;
- exception
- when no_dept_emp then
- dbms_output.put_line('部门下面没人,快招人吧');
- end;
- /*
-
- 存储过程 是一段封装好的代码块,过程是编译好放在服务器提供开发人员调用
-
- 封装的代码块意义: 提升开发效率 可以复用 谁用直接调用
- 提升运行效率 一调用直接运行
- 语法:create [or repalce] procedure 过程名称(参数名 out|in 参数类型)
- as|is
- --声明变量的部分
- begin
- --处理过程语句代码块
- end;
- 调用存储过程
- 在begin和end之间使用 过程名传参调用
- */
- --存储过程的简单示例 使用存储过程给某个员工增加工资100
- create or replace procedure add_sal(eno in number )
- as
- emp_sal number :=0;
- begin
- select sal into emp_sal from emp where empno = eno ;
- dbms_output.put_line('涨工资之前是===='||emp_sal);
- update emp set sal=sal+100 where empno = eno;
- select sal into emp_sal from emp where empno = eno ;
- dbms_output.put_line('涨工资之后是===='||emp_sal);
- commit;
- end;
- --------调用存储过程
- declare
- begin
- add_sal(7499);
- end;
- /*
- 使用存储过程统计某个员工的年薪,年薪需要返回输出打印
- in 类型输入参数可以 省略 默认就是输入参数
- */
- create or replace procedure count_sal(eno number,year_sal out number)
- as
- begin
-
- select sal*12+nvl(comm,0) into year_sal from emp where empno=eno; --使用into赋值给输出参数
- end;
- ----调用存储过程计算年薪
- declare
- v_emp_sal number :=0;
- begin
- count_sal(7499,v_emp_sal);
- dbms_output.put_line('年薪为=='||v_emp_sal);
- end;
- /*
- 使用存储过程 查询出某个部门的员工信息
- 某个部门应该接受一个in类型的输入参数
- 查询到的部门员工多条记录返回应该使用结果集
- 声明游标 cursor 游标名 is select 语句指定结果集
- 系统引用游标
- sys_refcursor
- 声明系统引用游标 变量名 sys_refcursor; --不需要指定结果集
- 打开游标 open 系统引用游标 for select 语句 --使用for关键字装入数据
- */
- create or replace procedure dept_emp(dno number,cusor_emp out sys_refcursor)
- as
- begin
- --根据传进来的部门编号给游标装入结果集数据
- open cusor_emp for select * from emp where deptno = dno;
- end;
- ----调用存储过程查询部门下的员工
- declare
- cursor_emp sys_refcursor; --声明系统引用游标传参使用
- emp_row emp%rowtype ;--记录类型变量
- begin
- dept_emp(10,cursor_emp);
- --提取游标中的数据
- loop
- fetch cursor_emp into emp_row;
- exit when cursor_emp%notfound;
- dbms_output.put_line('编号'||emp_row.empno||'姓名'||emp_row.ename);
- end loop;
- close cursor_emp;
- end;
- /*
- 存储函数 是一段封装好的代码块,是编译好放在服务器提供开发人员调用
-
- 封装的代码块意义: 提升开发效率 可以复用 谁用直接调用
- 提升运行效率 一调用直接运行
-
- 语法:create [or repalce] function 函数名称(参数名 out|in 参数类型) return 数据类型
- in 代表传入参数,out 代表传出参数
- as|is
- --声明变量的部分
- begin
- --处理过程语句代码块
- --return 变量
- end;
- 调用存储函数
- 在begin和end之间使用 函数名传参调用 函数必须使用变量接收 返回值
-
- */
- --使用存储函数统计某个员工的年薪
- create or replace function count_emp_sal(eno number,year_sal out number) return number
- as
- v_sal number :=0;
- begin
-
- select sal*12+nvl(comm,0) into year_sal from emp where empno=eno; --使用into赋值给输出参数
- return v_sal;
- end;
- --不带out类型输出参数统计年薪
- create or replace function count_sal_noout(eno number) return number
- as
- v_sal number :=0;
- begin
-
- select sal*12+nvl(comm,0) into v_sal from emp where empno=eno; --使用into赋值给输出参数
- return v_sal;
- end;
- --调用函数统计年薪
- declare
- emp_sal number:=0;
- total_sal number :=0;
- begin
- --total_sal := count_emp_sal(7499,emp_sal);
- total_sal := count_sal_noout(7499);
- dbms_output.put_line(emp_sal);--0
- dbms_output.put_line(total_sal); --统计后年薪
- end;
- /*
- 存储函数和过程的区别
-
- 1.创建的关键字 procedure funciton
- 2.创建函数 必须使用return 声明函数的返回变量数据类型
- 3.在函数的方法体内 必须使用return 返回一个变量
- 4.函数的调用 必须有变量接收返回值
- 5.函数可以用在select 查询语句中 select emp.*,count_sal_noout(empno) from emp;
-
- 存储函数和过程使用场景
- 开发规范 java代码待用过程 过程是用来处理业务逻辑代码
- 如果逻辑中需要用到一些功能性的封装,可以调用函数
- 90%情况下 函数和过程通用 过程可以调用函数,函数同样可以调用过程
-
- */
-
- /*
- 触发器 是一个监视器,监视对表中数据的操作
- 如果对数据的操作满足触发器的执行条件,
- 触发器会自动运行
- 触发器语法:
- create or repalce trigger 触发器名称
- after|before --触发器执行时机
- insert|update|delete --监视的动作
- on 表名 --表级触发器
- declare
- begin
- end;
- 行级触发器 insert update delete
- :new 动作之后的记录 要插入的记录 修改后的记录 空
- :old 动作之前的记录 空 原始的记录 原始的记录
-
- */
- --创建触发器监视表,如果表中有数据插入,输出一个欢迎语句
- create or replace trigger insert_trigger
- after
- insert
- on p
- declare
-
- begin
- dbms_output.put_line('欢迎加入!');
- end;
- ----插入数据测试效果
- insert into p values(1,'zs');
- commit;
- --插入数据不能在休息日插入数据
- --休息日 周六和周日
- /*
- raise_application_error(v1,v2) v1错误代码 v2是提示语句
- -20000 -20999
- */
- create or replace trigger insert_no_work
- before
- insert
- on p
- declare
- v_day varchar2(10) ;
- begin
- --获取到当前星期
- select to_char(sysdate,'day') into v_day from dual;
- --判断星期是否在休息日
- if trim(v_day) in ('saturday','sunday') then
- --如果休息 错误提示
- raise_application_error(-20001,'不能休息日插入数据');
- end if;
- end;
- ----插入数据测试效果
- insert into p values(1,'zs');
- commit;
- --使用触发器监视表中数据修改,不能做降低工资的操作
- create or replace trigger can_not_low
- before
- update
- on emp
- for each row --行级触发器
- declare
-
- begin
- --获取到原始记录的工资 --获取修改后的工资
- if :old.sal > :new.sal then
- --谈错误框提示
- raise_application_error(-20002,'不能降低工资');
- end if;
- end;
- --修改员工的工资测试触发器
- update emp set sal=sal-1 where empno=7499;
- /*
- 触发器实际应用
- 使用触发器实现 插入数据的id 自增长 面试题
- **/
- create or replace trigger auto_increment_id
- before
- insert
- on test_trigger
- for each row
- declare
- begin
- --补全将要插入记录的id
- --补全的id 是自增长的数值 如果没有提前创建序列,需要提前创建序列 --创建序列 create sequence order_sequence
- select order_sequence.nextval into :new.pid from dual;
- end;
- insert into test_trigger(pname,phone) values('zs','1234566');
- commit;
- package baidu;
- import java.sql.CallableStatement;
- import java.sql.Connection;
- import java.sql.DriverManager;
- import java.sql.PreparedStatement;
- import java.sql.ResultSet;
- import org.junit.Test;
- import oracle.jdbc.OracleCallableStatement;
- import oracle.jdbc.OracleTypes;
- public class TestJdbc {
- String driverClass = "oracle.jdbc.driver.OracleDriver";
- String url ="jdbc:oracle:thin:@192.168.17.128:1521:orcl";
- String user= "baidu_03";
- String password = "baidu_03";
- /*
- *测试jdbc连接数据库
- *
- * */
- @Test
- public void querEmp(){
- try{
- //加载驱动
- Class.forName(driverClass);
- //获取链接
- Connection con = DriverManager.getConnection(url, user,password);
- //获取预编译的statement
- PreparedStatement pst= con.prepareStatement("select * from emp");
- //执行查询
- ResultSet rs = pst.executeQuery();
- //处理结果
- while(rs.next()){
- System.out.println(rs.getInt(1)+"员工姓名"+rs.getString("ename"));
- }
- rs.close();
- con.close();
- //关闭连接
- }catch(Exception e){
- e.printStackTrace();
- }
-
- }
- /*存储过程的调用
- * {call <procedure-name>[(<arg1>,<arg2>, ...)]}
- add_sal(eno number,addsal number)
- * */
- @Test
- public void callAddSal(){
- try{
- //加载驱动
- Class.forName(driverClass);
- //获取链接
- Connection con = DriverManager.getConnection(url, user,password);
- //获取预编译的statement
- CallableStatement pst= con.prepareCall("{call add_sal(?,?)}");
- pst.setInt(1, 7499);
- pst.setInt(2, 1000);
- //执行查询
- pst.execute();
- con.close();
- //关闭连接
- }catch(Exception e){
- e.printStackTrace();
- }
-
- }
-
- /*存储过程的调用
- * {call <procedure-name>[(<arg1>,<arg2>, ...)]}
- count_yearsal(eno number,total_year_sal out number)
- * */
- @Test
- public void callCountSal(){
- try{
- //加载驱动
- Class.forName(driverClass);
- //获取链接
- Connection con = DriverManager.getConnection(url, user,password);
- //获取预编译的statement
- CallableStatement pst= con.prepareCall("{call count_yearsal(?,?)}");
- pst.setInt(1, 7499);
- //注册输出参数
- pst.registerOutParameter(2, OracleTypes.NUMBER);
- //执行查询
- pst.execute();
- int total = pst.getInt(2);
- System.out.println(total);
- con.close();
- //关闭连接
- }catch(Exception e){
- e.printStackTrace();
- }
-
- }
- /*
- * pro_dept_emp(dno number,dept_emp out sys_refcursor)
- * */
- @Test
- public void callProEmp(){
- try{
- //加载驱动
- Class.forName(driverClass);
- //获取链接
- Connection con = DriverManager.getConnection(url, user,password);
- //获取预编译的statement
- CallableStatement pst= con.prepareCall("{call pro_dept_emp(?,?)}");
- pst.setInt(1, 10);
- //注册输出参数
- pst.registerOutParameter(2, OracleTypes.CURSOR);
- //执行查询
- pst.execute();
- OracleCallableStatement ocs = (OracleCallableStatement)pst;
- ResultSet rs = ocs.getCursor(2);
- while(rs.next()){
- System.out.println(rs.getInt(1)+"员工姓名"+rs.getString("ename"));
- }
- rs.close();
- ocs.close();
- pst.close();
- con.close();
- //关闭连接
- }catch(Exception e){
- e.printStackTrace();
- }
-
- }
- }
- public void show4(){
- try {
-
- Class.forName(driverClass);
- Connection con = DriverManager.getConnection(url, user,password);
- CallableStatement pst= con.prepareCall("{?= call count_sal_noout(?)}");
- //给第二个参数赋值
- pst.setLong(2, 7499);
- // stat2.setLong(2, empno);
- //声明第一个参数的类型
- pst.registerOutParameter(1, OracleTypes.NUMBER);
- pst.execute();
- OracleCallableStatement ocs = (OracleCallableStatement)pst;
- NUMBER num = ocs.getNUMBER(1);
- System.out.println(num);
- // long i = pst.getLong(1);
- // System.out.println(i);
-
- con.close();
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- /*