Oracle SQL&PLSQL学习笔记

SQL语言共分为四大类:数据查询语言DQL,数据操纵(增删改)语言DML,数据定义语言DDL()表、视图、索引、同义词、聚簇等DDL操做是隐性提交的!不能rollback),数据控制语言DCL()授予或回收访问数据库的某种特权,并控制数据库操纵事务发生的时间及效果,对数据库实行监视等。node

DAY1sql

 

--oracle的数据类型数据库

 

--字符类型:session

 

--char : 定长,最大2000字符oracle

--例子:char(10)  '张三',后6位空格补全 ide

--特色:查询速度极快函数

 

--varchar2 : 变长,最大4000字符oop

--例子:varchar2(10) '张三'fetch

--特色:节省空间ui

 

--clob : 字符型大对象,最大4G

 

--数字类型:

 

--number:既能够表示整数也能够表示小数

 

--范围:-10e38-10e38

 

--整数:number(3),表示一个3位的整数,范围-999-999

 

--小数:number(5,2),表示一个小数,该小数一共5位,其中小数部分占2位,范围:-

999.99-999.99之间

 

--日期类型:

 

--date:包含年月日时分秒

 

--timestamp:oracle对date类型的扩展,比date更加精确

 

--二进制数据类型:

 

--blob:二进制数据,能够存放图片,音频,视频,范围4G

 

--通常不会把图片和声音存放在数据库中,一般的作法是将图片或音频的路径存在数据库

中(char/varchar2),若是保密性要求很是高,能够存放到数据库中。

 

--SQL语言:结构化查询语言

 

--建表

 

--表名和列名的命名规则:

 

--1,必须以字母开头

--2,长度不能超过30个字符

--3,不能使用oracle关键字和保留字

--4,只能使用以下字符:A-Z,a-z,0-9,#$等

--5,oracle不要使用中文

 

--建立学生表

 

create table student(

stuno number(4) primary key,

stuname char(50),

gender char(3),

age number(3),

birthday date,

jxj number(7,2),

classno number(3),

--外键,classno是外键,该列的数据受classes表的cno的约束(classno的值必须来自于

classes的cno字段的值)

constraint fk_classes foreign key(classno) references classes(cno)

)

 

--建立班级表:班级编号,班级名称

 

create table classes(

cno number(3) primary key,

cname varchar2(100)

)

 

--oracle中的约束

SQL 使用单引号来环绕文本值(大部分数据库系统也接受双引号)。若是是数值,请不要使用引号。

--oracle中,约束包括:not null,unique,primarykey,foreign key,check五种

 

--1,not null:非空

 

create table tab1(

      tid number(3) not null,

      tname varchar2(20)

)

 

--2.unique:惟一

 

create table tab2(

tid number(2) not null,

sfz char(18) unique

)

 

--primary key :主键约束(非空+惟一)

--一个表中只能有一个主键,可是主键能够由多个列组成(联合主键)

 

create table tab3(

tid number(5) primary key,

tname varchar2(50),

address varchar2(100)

)

 

create table tab4(

stuno number(5),

school varchar2(50),

--address varchar2(100) primary key,

primary key(stuno,school)--联合主键

)

 

--check约束

 

create table tab5(

tid number(5) primary key,

age number(3) check (age>0 andage<=120),

gender char(3) default '' check(gender='' or gender='') ,

jxj number(7,2) default 0.0

)

 

--foreign key :外键约束

 

 

DAY2

--做业:

 

--商店售货系统:

 

--现有一个商店的数据库,记录客户及其购物状况,由下面三个表组成:

 

--商品表goods(商品编号,商品名称,单价,商品类别,供应商)

--客户表customer(客户编号,姓名,地址,电子邮件,性别,身份证号码)

--购买表perchase(客户编号,商品编号,购买数量,购买时间)

 

--要求:

 

--每一个表都要有主键

--相关联的表有外键

--客户姓名不能为空,身份证惟一,电子邮件惟一

--单价大于0,购买数量在1-50之间

--客户性别只能是男或女,默认男

 

