标签:cap 多表 需求分析 模糊 完整性 直接 快捷 代码 出现
1.关系型数据库和结构化查询语言sql
2.Oracle,DB2,Sybase,MS SQL ,Mysql
3.实体,属性,关系 1521
4.oracle的服务:监听服务(远程访问需要)和数据库服务(要启动)
5.oracle的配置文件:
listener.ora(监听器服务的配置文件)和
tnsname.ora(监听器服务访问的配置文件)连接数据库的主机字符串(自定义:主机字符串包括远程IP
和数据库名了)
6.测试远程连接
net manager(配置主机字符串和监听器)
找安装路径的快捷方式:右击net manager打开文件
plsql工具:字体设置和显示行号 关键字大写
7.oracle的物理文件
分为三类:数据文件(.dbf)、控制文件(.ctl)、日志文件(.log)
8.oracle系统表(数据字典)
9.表空间(对应一个物理的磁盘存储位置)
CREATE TABLESPACE j1706 DATAFILE 'E:\oracle\product\10.2.0\oradata\orcl\j1706.dbf' SIZE 20M AUTOEXTEND ON ; 用户 授权 表
10.sql语句
SQL语句主要可以划分为以下几类:
DDL(Data Definition Language):数据定义语言,定义对数据库对象(库、表、列、索引)的操作。
CREATE、DROP、ALTER、RENAME、 TRUNCATE等
DML(Data Manipulation Language): 数据操作语言,定义对数据库记录的操作。
INSERT、DELETE、UPDATE
DCL(Data Control Language): 数据控制语言,定义对数据库、表、字段、用户的访问权限和安全级别。
GRANT、REVOKE等
Transaction Control:事务控制
COMMIT、ROLLBACK、SAVEPOINT等
(1)常用的数据类型 数值型(int、number)、字符型(char(固定长度)、varchar(可变长度)
varchar2(可变长度))、日期型date
(2)DDL(数据定义语言:表结构) 定义对数据库对象(库、表、列、索引)的操作
建表: create table tb_person( id int, name varchar2(15), sex char(3), age int ); 查询表: select * from tb_person; 删除表: drop table tb_person; 修改表; 增加列: alter table tb_person add(phone varchar2(18),address varchar2(30)); 改变列长度: alter table tb_person modify(phone varchar2(20)); 删除列: alter table tb_person drop(phone,address); 修改列名: alter table tb_person rename column phone to iphone7s; 修改表名: rename tb_person to tb_people; 截断表 当表结构必须保留, 而表数据不再需要的时候 TRUNCATE TABLE tb_person
(3)DML(数据操作语言) 定义对数据库记录的操作
插入: insert into tb_person(id,name,sex,age) values(1,'tom','男',20); 删除数据: delete from tb_personn;或者DDL中的截断: truncate table tb_person; 修改数据: update tb_person set age=21; update tb_person set age=21,id=2 where sex='男' and name='tom';
sql语句删除数据有几种方式?分别是什么?
答: 1. delete -- DML语句,delete语句最小单位是行,可以通过where选择删除,删除数据可以回滚, 保留表结构。最慢 2. truncate -- DDL语句,TRUNCATE是截断表的所有数据,删除数据不可以回滚,保留表结构。较快 3. drop -- DDL语句,删除表结构和表所有数据,并且不能回滚,慎用。最快
(4)事务控制
transaction control:事务控制 commit(提交)、rollbck(回滚)
(4)约束
check 检查约束 -- not null 非空约束(特殊的检查约束) unique 唯一约束 primary key 主键约束(非空且唯一) foreign key 外键约束(解决数据冗余问题) 列级约束: create table tb_person( id int primary key, name varchar2(18) not null, sex char(3) check(sex='男' or sex='女'), age int check(age>=18 and age<60), phone varchar2(20) unique, address varchar2(30), clazz_id int references tb_clazz(id) on delete cascade ); create table tb_clazz( id int primary key, code varchar2(15), name varchar2(15), bzr varchar2(20) );
外键中,当主表的记录被子表参照时,主表记录不允许被删除。 解决方案: 先删除字表数据,在删除父表数据。 先将字表关联数据设为null,在删除父表数据 先将子表数据修改,在删除父表数据。 on delete cascade 当删除父表数据时,级联删除子表数据。 on set null 当删除父表数据时,将关联的数据设置为null
表级约束: create table tb_student( id int, name varchar2(18), sex char(3), age int, phone varchar2(18), email varchar2(18), address varchar2(18), clazz_id int, constraints tb_students_pk primary key(id), check(name is not null), check(sex='男' or sex='女'), check(age>18 and age<50), unique(phone), unique(email), constraints tb_students_fk foregin key(clazz_id) reference tb_clazz(id) ); 自定义约束名:(约束 约束名 约束类型) constraints tb_students_pk 数据库建议建表: 外键以表级约束,其他用列级约束。 约束的维护(添加、删除): alter table tb_student add primary key(id); 删除约束根据约束名删除: alter table tb_student drop constraints tb_students_pk; 复合约束(只能在表级中定义): primary key(year,month) (5)nvl函数 nvl(第一个参数,第二个参数), 如果第一个参数为null,则取第二个参数 定义字段的别名as select empno as eID,ename,sal,sal*12 as yearsal from scott.emp; distinct关键字去除重复数据: select distinct deptno from scott.emp; 比较运算符: select *from scott.emp where sal>=800 and sal<=1600; select * from scott.emp where sal between 800 and 1600; select * from scott.emp where deptno=20 or deptno=30; select * from scott.emp where deptno in(20,30); 模糊查询like: %匹配所有 _匹配一个字符 select * from scott.emp where ename like 's%'; select * from scott.emp where ename like '%s'; select * from scott.emp where ename like '%s%'; select * from scott.emp where ename like '_s%'; 优先级规则:先and后or 对结果排序 order by asc(升序 默认) desc(降序) select * from scott.emp order by sal asc; select * from scott.emp order by sal desc; (6)多表连接 内连接(等值连接) 两个表(或连接)中某一数据项相等的连接称为内连接。 SELECT FROM dept d INNER JOIN emp e ON d.deptno = e.deptno'; 外连接(非等值连接) 用于查询一张表在另一张表中没有关联数据的信息 外连接分为三种: 左外连接(LEFT OUTER JOIN) 右外连接(RIGHT OUTER JOIN) 全外连接(FULL OUTER JOIN) -- 左外连接:+号在右边,左边的表的所有数据都要显示,如果右边表没有对应的数据,则补Null -- 右外连接:+号在左边,右边的表的所有数据都要显示,如果左边表没有对应的数据,则补Null -- 全外连接:两张表的所有数据都要全部显示 备份一张表(只备份数据,不备份约束): create table tb_emp as select * from scott.emp; select e.empno,e.ename,e.mgr,t.ename from scott.emp e,tb_emp t where e.mgr=t.empno and e.empno='7369'; 自连接: select e.empno,e.ename,e.mgr,t.ename from scott.emp e,scott.emp t where e.mgr=t.empno and e.empno='7369'; (7)组函数:(组函数都会忽略NULL值) 对一组值进行运算,并返回单个值,也叫聚合函数。 count(*|列名) 统计行数: select count(*) from scott.emp; select count(comm) from scott.emp; sum(数值类型列名) 求和: select sum(sal) from scott.emp; avg(数值类型列名) 平均值: select avg(sal) from scott.emp; max(列名) 最大值: select max(sal) from scott.emp; min(列名) 最小值: select min(sal) from scott.emp; (8)分组 group by 把该列具有相同值得多条记录当成一条记录处理,最后只输出一条记录。 分组函数忽略空值。结果集隐式按升序排列, 如果需要改变排序方式可以使用order by子句。 按部门分组: select deptno from scott.emp group by deptnot; 按工作岗位分组: select job from scott.emp group by job; group by子句的真正作用在于与各种组函数配合使用: select deptno,count(*),sum(sal),avg(sal),max(sal),min(sal) from scott.emp group by deptno;
面试题:数据条件筛选时有几种方式?有什么区别?
限定组的结果:having子句 having子句用来对分组后的结果进行条件过滤。 having和where的区别; where和having都是用于条件过滤。 where在分组前进行条件过滤,having子句是在分组后进行条件过滤, where子句中不能使用聚合函数,having子句可以使用聚合函数。 select deptno,count(*),sum(sal),avg(sal),max(sal),min(sal) from scott.emp group by deptno having sum(sal)>9000 order by sum(sal) desc;
(9)子查询 子查询就是把多条语句写成一条,子查询执行的时候先执行子查询 再执行主查询: select * from scott.emp where sal>( select sal from scott.emp where ename='allen' ); 子查询需要注意的问题:单行子查询返回多行 多行比较运算符: In:与列表中的一个值相等(包含) any:与子查询返回的每一个值比较 all:与子查询返回的所有值比较 in: select * from scott.emp where sal in( select min(sal) from scott.emp group by deptno ); any与子查询返回的每一个值比较 >any 大于最小的 <any 小于最大的 select * from scott.emp where sal>any( select min(sal) from scott.emp group by deptno ); all与子查询返回的所有值进行比较 >all 大于最大的 <all 小于最小的 select * from scott.emp where sal>all( select min(sal) from scott.emp group by deptno ); (10)集合运算:从多个结果集中提取数据 union 把两个结果集的数据合起来,然后干掉重复的 select deptno from scott.dept union select deptno from scott.emp; union all:把两个结果集的数据合起来 select deptno from scott.dept union all select deptno from scott.emp; intersect:把两个结果集的数据合起来,然后干掉重复的, 再找两个查询中都出现的记录 select deptno from scott.dept intersert slect deptno from scott.emp; minus:判断数据存在第一查询的结果集,而·不存在第二查询的数据集 select deptno from scott.dept minus slect deptno from scott.emp; 面试题: select r.id,r.R1,nvl(b.R2,'null') from r,b where r.id=b.id(+) union selet b.id,nvl(r.R1,'null'),b.R2 from r,b where r.id(+)=b.id; 标准外连接: select r.id,r.R1,b.R2 from r left outer join b on r.id=b.id union select b.id,r.R1,b.R2 from r right outer join b on b.id=r.id; 全外连接: select nvl(r.id,b.id) as id,r.R1,b.R2 from r full outer join b on r.id=b.id; (11)rownum 伪列 ‘结果集’中产生的序列 select rownum,deptno,dname,loc from scott.dept; 只有存在rownum=1的记录,才可能存在rownum=2的记录 利用rownum分页: select * from( select rownum as tempid,empno,ename from scott.emp )t1 where t1.tempid between 6 and 10; rowid:一般来说每一行数据对应一个rowid,而且固定且唯一。 在这一行存入数据库时就确定了。可以理解为java对象中的内存地址。 可以利用rowid来查询记录,而且通过rowid查询速度最快的查询方法。 rowid只有在表发生移动(比如表空间变化,数据导入/导出后)才会发生变化。 面试题: 删除重复数据(删除所有重复数据 /删除重复数据但保留一条(保留最大rowid或者最小)): 删除所有数据; delete from tb_test where name in( select name from tb_test group by name,age having count(*)>1 ); 删除数据,保留一条数据(第一种方法); create table tb_tmp as select distinct name,age from tb_test; truncate table tb_test; insert into tb_test(name,age) select name,age from tb_tmp; 删除数据,保留一条数据(方法二): delete from tb_test where rowid not in( select max(rowid) from tb_test group by name,age ); (12)常用函数 dual是oracle提供的一个虚表 select length('hello') from dual; 常用函数: lower把大写转成小写 upper把小写转大写: select upper('helloworld') from dual; select lower('HELLOWORLD') from dual; select * from scott.emp where ename='smith'; select * from scott.emp where lower(ename)='smith'; initcap使串中的所有单词首字母变成大写: select initcap('sql course') from dual; concat 连接两个字符串: select concat('Hello','World') from dual; substr 取字符串,从start开始,取count个: select substr('HelloWorld',1,5) from dual; 从4开始取到末尾: select substr('Helloworld',4) from dual; length 返回字符串的长度: select length('HelloWorld') from dual; instr 在一个字符串中搜索指定的字符,返回发现指定的字符的位置,从1开始: select instr('HelloWorld','l') from dual; trim 删除首尾的空字符串 select trim(' HelloWorld ') from dual; replace 替换: select replace('HelloWorld','ll','ff') from dual; round 四舍五入; select round(45.926,2) from dual; trunc 截断: select trunc(45.926,2) from dual; mod 取模: select mod(1600,300) from dual; decode函数: select ename,job,sal 基本工资,decode(job, 'salesman', sal*0.9, 'manager',sal*0.85, 'clerk',sal+100, 'pre sident',sal )as 实发工资 from scott.emp;
面试题: select name, sum(decode(t.course,'JDBC',t.grade,0)) JDBC, sum(decode(t.course,'Hibernate',t.grade,0)) Hibernate, sum(decode(t.course,'Spring',t.grade,0)) Spring from tb_course t group by t.name; 11.数据库对象 (1)数据库对象包括: 表、序列、同义字、数据库链接、视图等。 对象的特点:可以给其他对象使用,名字不能重复。 (2)序列:自动生成的唯一序列号,常用在主键自动生成。 创建序列: create seqeuence s_tb_student; 删除序列: drop seqeuence s_tb_student; 序列的两个属性currval,nextval: select s_tb_student.currval from dual; select s_tb_student.nextval from dual; 使用序列: insert into tb_student(id)values(s_tb_student.nextval); 序列不会随着rollback回滚,下面这些情况时sequence值可能产生间隙: 回滚发生; 序列用于多个表(不建议),建议一张表使用一个序列; 系统宕机。 (3)索引 面试:如何优化你的数据库查询? 1.数据库的查询方式? --全表扫描 select * from tb_student 慢 --利用索引扫描 快 --共享语句 最快(oracle有个回滚段,临时表空间) 索引 index 作用:在数据库中用来加速对表的查询 原理:通过使用快速路径访问方法快速定位数据,减少了磁盘的I/O 特点:与表独立存放,但不能独立存在,必须属于某个表 由数据库自动维护,表被删除时,该表上的索引自动被删除。 索引的创建: 自动:当在表上定义一个primary key或者unique约束1条件时,数据库会 自动创建一个对应的索引。 手动:用户可以创建索引以加速查询。 create index i_tb_student_name on tb_student(name); 查询的时候使用索引: select * from tb_student where name='Alice'; 删除索引: drop index i_tb_student_name; 当创建索引的时候,oracle会默认创建一个和当前表相关的索引页, 而索引页中保存了索引字段和真实的磁盘地址,当用户发送sql语句带了索引时, oracle会到索引页中查询索引字段,直接定位磁盘IO,提取数据。 所以索引数据快于全表扫描。 索引的维护 1.建立索引后,查询的时候需要在where条件中带索引字段才可以使用索引。 2.在经常查询的字段上面建立索引。不要在所有字段上建立索引。 3.因为索引是用来加速查询速度的,如果一张表经常做insert,delete, update ,而很少做select,不建议建立索引 如果一张表字段很少,不建议建立索引。 4.索引是由oracle自动维护的。索引使用久了会产生索引碎片 (磁盘碎片),影响查询效果,所以使用久了需要手动进行维护(删除在重建) sql语句的优化: 多使用共享语句,尽量使你的sql语句能够使用索引。 怎样使sql语句能够使用到索引呢? 当sql语句中包含not in,<>,is null,is not null,like'%%'的时候 不会使用索引。 in:可以使用索引。 优化方案: a<>0 改为a>0 or a<0 a is not null改为 a>0 或a>'' is null 用一个缺省值代替空值 like'%%'不能使用索引 like'001%'可以使用索引 (4)同义字 :通过创建同义字(对象的另外的一个名字)简化访问对象的操作。 create synonym tb_emp for scott.emp; select * from tb_emp; 删除:drop synonym tb_emp; 数据库链接--database link (5)视图 创建用户时通过dba角色赋予权限,而不是手动赋予权限,则会创建 视图会报:没有权限 解决方案:使用system用户登录,在给j1703赋予权限 grant create any table to j1703 with admin option; grant create any view to j1703 with admin option; grant select any table to j1703 with admin option; 所有数据字典都是视图: select * from User_Tables; 视图可以使复杂的查询变得简单 创建简单视图(一个表): create view v_deptinfo as select deptno as 部门,count(*) 人数,sum(sal) 总工资,avg(sal) 平均工资,max(sal) 最高工资,min(sal) 最低工资 from scott.emp group by deptno; 使用视图:select *from v_deptinfo; 复杂视图(多个表) 删除视图:drop view v_deptinfo; (6)数据建模(试规范题) 软件开发过程: 1. 需求调研,与客户进行沟通 2. 需求分析,将现实工作中的动作模拟到计算机 数据建模 3. 开发 4. 测试 5. 上线部署 从关系数据库的表中删除冗余信息的过程称为规范化, 是得到高效的关系型数据库表的逻辑结构最好和最容易的方法。 规范化数据时:应执行以下操作: 将数据库的结构精简为最简单的形式 从表中删除冗余值 标识所有依赖与其他数据的数据 获得数据化的三种方法:三范式 步骤1: 第一范式:必须要有主键,并且每个属性值都是不可分的最小数据单元 ,则称为是第一范式。 第二范式:所有非主关键字都完全依赖于主关键字(通常用于联合主键) 第三范式:非主关键字不能依赖于其他非主关键字(通常用于一个主键) 数据建模 1.根据三个范式 2.分析实体之间的关系 1对1:一个人只有一个身份证 唯一外键关联或者主键关联 一对多:一个班级可以有多个学生 一个学生只属于一个班级 关联:一对多使用主外键关联,通常在多方建立外键 多对多:一个学生可以选择多门课程 一门课程可以被多个学生选修 关联:多对多通常使用中间表(再多建一张表存储)关联数据 通常中间表会有两张表的id作为联合主键,并且 作为外键指向关联表 订单和用户之间的关系是多对一: create table tb_order( id int primary key, code varchar2(50), user_id int, foregin key(user_id) references tb_user(id) ); 订单和书籍是多对多关系: create table tb_item( order_id int, book_id int, count int, primary key(order_id,book_id), foregin key(order_id) references tb_order(id), foregin key(book_id) references tb_book(id) ); select * from tb_user u,tb_book b,tb_order o,tb_item i where u.id=o.user_id and o.id=i.order_id, and b.id=i.book_id
and u.name='jack'; 12.plsql(数据库编程语言) PL/SQL=传统SQL+结构化流程控制 好处:1.有结构化的流程控制,可以完成复杂的操作 2.性能高于sql sql:页面输入信息 -- servlet接收数据,调用持久层生成sql - sql语句发送到数据库(DBMS),数据库编译 -- 执行sql。 plsql:页面输入信息 -- servlet接收数据,调用持久层传入参数(调用存储过程) - 执行sql。 3.可以对程序中的异常进行处理 PL/SQL程序由三个块组成。 (1) 声明部分: 在此声明PL/SQL用到的变量,类型及游标,以及局部的存储过程和函数 (2)执行部分: 过程及SQL 语句 , 即程序的主要部分 (3) 异常处理部分: 错误处理 语法:declare --声明部分,用来定义变量等 begin--可以理解成java的花括号,编写代码的地方 exception--处理程序抛出异常 end; 第一个plsql,在控制台输出HelloWorld BEGIN --包名.过程('参数') dbms_output.put_line('HelloWorld!'); END; 定义变量,变量初始值都是null 常量constant declare v_id int; v_name varchar2(18):='jack'; v_clazz constant varchar2(5):='j1703'; begin v_id:=100; dbms_output.put_line('v_id='||v_id); dbms_output.put_line('v_name='||v_name); end; 复合变量(数据类型) record 1.包含多个内部组件,用于存放多个值 2.需要先定义类型,然后用该类型可重复定义多个变量 注意:复合变量属于数据类型,定义时前面要加TYPE TYPE是不能直接使用的,使用前需要定义变量引用 declare type r_tb_clazz is record ( id int, code varchar2(18) ); v_clazz r_tb_clazz; begin v_clazz.id:=1; v_clazz.code:='j1703'; end; plsql分两大类:匿名块,带名块 begin insert into tb_clazz(id,code) values(3,'j1703'); commit; end; select 1.缺少into子句,plsql目的是操作数据,需要定义变量 2.实际返回行数超过请求行数(只能查询一条数据,如果需要查询 多条数据,使用游标) 3.未找到数据 declare v_id int; v_code varchar2(18); begin select id,code into v_id,v_code from tb_clazz where id=1; dbms_output.put_link(v_id || '' || v_code); end; %type属性: 定义某个变量的数据类型与已经存在的变量数据类型, 某个列的数据类型相同。 declare v_id tb_clazzz.id%type; v_code tb_clazz.code%type; begin select id,code into v_id,v_code from tb_clazz where id=1; dems_output.put_line(v_id || '' || v_code); end; %rowtype属性: 用于定义不确定的类型的变量 当数据库中表字段的个数和数据类型会在运行中改变, 程序中的变量也会自动随之改变。 rt_tb_clazz tb_clazz%rowtype rt_tb_clazz 变量和tb_clazz表结构一致,相当于表结构的副本。 declare v_tb_clazz tb_clazz%rowtype; begin select id,code into v_tb_clazz.id,v_tb_clazz.code from tb_clazz where id=1; dbms_output.put_line(v_tb_clazz.id || '' || v_tb_clazz.code); end; declare v_tb_clazz tb_clazz%rowtype; begin select * into v_tb_clazz from tb_clalzz where id=1; dbms output.put_line(v_tb_clazz.id || '' || v_tb_clazz.code); end; 使用recode declare type r_tb_clazzz is recode ( id tb_clazz.id%type, code tb_clazz.code%type; ); v_tb_clazz r_tb_clazz; begin select * into v_tb_clazz from tb_clazz where id=1; dbms_output.putline(v_tb_clazz.id || '' || v_tb_clazz.code); end; 循环和判断 if分支 declare v_i number:=10; begin if(v_i=10)then dbms_output.putline('进入if块'); end if; end; if else分支 if ()then...else ...end if if elsif else分支 if() then...elsif()then ...else ...end if plsql的循环有三种:loop for while loop循环: loop v_i:=v_i+1;--自增 exit when v_i=5; end loop; 第二种结束方法: loop v_i:=v_i+1; if(v_i=5) then exit; end if; end loop; for循环 for v_i in 1..5 loop end loop; --重点 项目当中最常用的异常处理 --实际开发中异常的处理 重点 create table tb_error( id int primary key, errorObj varchar2(18),--抛出异常的对象 sqlcode varchar(50),--异常编码 sqlerrm varchar(200),--异常信息 currdate date --发生时间 ); create sequence s_tb_error; --重点掌握 --orale当抛出异常时会将异常编码存储到sqlcode函数,异常信息 -- 存储到sqlerrm declare v_id tb_clazz.id%type; v_code tb_clazz.code%type; begin select id,code into v_id,v_code from tb_clazz; dbms_output.put_line(v_id || '' || v_code ); exception when others then v_sqlcode :=sqlcode; v_sqlerrm:=sqlerrm; insert into tb_error(id,errorobj,sqlcode,sqlerrm,currdate) values(s_tb_error.nextval,'default',v_sqlcode,v_sqlerrm,sysdate); commit; end; --游标:用来提取多行数据 --oracle打开一个工作区(缓存)来保存多行查询的结果集, -- 游标就是给这个工作区命的名称,并能用于处理由多行查询而返回的 记录行 --隐式游标:默认的DML语句和select语句都有隐式游标 --显示游标:开发中给工作区命名,并且可以进行操作 --%isopen boolean 游标打开,则返回true --%nofound boolean 如果最近抓取没有获得记录,返回true --%found boolean 如果最近抓取获得记录,返回true --%rowcount number 返回到目前为止获取的记录数 --使用游标的步骤 --1.定义游标 cursor c_tb_clazz is select * from tb_clazz; --2.打开游标 open c_tb_clazz; --3.fetch游标 fetch c_tb_clazz into r_tb_clazz; -- 游标有个指针,默认指向第一行之上,fetch将指针向下移动,指向第n 行数据,如果有数据,notfound 返回false,found返回true 如果到末尾,抓取不到数据,一直显示最后一条数据 --4.关闭游标 close c_tb_clazz; --第一个例子 ;使用游标提取tb_clazz的所有数据 declare cursor c_tb_clazz is select * from tb_clazz; r_tb_clazz tb_clazz%rowtype; begin open c_tb_clazz; loop fetch c_tb_clazz into r_tb_clazz; dbms_output.put_line(r_tb_clazz.id || '' || r_ tb_clazz.code); end loop; close c_tb_clazz; end; --带参数的游标 第二个例子:使用游标提取tb_clazz的所有数据,同时提取每个班级的学生数据 --注意:传递是形参,形参是不用长度的 declare --班级游标 cursor c_tb_clazz is select * from tb_clazz; r_tb_clazz tb_clazz%rowtype; --学生游标 cursor c_tb_student(v_clazz_id tb_clazz.id%type) is select * from tb_student where clazz_id=v_clazz_id; r_tb_student tb_student%rowtype; begin open c_tb_clazz; loop fetch c_tb_clazz into r_tb_clazz; exit when c_tb_clazz%notfound; dbms_output.put_.line('班级' || r_tb_clazz.id || '' || r_tb_clazz.code); --当前班级的学生数据 --打开学生游标,参数是班级id open c_tb_student(r_tb_clazz.id); loop fetch c_tb_student into r_tb_student; exit when c_tb_student%nofound; dbms_output.putline(r_tb_student.id || '' || r_tb_student.name); end loop; close c_tb_student; end loop; close c_tb_clazz; end; --游标for循环 1.不需要显式打开游标 2.for循环自动隐式地定义recode变量 3.不需要使用fetch抓取数据 4.循环结束后,不需要使用close来关闭游标 declare cursor c_dept is select * from scott.dept; begin for re_dept in c_dept loop dbms_output.put_line(); end loop; end; --带名块(declare begin end; 就是匿名块) 是数据库中命名的PL/SQL块,作为数据库对象保存在数据库里。 主要四类: 存储过程:执行特定操作,无返回值 函数:进行复杂计算,有返回值 包:逻辑上相关的过程和函数组织在一起 触发器:事件触发,执行相应操作 过程和函数统称为PL/SQL子程序,过程和函数的唯一区别是函数总向调用者返回数据, 而过程则不返回数据。 --存储过程 语法:(直接创建) procedure name [(parameters)形参] is 局部变量声明 begin 语句; [exception] end; --建立存储过程,可以被多个程序调用(java或者c++),可以向 --存储过程传递参数,也可以让存储过程传出参数 --参数: --in:默认,值被传递给子程序。子程序不能改变参数值。 --out:值被返回调用环境(java或者c++),子程序会改变参数值。 --调用存储过程 begin insertclazz();--存储过程名 end; --调用存储过程通过带参数传给存储过程 --函数与过程语法差异: (1)在函数的声明中,必须包含一个带有数据类型的return字句, 返回值表示的类型,在函数体中必须有一个有效的return语句。 (2)只能使用in模式参数传入参数值 --语法: function name [(parameters)形参] return datatype is 局部变量声明 begin 语句; return value; [exception] end; 包类似于C++和Java语言中的类,其中变量相当于类中的成员变量,过程和函数相当于类方法。把相关的程序单元归纳到包里 通过使用包,可使开发人员利用面向对象的方法进行存储过程的开发,从而提高系统性能。 --触发器 --触发器是当某个事件发生时自动隐式运行。而且,触发器不能 接收参数。 --触发器最主要作用:提供更灵活的完整性校验规则。 --语法: trigger name after|berfore is 局部变量声明; begin 语句; [exception] end; --触发器的组成成分: 触发事件:在任何情况下触发trigger(insert,undate,delete等) 触发时间:before或者after 触发器本身:该trigger被触发后的执行体 触发频率:动作被执行的次数(主要行级触发器) 当行级触发器被触发时,如果要访问插入,更新或删除的记录的值, 可以使用: :new 访问操作完成后的值 :old 访问操作前的数据 --特性 insert update delete :old Null 有效 有效 :new 有效 有效 null 当删除tb_tran的数据时,将数据备份到tb_back: create or replace trigger t_del_tran before delete on tb_tran for each row declare begin insert into tb_back(id,accout,amount,currdate) values(:old.id,:old.Accout,:old.Amount,:old:Currdate); end t_del_tran; 触发器还可以用来维护数据完整性: create or replace trigger t_del_clazz before delete on tb_clazz for each row declarer begin delete from tb_student_course where student_id in ( select id from tb_student where clazz_id=:old.id ); delete from tb_student where clazz_id=:old.id; end t_del_clazz;
标签:cap 多表 需求分析 模糊 完整性 直接 快捷 代码 出现
原文地址:http://blog.51cto.com/10913595/2071359