JavaWeb开发知识总结(四)-(oracle_编程)
来源:互联网 发布:mac 用appleid 登陆 编辑:程序博客网 时间:2024/06/15 21:23
JavaWeb开发知识总结(Oracle-编程)
1. PL/SQL:Oracle特有
1.1 PL/SQL概述
PL/SQL(Procedure Language/SQL)是 Oracle 对 sql 语言的过程化扩展,指在 SQL 命令语言中增加了过程处理语句(如分支、循环等),使 SQL 语言具有过程处理能力。把 SQL 语言的数据操纵能力与过程语言的数据处理能力结合起来,使得 PLSQL 面向过程但比过程语言简单、高效、灵活和实用。
基本的语法结构:
--语法:变量声明和异常处理可以没有,当时begin..end块必须存在[declare 声明变量;]begin 逻辑代码; [exception 异常处理逻辑; ]end;
1.2 变量
变量声明:
--语法:在declare中声明变量--1.只声明变量,不赋值变量名称 变量类型(长度); --如:v_name varchar2(30);--2.声明时就给初始值变量名称 变量类型(长度):=值; --如:v_name varchar2(30):='somnus';
变量的赋值:
--变量赋值方式:--1.声明时就给初始值变量名称 变量类型(长度):=值; --如:v_name varchar2(30):='somnus';--2.先声明,在begin..end块中进行赋值变量名:=值; --如:v_name:='somnus';--3.先声明,在begin..end块中通过select 字段名 into 变量名 from 表名 条件;方式进行赋值select 字段名 into 变量名 from 表名 条件;
案例:
--1.变量声明和赋值declare v_price number(10,2); -- 水费单价 v_usenum number;--水表数字 v_usenum2 number(10,2);--水的吨数 v_money number(10,2); --水费金额begin --赋值 v_price:=2.45; v_usenum:=9527; v_usenum2:=round(v_usenum/1000); v_money:=v_price*v_usenum2; --输出值 dbms_output.put_line('用水量/吨:'||v_usenum2); dbms_output.put_line('金额/元:'||v_money);end; --要有分号--2.从表中查询数据到变量中 select 列名 into 变量名from 表名 [条件]declare v_price number(10,2); -- 水费单价 v_usenum number;--水表数字 v_usenum2 number(10,2);--水的吨数 v_money number(10,2); --水费金额begin --赋值 v_price:=2.45; --从水费台帐表中查询数据到变量中 select usenum into v_usenum from t_account where year='2016' and month='01' and id = 1; v_usenum2:=round(v_usenum/1000); v_money:=v_price*v_usenum2; --输出值 dbms_output.put_line('用水量/吨:'||v_usenum2); dbms_output.put_line('金额/元:'||v_money);end; --要有分号
1.3 属性类型
如果定义的变量的类型依赖于具体表中的某列(引用型属性)或查询表结果集的中行(记录类型),则可以通过定义的方式的使得变量依赖于具体的列类型或行类型。
引用类型:变量名称 表名.列名%type;
--案例:declare v_price number(10,2); -- 水费单价 v_usenum t_account.usenum%type;--水表数字 v_usenum2 number(10,2);--水的吨数 v_money number(10,2); --水费金额begin --赋值 v_price:=2.45; --从表中查询数据到变量中 select usenum into v_usenum from t_account where year='2016' and month='01' and id = 1; v_usenum2:=round(v_usenum/1000); v_money:=v_price*v_usenum2; --输出值 dbms_output.put_line('用水量/吨:'||v_usenum2); dbms_output.put_line('金额/元:'||v_money);end; --要有分号
记录类型:变量名称 表名%rowtype;
将结果集中一行记录封装到变量中
declare v_price number(10,2); -- 水费单价 v_account t_account%rowtype;--将查询的一行记录封装到一个变量中 v_usenum2 number(10,2);--水的吨数 v_money number(10,2); --水费金额begin --为变量赋值 v_price:=2.45; --从表中查询一行数据封装到一个变量中 select * into v_account from t_account where year='2016' and month='01' and id = 1; --通过记录类型变量.列名获取一行记录中某列的值 v_usenum2:=round(v_account.usenum/1000); -- 通过变量.列名调用某列的值 v_money:=v_price*v_usenum2; --输出值 dbms_output.put_line('用水量/吨:'||v_usenum2); dbms_output.put_line('金额/元:'||v_money);end; --要有分号
1.4 异常
在运行程序时出现的错误叫做异常/例外,发生异常后,语句将停止执行,控制权转移到 PL/SQL 块的异常处理部分
异常有两种类型:
1. 预定义异常:当 PL/SQL 程序违反 Oracle 规则或超越系统限制时隐式引发,一共有21种异常;
2. 用户定义异常:用户可以在 PL/SQL 块的声明部分定义异常,自定义的异常通过 RAISE 语句显式引发。
异常处理的语法:
--语法:在begin..end块中定义begin 处理逻辑; exception when 异常类型 then 异常处理逻辑end;
案例:
--一般使用系统预定义异常:--可能多个异常时,需要有多个when..then语句--异常/例外 预定义异常21种和其他用户自定义异常declare v_num number;begin v_num:=1/0; --除0异常 exception when ZERO_DIVIDE --除数不能为0的异常关键字 then dbms_output.put_line('除数不能为0'); when NO_DATA_FOUND --使用 select into 未返回行 then dbms_output.put_line('没有返回数据');end;
1.5 条件判断:if语法
判断语句if的语法:
--在begin..end块中使用判断语句:注意elsif中不是else ifdeclare --当没有变量的定义时,declare可以省略begin --if的格式1:if语句 if 1<2 then dbms_output.put_line('1小于2'); end if; --if的格式2:if..else语句 if 1>2 then dbms_output.put_line('1大于2'); else dbms_output.put_line('1小于2'); end if; --if的格式3:if..elsif..elsif..else语句 if 1>2 then dbms_output.put_line('1大于2'); elsif 1=2 then dbms_output.put_line('1等于2'); else dbms_output.put_line('1小于2'); end if;end;
1.6 循环:
无条件循环:
--语法:循环语句定义在begin..end块中loop 循环体;end loop;--案例:declare v_num number:=1;begin loop dbms_output.put_line(v_num); v_num:=v_num+1; --退出循环方式1 if v_num >= 100 then exit; end if; --退出循环方式2 exit when v_num >= 100; end loop;end;
有条件循环:
--语法:循环语句定义在begin..end块中while 条件;--条件是指循环能够执行的条件loop 循环体;end loop;--案例:declare v_num number:=1;begin while v_num < 100 --循环的条件 loop dbms_output.put_line(v_num);--输出变量的值 v_num:=v_num+1; -- 变量加1 end loop;end;
for循环:
--语法:循环语句定义在begin..end块中for 变量 in 起始值..终止值loop 循环体;end loop;--案例:--使用for循环declarebegin --此处的x变量相当于是局部变量,不用再定义,并且x只能在loop循环体内使用 for x in 1..100 loop dbms_output.put_line(x); end loop;end;--for循环,可以使用变量控制循环的数据范围declare v_num number:=50;begin --此处的x变量相当于是局部变量,不用再定义,并且x只能在loop循环体内使用 for x in 1..v_num loop dbms_output.put_line(x); end loop;end;
1.7 游标
游标是系统为用户开设的一个数据缓冲区,存放 SQL 语句的执行结果。我们可以把游标理解为 PL/SQL 中的结果集。查询的数据存放在内存中缓冲区中,降低了服务器性能。游标打开时默认指向的是结果集中第一行的上面,当通过fetch抓取数据时才使得游标指向第一条数据。
定义无参数游标语法:
--语法:cursor 游标名称 is SQL 语句;
无参数游标使用语法:
--语法:open 游标名称;loop fetch 游标名称 into 变量; exit when 游标名称%notfound;end loop;close 游标名称;--案例:--无参数的游标declarecursor cur_pricetable is select * from t_pricetable where ownertypeid=1;--获取游标中存储的值v_price t_pricetable%rowtype;begin open cur_pricetable; loop fetch cur_pricetable into v_price; --获取游标中的值到行变量中 exit when cur_pricetable%notfound; --游标的值取完后退出循环 dbms_output.put_line(v_price.price||'--'||v_price.minnum||'--'||v_price.maxnum); --退出语句放在输出语句后面,会将最后一个值输出两次 --原因是:只有fetch语句才会抓取下一个值,当是最后一个值,输出语句进行输出, --判断条件判断的是当前的结果是最后一个值,下次循环,fetch抓取的是空值,但 --输出语句还是会继续输出最后一个值,到退出语句才会结束循环 --exit when cur_pricetable%notfound; --游标的值取完后退出循环 end loop; close cur_pricetable;end;
有参数游标的定义与使用:
--定义带参数的游标declarecursor cur_pricetable2(v_ownertypeid number) is --定义游标的参数select * from t_pricetable where ownertypeid=v_ownertypeid;--获取游标中存储的值v_price t_pricetable%rowtype;begin open cur_pricetable2(3); --调用带参数的游标需要传入参数 loop fetch cur_pricetable2 into v_price; --获取游标中的值到行变量中 exit when cur_pricetable2%notfound; --游标的值取完后退出循环 dbms_output.put_line(v_price.price||'--'||v_price.minnum||'--'||v_price.maxnum); end loop; close cur_pricetable2;end;
通过for循环使用游标:
--for循环提取游标值:隐式的打开游标和关闭游标declarecursor cur_pricetable2(v_ownertypeid number) is --定义游标的参数select * from t_pricetable where ownertypeid=v_ownertypeid;--获取游标中存储的值v_price t_pricetable%rowtype;begin for v_price in cur_pricetable2(1) loop dbms_output.put_line(v_price.price||'--'||v_price.minnum||'--'||v_price.maxnum); end loop;end;
2. 存储函数:Oracle和mysql通用
存储函数又称为自定义函数。可以接收一个或多个参数,返回一个结果。在函数中我们可以使用 P/SQL 进行逻辑的处理。
创建存储过程语法:
--语法:CREATE [ OR REPLACE ] FUNCTION 函数名称(参数名称 参数类型, 参数名称 参数类型, ...) RETURN 结果变量数据类型IS 变量声明部分;BEGIN 逻辑部分; RETURN 结果变量; [EXCEPTION 异常处理部分]END;--注意事项:函数的参数声明时不能加参数长度;函数的返回值不能添加类型的长度;
案例:
--存储函数可以嵌入SQL语句中,返回的是一个值或对象create or replace function fn_getAddress(v_id number)return varchar2is --变量声明 v_name varchar2(20);begin select name into v_name from t_address where id = v_id; return v_name;end;--调用存储函数select fn_getAddress(1) from dual; --简单的调用存储函数--调用存储函数作为select语句字段select id,name,fn_getaddress(addressid) from t_owners where id=1;
3. 存储过程(重点):Oracle和mysql通用
存储过程是被命名的 PL/SQL 块,存储于数据库中,是数据库对象的一种。应用程序可以调用存储过程,执行相应的逻辑。存储过程的缺点:数据库中表之间耦合度较高,不利于功能需求的更改。
存储过程:能够将开发中的业务逻辑进行封装,其思想和hibernate框架思想相反。
存储过程与存储函数都可以封装一定的业务逻辑并返回结果,存在区别如下:
- 存储函数中有返回值,且必须返回;存储过程没有返回值,但可以通过传出参数返回多个值。
- 存储函数可以在 select 语句中直接使用;存储过程不能直接在select语句中使用,存储过程多是被应用程序(java)调用。
- 存储函数一般都是封装一个查询结果;存储过程一般都封装一段事务代码,进行事务操作的控制。
存储过程语法结构:
--语法:CREATE [ OR REPLACE ] PROCEDURE 存储过程名称(参数名 [in|out|in out] 类型, 参数名 [in|out|in out] 类型, 参数名 [in|out|in out] 类型...)IS|AS --两者都可以,但必须有一个 变量声明部分;BEGIN 逻辑部分; [EXCEPTION 异常处理部分]END;--注意事项:参数声明时不能指定类型的长度;参数的in|out说明:in代表该参数是传入参数,out代表该参数是传出参数 声明参数为in:声明该参数是传入参数 声明参数为out:声明该参数是传出参数 声明参数为in out:声明该参数是传入传出参数无传出参数的存储过程调用: call方式调用; begin...end方式调用; JDBC中调用;有传出参数的存储过程调用:不能使用call调用,无法获取传出参数 begin...end方式调用; JDBC中调用;
案例1:无参数的存储过程创建
--不带传出参数的存储过程create sequence seq_owners start with 18;--创建自动增长序列,用于设置表的id列主键--创建存储过程create or replace procedure pro_owners_add(v_name varchar2, --传入参数默认省略in关键字v_addressid number,v_housenumber varchar2,v_watermeter varchar2,v_ownertypeid number)is--声明变量begin insert into t_owners values (seq_owners.nextval,v_name,v_addressid,v_housenumber,v_watermeter ,sysdate,v_ownertypeid);end;
案例1:无参数的存储过程调用–call和begin..end方式调用
--调用不带传出参数的存储过程--调用方式1:call pro_owners_add('sunmos',1,'2-1','0729-0809',1);commit;--调用方式2:begin pro_owners_add('sunmos',1,'2-1','0729-0809',1); commit;end;
案例1:无参数的存储过程调用–jdbc方式调用
/** * 注意事项:调用方式:{call pro_owners_add(?,?,?,?,?)},必须要加{},传入参数 * 调用数据库的无传出参数的存储过程 */public void pro_add(Owners owners) { // 声明数据库连接对象 Connection conn = null; // 声明执行存储过程的对象 CallableStatement stmt = null; // 存储过程使用的CallableStatement对象 try { // 获取连接 conn = BaseDao.getConnection(); // 预编译存储过程 stmt = conn.prepareCall("{call pro_owners_add(?,?,?,?,?)}"); // 设置参数 stmt.setString(1, owners.getName()); stmt.setLong(2, owners.getAddressid()); stmt.setString(3, owners.getHousenumber()); stmt.setString(4, owners.getWatermeter()); stmt.setLong(5, owners.getOwnertypeid()); // 执行sql语句 stmt.execute(); } catch (SQLException e) { e.printStackTrace(); } finally{ // 释放资源 BaseDao.closeAll(conn, stmt, null); }}
案例2:有传出参数存储过程的创建
--创建带传出参数的存储过程create or replace procedure pro_owners_add2(v_name varchar2,v_addressid number,v_housenumber varchar2,v_watermeter varchar2,v_ownertypeid number,v_id out number --传出参数需要定义out关键字)is -- is和as均可以begin --将添加的业主的id值存储到传出变量中 select seq_owners.nextval into v_id from dual; insert into t_owners values (v_id,v_name,v_addressid,v_housenumber,v_watermeter ,sysdate,v_ownertypeid); commit; --dml操作需要使用commit提交事务end;
案例2:有传出参数存储过程的调用–begin..end方式调用
--调用带传出参数的存储过程--只能通过begin...end语句进行调用,不能通过call调用declare v_id number; --声明接收传出参数的变量begin --将传出参数作为存储过程的对应的参数 pro_owners_add2('sunmos',1,'2-1','0729-0809',1,v_id); dbms_output.put_line(v_id);--输出传出参数值end;
案例2:有传出参数存储过程的调用–JDBC方式调用
/** * 注意事项: * 调用方式:{call pro_owners_add(?,?,?,?,?)},必须要加{},传入参数; * 获取传出参数必须在执行SQL语句后才能获取传出参数值; * 调用数据库的有传出参数的存储过程 */public Long pro_add2(Owners owners) { // 定义传出的数据的值 Long v_id = 0L; // 声明数据库连接对象 Connection conn = null; // 声明执行存储过程的对象 CallableStatement stmt = null; // 存储过程使用的CallableStatement对象 try { // 获取连接 conn = BaseDao.getConnection(); // 预编译存储过程 stmt = conn.prepareCall("{call pro_owners_add2(?,?,?,?,?,?)}"); // 设置参数 stmt.setString(1, owners.getName()); stmt.setLong(2, owners.getAddressid()); stmt.setString(3, owners.getHousenumber()); stmt.setString(4, owners.getWatermeter()); stmt.setLong(5, owners.getOwnertypeid()); // 设置传出参数的类型,最后一个参数是传出参数,类型时number类型 stmt.registerOutParameter(6, OracleTypes.NUMBER);//OracleTypes是Oracle驱动包中的类 // 执行SQL语句 stmt.execute(); // 在存储过程执行完毕后获取传出参数值 v_id = stmt.getLong(6); } catch (SQLException e) { e.printStackTrace(); } finally{ BaseDao.closeAll(conn, stmt, null); } return v_id;}
4. 触发器:Oracle和mysql通用
数据库触发器是一个与表相关联的、存储的PL/SQL程序。每当一个特定的数据操作语句(Insert,update,delete)在指定的表上发出时,Oracle 自动地执行触发器中定义的语句序列。触发器是作用表上的监听DML操作并执行预定义的逻辑代码。触发器分为前置触发器和后置触发器。当表被删除时,作用在表上的触发器会被自动删除。
触发器的作用: 数据确认;实施复杂的安全性检查;做审计,跟踪表上所做的数据操作等; 数据的备份和同步。
触发器的定义:
--语法:CREATE [or REPLACE] TRIGGER 触发器名 BEFORE | AFTER [DELETE ][[or] INSERT] [[or]UPDATE [OF 列名]] ON 表名 [FOR EACH ROW ] [WHEN(条件) ]declare 变量声明;begin 逻辑代码块;End;--注意事项:before:代表是前置触发器;执行语句会先被挂起,如果触发器执行过程抛出异常,挂起的sql语句不能执行;after:代表是后置触发器;执行语句执行后,再执行触发器;[DELETE ][[or] INSERT] [[or]UPDATE [OF 列名]]:表示该表发生那种DML操作时触发该触发器,如果需要监听多个DML操作,则使用or关键字连接;如果是监听update操作,还可以指定要监听该表的具体列,监听多列时,列名用逗号隔开;[FOR EACH ROW ]:表示该触发器的类别是行级触发器,缺省时代表是语句级触发器;[WHEN(条件) ]:表示该触发器执行的条件,默认是true,执行;触发器中的dml语句会自动commit提交,不用手动提交.
行级触发器和语句触发器的区别:
行级触发器:for each row,一次语句执行,执行一次触发器中的逻辑;语句级触发器:没有伪记录变量 多次的语句执行,才执行一次触发器中的逻辑;
触发器中的伪记录变量:每一个触发器都有默认的old和new变量,old代表变化之前的行记录,new代表变化后行记录
案例:
--定义前置触发器--自动计算每月用水量create trigger tri_account_usenumbefore --创建前置触发器update of num1 --触发器作用在某列的值改变on t_accountfor each rowdeclare--声明变量begin :new.usenum:=:new.num1-:new.num0;end;--定义后置触发器--当业主名称修改时,将修改之前的信息保存到信息记录表中--创建存储用户信息修改的日志表create table t_owners_log(v_updatetime date,v_oldname varchar2(30),v_newname varchar2(30),v_ownersid number);--创建后置触发器create trigger tri_owners_updateafterupdate of Name --在业主表的name列上创建触发器on t_ownersfor each rowdeclare--声明变量begin --触发器中的dml语句会自动提交事务,不用手动提交事务 insert into t_owners_log values (sysdate,:old.name,:new.name,:old.id);end;
- JavaWeb开发知识总结(四)-(oracle_编程)
- JavaWeb开发知识总结(一)-(oracle_基础)
- JavaWeb开发知识总结(二)-(oracle_查询)
- JavaWeb开发知识总结(三)-(oracle_对象)
- JavaWeb开发知识总结(tomcat)
- JavaWeb开发知识总结(tomcat)
- JavaWeb开发知识总结(Listener)
- JavaWeb开发知识总结(filter)
- JavaWeb开发知识总结(网上商城项目总结)
- JavaWeb前端开发知识总结(HTML)
- JavaWeb前端开发知识总结(CSS)
- JavaWeb前端开发知识总结(javaScript)
- JavaWeb前端开发知识总结(jQuery)
- JavaWeb前端开发知识总结(mysql)
- JavaWeb数据库开发知识总结(jdbc基础)
- JavaWeb数据库开发知识总结(jdbc进阶)
- JavaWeb数据库开发知识总结(xml)
- JavaWeb前端开发知识总结(CSS)
- BZOJ 2648: SJY摆棋子/BZOJ 2716: [Violet 3]天使玩偶 kdtree
- iOS开发-Umeng第三方登录-个人整理
- JavaWeb开发知识总结(三)-(oracle_对象)
- 50个必备的实用jQuery代码段+ 可以直接拿来用的15个jQuery代码片段
- 混合合作-竞争环境的多代理行动者鉴定
- JavaWeb开发知识总结(四)-(oracle_编程)
- 四级,傻逼了...
- MongoDB复制集深入(设计复制集,日志,写关注,读关注,标签)
- iOS开发-Realm数据库
- 同一个界面多个子控制器切换视图
- 剖析spring AOP工作原理
- 关于VS2017丢失 gdi32.lib 的一种解决思路
- JavaWeb开发知识总结(五)-(struts2_概述)
- JavaWeb开发知识总结(六)-(struts2_ognl_valuestack_interceptor)