create table goods(

gid number(5) primary key,

gname varchar2(100),

price number(10,2) check (price>0),

gtype varchar2(100),

provider varchar2(100)

);

 

create table customer(

cid number(5) primary key,

cname char(20) not null,

address varchar2(100),

email varchar2(50) unique,

gender char(3) default '男'check(gender='男' or gender='女'),

sfz char(18) unique

);

 

create table perchase(

cid number(5),

gid number(5),

buyaccount number(2) check(buyaccount>0 andbuyaccount<=50),

buytime date,

primary key(cid,gid,buytime),

constraint fk_goods foreign key(gid)references goods(gid),

constraint fk_customer foreign key(cid)references customer(cid)

);

 

--添加数据

 

--查看表结构

desc student

 

insert into student(stuname,stuno,gender,age)values ('李四',333,'男',20)

 

--向所有字段添加数据,此时字段名能够省略

--添加空值

insert intostudent--(stuno,stuname,gender,age,birthday,jxj,classno)

values

(112,'张三2','男',22,'01-10月-98',null,1)

 

--修改默认的日期格式(临时)

alter session set nls_date_format='yyyy-mm-dd';

 

insert into student

values

(113,'张三2','男',22,'1998-2-16',100,1)

 

--修改数据

 

update student set stuname='李思思',gender='女',age=18where stuno=333

--有奖学金的同窗奖金翻倍

update student set jxj=jxj*2 where jxj isnot null;

 

--没有奖学金的同窗发50

update student set jxj=50 where jxj is null;

 

--注意:若是update语句中没有where条件,则更新所有数据

 

--删除数据

 

delete from student where stuno=1;

 

--注意:若是delete语句中没有where条件,则删除所有数据

 

--还有一种删除所有数据的方法

 

truncate table student;

 

--小结:清空表有两种方式:1,delete fromstudent;2,truncate table student

--两种方式的区别:

--1,delete的速度慢,truncate速度快

--2,delete删除的数据能够恢复,由于写了日志,而truncate删除的数据没有写日志,不能恢复

--3,若是表中的数据很大,而且肯定要完全删除数据,此时可使用truncate,不然就使用delete

 

--删除表结构

drop table student;

 

--查询

 

--查询所有数据

 

select * from emp;

 

--查询部分字段(指定的列)

 

select empno,sal,ename,job from emp;

 

--查询所有职位

select job from emp;

 

--去掉重复行

select distinct job from emp;

select distinct deptno from emp;

 

--查询KING的信息

SELECT * from EMP where ename='KING';

 

--oracle语句不区分大小写,可是数据要区分

 

--查询部门编号为10号部门员工的姓名,上级,职位,部门编号

select ename,mgr,job,deptno from emp wheredeptno=10;

 

--查询工资在1000到2000之间的员工

 

select * from emp where sal>=1000 andsal<=2000

select * from emp where sal between 1000and 2000

 

--查询30号部门工资在1000到2000之间的员工

select * from emp where sal between 1000and 2000 and deptno=30

 

--查询工资低于1000和高于3000的员工

select * from emp where sal<1000 orsal>3000;

 

--查询1982,1,1,年以后入职的员工

select * from emp wherehiredate>='1982-01-01';

 

--查询1981年入职的员工

select * from emp where hiredate between'1981-01-01' and '1981-12-31';

 

--查询每一个员工的年薪(as能够省略)

select (sal+nvl(comm,0))*12 as 年薪,ename,sal,commfrom emp;

--说明:nvl(comm,0)的含义是:若是commnull,则使用0参与运算

 

--模糊查询

--like关键字

--%:表示匹配0-N个字符

--_:表示匹配1个字符

 

 

--查询名字首字母为M的员工

select ename from emp where ename like'M%';

 

--查询名字第三个字母为A的员工

SELECT * from emp where ename like '__A%';

 

--查询姓名为KING,SCOTT,MILLER的员工的信息

select * from emp where ename='KING' ORENAME='SCOTT' OR ENAME='MILLER'

select * from emp where ename in('KING','SCOTT','MILLER')

--where条件中,使用in比使用or效率高

 

--查询没有上级的员工

select * from emp where mgr is null;

 

--查询工资高于1000或者职位为MANAGER的员工,同时知足其姓名首写字母为J

select * from emp where (sal>1000 orjob='MANAGER') and ename like 'J%';

 

--排序

 

--按照员工编号有小到大排序(asc能够省略)

select * from emp order by empno asc;

 

--按照员工编号由大到小

select * from emp order by empno desc;

 

--查询员工姓名,工资,按照工资由高到低排序

select ename,sal from emp order by saldesc;

 

--查询员工信息,按照部门编号升序而员工工资降序排列

select * from emp order by deptno,sal desc;

 

--查询员工信息,按照部门编号降序员工入职时间升序

select * from emp order by deptnodesc,hiredate;

 

--使用别名排序

select ename, (nvl(comm,0)+sal)*12 年薪 from emporder by 年薪 desc

 

--数据分组:max,min,avg,sum,count

 

--查询最高工资是多少

select max(sal) from emp;

 

--查询最高工资和最低工资,平均工资,总工资是多少

select max(sal),min(sal),avg(sal),sum(sal)from emp;

 

--查询公司员工人数

select count(*) from emp;

 

--查询工资最低的员工信息

--select *,min(sal) from emp;

--子查询

select * from emp where sal=(selectmin(sal) from emp);

 

--查询工资高于平均工资的员工

select * from emp where sal>(selectavg(sal) from emp);

 

--把工资低于平均工资的,入职时间在1982年以前的员工,工资增长10%

update emp set sal=sal+sal*0.1 wherehiredate<'1982-01-01' and sal<(select avg(sal) from emp);

 

--分组

 

--group by:用于对查询结果分组

 

--查询每一个部门的最高工资和最低工资

select max(sal),min(sal),deptno,sal fromemp group by deptno;

 

--查询每一个部门的每种职位的最高工资和最低工资

select min(sal),max(sal),deptno,job fromemp group by deptno,job order by deptno;

 

--having:用于分组后结果的筛选

 

--查询平均工资低于2000的部门及其平均工资

select avg(sal) 部门平均工资,deptnofrom emp group by deptno having avg(sal)<2000;

 

--小结:

--1.若是使用group by,那么在select后面只能跟分组函数和groupy by后面跟的字段

--2.分组后的筛选用having而不能用where

--3.顺序:groupby,having,order by

 

查询emp 每一个部门最高薪资大于2800的员工记录select e.* from emp e,(select deptno,max(t.sal)m from(select * from emp where(sal>2800))t group by deptno) d where (e.deptno =d.deptno and e.sal = d.m);

 

 

 

 

 

DAY3

--多表查询

 

--查询员工姓名及所在部门名称

 

--dept表和emp表作笛卡尔乘积

 

select * from emp,dept;

 

--就笛卡尔乘积的结果进行筛选

 

select * from emp,dept whereemp.deptno=dept.deptno;

 

--查询指定的列

 

select emp.ename,dept.dname from emp,deptwhere emp.deptno=dept.deptno;

 

--给表取别名

 

select e.ename,d.dname from emp e,dept dwhere e.deptno=d.deptno;

select e.ename,d.dname from emp e join deptd on e.deptno=d.deptno;

 

--数据库笛卡尔乘积的原则:

--若是n张表作乘积,至少须要n-1个条件

 

--查询10号部门的部门名称,员工姓名,工资

 

select d.dname,e.ename,e.sal from empe,dept d where e.deptno=d.deptno and d.deptno=10;

select d.dname,e.ename,e.sal from emp ejoin dept d on e.deptno=d.deptno and d.deptno=10;

 

--查询员工姓名,工资,及工资的级别

 

select e.ename,e.sal,s.grade from empe,salgrade s where e.sal between s.losal and s.hisal;

 

--查询员工姓名,工资,部门名称,按照部门编号排序

 

select e.ename,e.sal,d.dname from empe,dept d where e.deptno=d.deptno order by e.deptno desc;

 

--查询scott的上级的姓名

 

select a.ename,b.ename 上级名字 from empa,emp b where a.mgr=b.empno and a.ename='SCOTT';

 

--联合查询

 

--库存表

create table kucun(

kid number(5) primary key,

gname varchar2(100),--产品名称

kaccount number(5)--库存数量

);

--订单表

create table dingdan(

did number(5) primary key,

gname varchar2(100),--产品名称

daccount number(5)--数量

) ;

 

--产品表

create table chanpin(

cid number(5) primary key,

gname varchar2(100),--产品名称

price number(7,2)--单价

);

 

insert into chanpin values(1,'电脑',2000);

insert into chanpin values(2,'苹果',5);

insert into chanpin values(3,'手机',7000);

 

insert into kucun values(1,'苹果',100);

insert into kucun values(2,'鼠标',1000);

insert into kucun values(3,'门',10);

 

insert into dingdan values(1,'苹果',5);

insert into dingdan values(2,'键盘',50);

insert into dingdan values(3,'手机',10);

 

--查询能够出货的产品(某个产品既有订单,又有库存)

select k.*,d.* from kucun k,dingdan d wherek.gname=d.gname;

 

--查询全部库存产品,以及那些库存产品有了订单???????(使用联合查询)

 

/*

联合查询:join....on....

join的做用是将两个或两个以上的表记录横向链接起来,on的做用是设置查询条件,将无用的记录过滤掉

分类:

1.内部联接:[inner] join

2.左外部联接 left [outer]join

3.右外部联接 right [outer]join

4.彻底外部联接 full [outer]join

5.交叉联接 cross join

*/

 

--1.内部联接:[inner] join

--内部联接只显示符合条件的记录

 

--查询能够出货的产品(某个产品既有订单,又有库存)

select * from kucun k inner join dingdan don k.gname=d.gname;

select * from dingdan k inner join kucun don k.gname=d.gname;

 

--三张表

select * from dingdan d join kucun k ond.gname=k.gname join chanpin c on d.gname=c.gname;

select k.*,d.*,c.* from kucun k,dingdand,chanpin c where k.gname=d.gname and d.gname=c.gname;

 

--2.左外部联接 left [outer]join

--显示左边表中全部的记录,以及右边表中符合条件的记录

 

--查询全部库存产品,以及哪些库存产品有了订单

select * from kucun k left outer joindingdan d on k.gname=d.gname;

 

--3.右外部联接 right [outer]join

--查询右边表中全部的记录,以及左边表中符合条件的记录

 

--查询全部库存产品,以及哪些库存产品有了订单

select * from dingdan d right outer joinkucun k on d.gname=k.gname;

 

--4.彻底外部联接 full [outer]join

--查询所有数据,包括符合条件的和不符合条件的

--查询全部的库存和订单,显示哪些库存没有订单,以及哪些订单没有库存

select * from dingdan d full join kucun kon d.gname=k.gname;

 

--5.交叉联接 cross join(笛卡尔乘积):没有on来设置条件

 

select * from kucun cross join dingdan;

 

/*集合操做:并集,交集,差集

 

并集(union):union的做用是将两个或多个查询的结果合并为一个结果集。该结果集包含联合查询中的全部查询的所有行,

union运算不等同于join运算,join是将两个或多个数据表的字段进行水平合并,通常来讲,合并后的字段数会增长,

union是将多个查询结果上下叠加,合并后字段数不会增长,但记录总数会增长。

*/

 

create table stuInfo(

stuid number(5) primary key,

stuname varchar2(50)

);

 

create table userinfo(

userid number(5) primary key,

username varchar2(50)

);

 

insert into stuinfo values(1,'张三');

insert into stuinfo values(2,'张三三');

insert into stuinfo values(3,'李四');

 

insert into userinfo values(1,'张三');

insert into userinfo values(2,'张三三');

insert into userinfo values(3,'王五');

 

--查询全部注册了的和未注册的学生

 

--合并了相同的结果

select * from stuinfo where stuid=3 unionselect * from userinfo where userid=3;

 

--不合并相同结果

select * from stuinfo union all  select * from userinfo;

 

--交集(intersect):合并两个结果集,返回两个查询相同的全部非重复的值

 

--查询两个表中都有的信息

 

select * from stuinfo intersect select *from userinfo;

 

--差集(minus):合并两个结果集,该结果集比较两个查询的结果,从左查询中返回右查询中没有的非重复的值

 

--查询没有注册的学生

 

select * from stuinfo minus select * fromuserinfo;

 

--子查询

 

--子查询是指嵌入在其余sql语句中的select语句,也叫做嵌套查询

 

--单行子查询:只返回一行数据的子查询

 

--查询与SCOTT相同部门的员工

 

select deptno from emp where ename='SCOTT';

 

select * from emp where deptno=(selectdeptno from emp where ename='SCOTT');

 

--多行子查询:子查询返回多行数据

 

--查询和部门编号为10号的部门职位相同的员工的信息

 

select job from emp where deptno=10;

 

select * from emp where job in(select job from emp where deptno=10);

 

--all关键字

 

--查询工资比30号部门全部员工都高的员工信息

 

select max(sal) from emp where deptno=30;

select * from emp where sal>(selectmax(sal) from emp where deptno=30);

 

--all关键字

select * from emp where sal>all(selectsal from emp where deptno=30);

 

--从效率上来说,第一种方式要高的多

 

--any关键字

 

--查询工资比30号部门任意一个员工工资高的员工信息

 

select * from emp where sal>(selectmin(sal) from emp where deptno=30);

 

--使用any关键字

 

select * from emp where sal>any(selectsal from emp where deptno=30);

 

--多列子查询:子查询返回多列

 

--查询跟SCOTT相同部门和职位的员工信息

 

select * from emp where (job,deptno)=(select job,deptno from emp whereename='SCOTT');

 

--查询工资高于本身所在部门平均工资的员工信息

 

--1.查询各个部门的部门编号和平均工资

select deptno,avg(sal) 平均工资 from empgroup by deptno;

--2.将上面的查询结果当成一张表,跟emp表作多表查询

select * from emp e,(select deptno,avg(sal) 平均工资 from emp group bydeptno) a

where e.deptno=a.deptno and e.sal>a.平均工资;

 

--事务

/*

事务用于保证数据的一致性,由一组相关的dml(增删改)语句组成,该组成的语句要么所有成功,要么所有失败。

事务是很必要的,好比,网上转帐系统,就是典型的须要用事务来处理。

*/

 

--设置保存点

savepoint a;

 

--取消部分事务

rollback to a;

 

--取消所有事务

rollback;

 

/*

事务的实现:锁

当执行事务的时候,oralce会在被做用的表上加锁,防止其余用户改表结构。

*/

 

/*

事务的提交:commit

执行commit以后,会确认事务的变化,事务结束,删除保存点,释放锁。

*/

 

--函数(库)

 

--字符函数

 

--lower(char):将字符串转换为小写

 

--以小写字母显示全部员工姓名

select lower(ename) from emp;

 

--upper(char)

--以大写字母显示员工姓名

select upper(lower(ename)) from emp;

 

--length(char):返回字符串长度

 

--查询名字为4个字母的员工

select * from emp where length(ename)=4;

 

--substr(char,m,n):截取子串,从第m个字符开始,n表示截取的长度

 

--显示全部员工姓名的前三个字母

select substr(ename,1,3) from emp;

 

--以首字母大写,其他字母小写的方式显示员工姓名

select upper(substr(ename,1,1)) from emp;--首字母大写

select lower(substr(ename,2,length(ename)-1))from emp;--其他字母小写

select upper(substr(ename,1,1))||lower(substr(ename,2,length(ename)-1))from emp;--合并

selectINITCAP(ename) from emp;

--replace(char,c1,c2)

--用哈哈替换姓名中全部的字母A

select replace(ename,'A','哈哈') FROMEMP;

 

--数学函数

 

--round(n,m):执行四舍五入,m能够省略,若是省略m,则四舍五入到整数,若是m是正数,则四舍五入到小数点的m位后,

--若是m是负数,则四舍五入到小数点的m位前

 

--保留工资小数点后一位,四舍五入

select ename,round(sal,1) from  emp;

 

--trunc(n,m):截取,不会四舍五入,多的位数直接舍弃

 

--保留工资小数点后一位,多的截取

select ename,trunc(sal,1) from emp;

 

--floor(n):向下取整

select floor(sal) from emp;

 

--ceil(n):向上取整

select ceil(sal) from emp;

 

--mod(m,n)取模

 

--计算10÷3的余数

select mod(10,3) from dual;--dual是一张虚拟表

 

--查询全部员工的日薪

 

select ename, ceil(sal/21.75) from emp;

 

select ename,trunc(sal/21.75) from emp;

 

select ename,round(sal/21.75) from emp;

 

--日期函数

 

--sysdate

 

select sysdate from dual;

 

--将字符串转换为日期

select to_date('1982','yyyy') from dual;

 

--将日期转换为字符串

select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') fromdual;

 

--add_months(d,n):加月份

 

--查询已经转正的员工(试用期三个月计算)

 

select * from emp whereadd_months(hiredate,3)<sysdate;

 

select * from emp whereadd_months(hiredate,4)<to_date('1982-1-1','yyyy-mm-dd');

 

--查询入职满5年的员工

 

select * from emp whereadd_months(hiredate,5*12)<sysdate;

 

--查询每一个员工的入职天数

select ename,trunc(sysdate-hiredate) 入职天数 fromemp;

 

--last_day(d):返回指定日期所在月份的最后一天

 

select ename,last_day(hiredate) from emp;

 

--查询每月倒数第三天入职的员工

 

select * from emp wherelast_day(hiredate)-2=hiredate;

 

--系统函数:sys_context('userenv',选项)

/*

选项能够是:

language:当前系统语言

db_name:当前数据库名字

nls_date_format:当前会话的日期格式

session_user:当前会话所对应的数据库用户名

current_schema:当前方案名

host:主机名

*/

 

select sys_context('userenv','host') fromdual;

 

 

4. 选择雇用时间在1981-02-01到1981-05-01之间的员工姓名,职位(job)和雇用时间,按从早到晚排序.
   select ename "姓名",job "职位",hiredate "雇佣时间"
   from emp where hiredate between to_date('1981-02-01','YYYY-MM-DD')and to_date('1981-05-01','YYYY-MM-DD')
   order by hiredate asc

 

6. 选择在1987年雇用的员工的姓名和雇用时间
   select ename "姓名",hiredate"雇佣时间" from emp whereto_char(hiredate,'YYYY')='1987'
   取出雇用时间的年份且转换为字符形式;而后与'1987'比较
   select ename "姓名",hiredate"雇佣时间" from emp where to_char(hiredate,'MM')='04'
   select ename "姓名",hiredate"雇佣时间" from emp where to_char(hiredate,'MM')='4'
   前者是能够的,后者不可

 

DAY4

/*

pl/sql

procedure language/sql

是oracle在标准的sql语言上的扩展,能够定义变量,可使用条件分之和循环,容许使用例外处理各类错误。

 

分类:

过程

函数

触发器

 

编码规范:

变量:建议使用v做为前缀 v_name

常量:建议使用c做为前缀 c_pai

游标:建议使用cursor做为后缀 user_cursor

例外:建议使用e做为前缀 e_exception

*/

 

/*

 

块是pl/sql的基本单元

 

组成:定义部分,执行部分,例外处理部分

 

基本语法:

 

declare

定义部分

begin

  执行部分

  exception

    例外处理部分

end;

 

*/

 

set serveroutput on;--打开输出选项

 

--helloworld

 

begin

 dbms_output.put_line('hello world');

end;

 

--输入员工编号,获取员工姓名并输出

 

declare

v_ename varchar2(10);

v_job varchar2(20);

begin

 select ename,job into v_ename,v_job from emp where empno=&n;

 dbms_output.put_line('员工的姓名是:'||v_ename||',职位是:'||v_job);

end;

 

--处理输入不存在的员工编号

 

declare

v_ename varchar2(10);

begin

  select ename into v_ename from emp whereempno=&n;

  dbms_output.put_line('员工的姓名是:'||v_ename);

  --处理例外

  exception

    when no_data_found then

      dbms_output.put_line('输入的编号不存在');

end;

 

--(存储)过程

 

create procedure pro1 is

begin

 insert into stuinfo values(5,'哇哈哈');

end;

 

--输入员工编号,新的工资,更新员工工资

 

create or replace procedure pro2(enonumber,newsal number) is

begin

 update emp set sal=newsal where empno=eno;

end;

 

--函数

 

--输入员工姓名,返回员工年薪

 

create or replace function fun1(empname varchar2)

return number is nx number(7,2);

begin

 select (sal+nvl(comm,0))*12 into nx from emp where ename=empname;

 return nx;

end;

 

--函数的调用

 

var a number;

call fun1('SMITH') into:a;

 

--包:包是过程和函数在逻辑上的组合。由包规范和包体两部分组成。

 

--定义包,放入一个过程和一个函数

create or replace package pac1 is

procedure updateuname(usersidnumber,newname varchar2);

function getusernamebyid(usersid number)return varchar2;

end;

 

--建立包体,实现上面的包

 

create or replace package body pac1 is

procedure updateuname(usersidnumber,newname varchar2) is

 begin

   update userinfo set username=newname where userid=usersid;

  end;

function getusernamebyid(usersid number)return varchar2 is

 returnname varchar2(10);

 begin

   select username into returnname from userinfo where userid=usersid;

   return returnname;

 end;

end;

 

--调用

var b varchar2;

call pac1.getusernamebyid(1) into:b;

 

--练习:建立包规范,包含一个过程(输入员工编号,新的职位,修改该员工职位),

--一个函数(输入员工编号,获取员工日薪),实现该包规范的包体

 

--触发器:当发生特定事件的时候,触发器自动执行

 

--向userinfo表中添加一条数据时,提示“添加了一条数据”

 

create or replace trigger trig1

after insert on userinfo

begin

 dbms_output.put_line('添加了一条数据');

end;

 

--语句级触发

create or replace trigger trig2

after update on userinfo

begin

 dbms_output.put_line('修改了一条数据');

end;

 

--行级触发

create or replace trigger trig2

after update on userinfo

for each row--表示是行级触发

begin

 dbms_output.put_line('修改了一条数据');

end;

 

--orcle中,自动增加,是经过序列实现的

 

create sequenceseq_stuid

start with 1

increment by 1

maxvalue 99999

cache 20;

 

--向stuinfo表中添加数据

insert into stuinfo values(seq_stuid.nextval,'张三','stu001');

insert into stuinfovalues(seq_stuid.nextval,'张三2','stu002');

insert into stuinfo values(seq_stuid.nextval,'张三3','stu003');

insert into stuinfovalues(seq_stuid.nextval,'张三4','stu004');

 

--触发器实例之一:实现触发器:每次向stuinfo表中添加数据以前,自动从序列产生一个数字,填入stuid

create or replace trigger trig_stuid

before insert on stuinfo

for each row

 declare

  newid stuinfo.stuid%type;--newid的数据类型是stuinfo表中的stuid字段的类型

  begin

    select seq_stuid.nextval intonewid from dual;

    :new.stuid:=newid;--:new表示新插入的那条数据

  end;

 

--实现id自动增加

insert into stuinfo(stuname,stuno)values('李四','stu110'); 

 

--触发器实例之二:写日志

 

--建立日志表,该表记录对stuinfo表的操做

create table stuinfolog(

operuser varchar2(20),--操做的帐户

opertype varchar2(10),--操做的类型:insert,update,delete

operdate date--时间

)

 

--建立写日志的触发器

create or replace trigger trig_stuinfo

after insert or update or delete onstuinfo

begin

   if insertingthen

      insert into stuinfologvalues(user,'insert',sysdate);

   elsif updatingthen

     insert into stuinfolog values(user,'update',sysdate);

   elsif deletingthen

     insert into stuinfolog values(user,'delete',sysdate);

   end if;

end;

 

--变量

 

--变长字符串

v_name varchar2(10);

 

--定义小数,初始值为3.14

c_pai number(3,2):=3.14;

 

--日期类型

c_date date;

 

--定义布尔类型,不能为空,初始值为false

v_b boolean not null default false;

 

--输入员工编号,输出员工姓名,工资,我的所得税,用块实现

 

declare

 v_ename emp.ename%type;

 v_sal emp.sal%type;

 v_tax number(5,2);

 c_rate number(3,2):=0.03;

begin

 select ename,sal into v_ename,v_sal from emp where empno=&n;

  --计算税

 v_tax:=v_sal*c_rate;

 dbms_output.put_line('姓名:'||v_ename||',工资:'||v_sal||',税:'||v_tax);

end;

 

--游标

 

--输入部门编号,输出该部门的员工姓名,职位,工资

 

declare

  --定义游标类型

 type emp_cursor_type is ref cursor;

  --定义游标变量

 emp_cursor emp_cursor_type;--e_name varchar2(10)

  --定义其余变量

 v_ename emp.ename%type;

 v_job emp.job%type;

 v_sal emp.sal%type;

begin

  --使用游标指向查询结果

 open emp_cursor for select ename,job,sal from emp where deptno=&n;

  --循环取出

 loop

   fetch emp_cursor into v_ename,v_job,v_sal;

   exit when emp_cursor%notfound;

   dbms_output.put_line('姓名:'||v_ename||',工资:'||v_sal||',职位:'||v_job);

  endloop;

end;

 

--条件分之语句

 

--1.if-then

 

--输入员工姓名,若是员工工资低于1000,就给加薪10%

 

create or replace procedure pro3 (empnamevarchar2) is

v_sal emp.sal%type;

begin

 select sal into v_sal from emp where ename=empname;

  --判断

  ifv_sal<1000 then

   update emp set sal=sal*1.1 where ename=empname;

  endif;

end;

 

--2.IF-THEN-ELSE

 

--输入员工姓名,若是该员工奖金为0,则奖金变为50,若是奖金不为0,则增长80

 

create or replace procedure pro4 (empnamevarchar2) is

v_comm emp.comm%type;

begin

 select comm into v_comm from emp where ename=empname;

 

  ifv_comm<>0 then

   update emp set comm=comm+80 where ename=empname;

  else

   update emp set comm=50 where ename=empname;

  endif;

end;

 

--if-then-elsif-else

 

--输入员工姓名,若是职位是CLERK,则工资增长50,若是职位是MANAGER,则工资增长80,其余职位,工资增长20

 

create procedure pro5(empname varchar2) is

v_job emp.job%type;

begin

 select job into v_job from emp where ename=empname;

 

  ifv_job='CLERK' then

   update emp set sal=sal+50 where ename=empname;

 elsif v_job='MANAGER' then

   update emp set sal=sal+80 where ename=empname;

 else

   update emp set sal=sal+20 where ename=empname;

  endif;

end;

 

--循环

 

--loop:相似于do-while

 

--输入用户名,向userinfo表中增长10条记录,编号从1-10

 

create procedure pro6(usname varchar2) is

--定义循环变量,初值为1

v_i number(2):=1;

begin

 loop

   insert into userinfo values(v_i,usname);

   --循环变量自增

   v_i:=v_i+1;

   --判断是否退出循环

   exit when v_i=11;

  endloop;

end;

 

--while

 

--输入用户名,向userinfo表中增长10条记录,编号从11-20

 

create procedure pro7(usname varchar2) is

v_i number(2):=11;

begin

 while v_i<=20 loop

   insert into userinfo values(v_i,usname);

   v_i:=v_i+1;

  endloop;

end;

 

--for

 

--输入用户名,向userinfo表中增长10条记录,编号从21-30

 

create or replace procedure pro8(usnamevarchar2) is

v_i number(2):=21;

begin

  forv_i in 21..30 loop

    insert into userinfo values(v_i,usname);

  endloop;

end;

 

----输入用户名,向userinfo表中增长10条记录,编号从40-31

 

create or replace procedure pro8(usnamevarchar2) is

v_i number(2):=31;

begin

  forv_i in reverse 31..40 loop

    insert into userinfo values(v_i,usname);

  endloop;

end;