首页 热点资讯 义务教育 高等教育 出国留学 考研考公
您的当前位置:首页正文

Oracle 命令

2023-05-23 来源:花图问答
Oracle 命令

Create identified //标识符Oracle用户管理:

创建一个用户:create user 用户名 identified by 密码(密码必须以字母开头) 给用户修给密码:password 用户名

修改用户密码:alter user 用户名 identified by 新密码 删除用户:drop user 用户名 [cascade]

授权用户登录dba:grant conn(connect) to 用户名

授予用户查询emp表权限:grant select on emp to 用户名 授予用户修改emp表权限:grant update on emp to 用户名 授予用户修改/删除/查修权限:grant all on emp to 用户名

收回用户对emp表的权限:revoke select/update on emp from 用户名

希望xiaoming用户可以把查询权限授予别的用户:grant select on scott.emp to xiaoming with grant option;(如果收回xiaoming对emp查询的权限,那么xiaoming授予用户也会受到诛连) 用户锁定:指定用户用户登录最多可以输入密码的次数。

例子:指定scott这个用户最多尝试3次登录,锁定时间为2天。 创建profile文件:

create profile lock_account limit failed_login_attempts 3 password_lock_time 2; alter user scott profile lock_account; 给用户解锁:

alter user 用户名 account unlock; 终止口令:

create profile myprofile limit password_life_time 10 password_grace_time 2; alter user 用户名 profile myprofile;

口令历史:如果希望用户在修改密码时不能用以前的密码。

create profile password_history limit password_life_time 10 password_grace_time 2 password_reuse_time 10 password_reuser_time;//指定口令可重用时间即10天后就可以重用。 删除profile:当不需要某个profile文件时,可是删除该文件。文件删除后,用这个文件去约束的那些用户通通也都被是放了。

drop profile password_history [casade]\\\\加了casade,就会把级联的相关东西也给删除掉。

password ['pɑ:swə:d]//密码 drop [drɔp]// 使终止 grant 授予 update account [ə'kaunt] 账户 limit ['limit] //限制 failed [feild] //失败 login [lɔg'in] 登陆 attempt [ə'tempt] //企图 grace [ɡreis] //恩惠 Oracle表的管理:

注意:表明和列明的规则 必须以字母开头,长度不超过30个字符,不能用oracle的保留字,只能使用如下字符A—Z,a-z,0-9,$,#等。

Oracle支持的数据类型

字符型:

char 定长 最大2000个字符

例子:char(10)‘小韩’ 前四个字符放 ‘小韩’,后添6个空个补全 如 ‘小韩 ’(横线表示空格)

varchar2(20) 分辨长度 最大4000个字符

alter ['ɔ:ltə] //修改 table 表 modify ['mɔdifai]//修改 column ['kɔləm] //列 insert 插入 values ['væljuz] 价值 session 会议 format ['fɔ:mæt]// 格式 into 到…里 例子:varchar2(10) ‘小韩’oracle分配四个字符。这样可以节省空间。

数字型:

number 范围 -10的38次方到10的38次方。可以表示证书,也可以表示小树。 number(5,2)\\\\表示一位小数有5位有效数,2位小数。范围-999.99-999.99

日期类型

date 包含年月日时分秒 oracle默认格式 1-1月-1999

创建表例子:

--学生表

create table student( ---表名 xh number(4), --学号 xm varchar2(20), --姓名 sex char(2), ----性别 birthday date, ---出生日期 sal number(7,2) ---奖学金 create table class (

classId NUMBER(2), cName VARCHAR2(40) );

修改表:

添加一个字段:ALTER TABLE student add (classId NUMBER(2));

修改一个字段的长度:ALTER TABLE student MODIFY (xm VARCHAR2(30)); //修改字段的类型/或是名字(不能有数据) 不建议做 ALTER TABLE student modify (xm CHAR(30));

删除一个字段 不建议做(删了之后,顺序就变了。加就没问题,因为加在后面) ALTER TABLE student DROP COLUMN sal; 修改表的名字: //很少有这种需求 RENAME student TO stu; 删除表:

DROP TABLE student;

添加数据:

INSERT INTO student VALUES (‘A001’,‘张三’,‘男’‘01-5月-05’,10);

oracle中默认的日期格式‘dd-mon-yy’dd天 mon月份 yy2位的年 ‘09-6月-99’1999年 6月9日

修改日期的默认格式(临时修改,数据库重启后仍未默认;如果修改需要改注册表) ALTER SESSION SET NLS_DATE_FORMAT=‘yyyy-mm-dd’; 修改后可以用我们熟悉的格式添加日期类型: INSERT INTO student VALUES (‘A002’,‘MIKE’,‘男’,‘1905-05-06’,10); 插入部分字段:

INSERT INTO student(xh,xm,sex) VALUES (‘A003’,‘JOHN’,‘女’);

rollback 'rəulbæk] point truncate ['trʌŋkeit]//截断的 grade [ɡreid]//等级 analyst ['ænəlist]分析者 distinct [dis'tiŋkt]//有区别的 插入空值:

INSERT INTO student(xh,xm,sex,birthday) VALUES(‘A004’,‘MARTIN’,‘男’,null);

如果要查询student表里birthday为null的记录,怎么写sql呢? select * from student where birthday is null;

如果要查询birthday不为null,位应该这样写: select * from student where birthday is not null; 修改数据:

修改一个字段:

UPDATE student SET sex=‘女’ WHERE xh=‘A001’; 修改多个字段:

UPDATE student SET sex=‘男’,birthday=‘1984-04-01’ WHERE xh=‘A001’; 修改含有null值的数据:

SELECT * FROM student WHERE birthday IS null; 删除数据:

DELETE FROM student;//删除所有记录,表结构还在,写日志,可以恢复的,速度呢慢。 Delete的数据可以恢复。 savepoint a;----创建保存点; DELETE FROM student;

rollback to a;---恢复到保存点。

一个有经验的DBA,在确保完成无误的情况下定期创建还原点。 DROP TABLE student;-----删除表的结构和数据; delete from student WHERE xh=‘A001’;----删除一条记录。

truncate TABLE student;----删除表中的所有记录,表结构还在,不写日志,无法找回删除的记录,速度快。

Oracle表查询(1):

Dept 部门表 Deptno 部门编号 Accounting 财务部 Research 研发部 Operations 业务部 Loc 部门所在地点 Salgrade 工资级别 Grade 级别 Losal 最低工资 Hisal 最高工资 emp 雇员表 clerk 普通员工 salesman 销售 manager 经理 analyst 分析师 president 总裁 mgr 上级的编号 Hiredate 入职时间 Sal 月工资 Comm 奖金 Deptno 部门 简单的查询语句: DESC emp; 查询所有列:

SELECT * FROM dept;//切记动不动就用select *因为查询所有的时间太长。 SET TIMING ON;打开显示操作时间的开关。 INSERT INTO users (userId,Username,userpassword) SELECT * FROM users;//从自己复制,加大数据量,用于测试。

SELECT COUNT(*) FROM users;//统计行数

查询指定列:SELECT enamel,sal,job,deptno FROM emp;

如何取消重复航DISTINCT:SELECT DISTINCT deptno,job FROM EMP;

查询SMITH所在部门,工资薪水?

SELECT deptno,job,sal FROM emp WHERE ename=‘SMITH’;

注意:oracle对内容的大小是区分的,所以ename=‘SMITH’和ename=‘smith’是不同的 使用算数表达式:nvl null

问题:如何显示每个雇员的年工资?

SELECT sal*13+nvl(comm,0)*13 “年薪”,ename,comm FROM emp; 使用列的别名:

SELECT ename “姓名”,sal*12 AS“年收入” FROM emp; 如何处理null值:使用nvl函数来处理。 如何连接字符串(||):SELECT ename || ‘is a’ || job FROM emp; 使用where子句:

问题:如何显示工资高于3000的员工? SELECT * FROM emp WHERE sal>3000; 问题:如何查找1982.1.1后入职的员工?

SELECT ename,hiredate FROM emp WHERE hiredate(雇用日期) >‘1--1 月-1982’; ......问题:如何显示工资在2000到3000的员工?

SELECT ename,sal FROM emp WHERE sal >=2000 AND sal <=3000; 如何使用like操作符:

%:表示0到多个字符 __:表示任意单个字符 问题:如何显示首字符为S的员工姓名和工资?

SELECT ename,sal FROM emp WHERE ename like ‘_0%’; 在where条件中使用in:

问题:如何显示empno为7844,7839,123,456的雇员情况?

SELECT * FROM emp WHERE empnp in (7844,7839,123,456); 使用is null的操作符,问题:如何显示没有上级的雇员的情况? SELECT * FROM emp WHERE mgr is null;

Oracle表查询(2):

使用逻辑操作符号,问题:查询工资高于500或者是岗位为MANAGER的雇员,同时还要满足他们的姓名首字母为大写的J?

SELECT * FROM emp WHERE (sal >500 or job =‘MANAGER’)and ename LIKE ‘J%’; 使用order by字句 默认asc,问题:如何按照工资的从低到高的顺序显示雇员的信息? SELECT * FROM emp ORDER by sal;

问题:按照部门号升序而雇员的工资降序排列。

SELECT * FROM emp ORDER by deptno,sal DESC; 使用列的别名排序:问题:按年薪排序。 select ename,(sal+nvl(comm,0))*12 \"年薪\" from emp order(命令) by “年薪” asc;//别名需要使用使用“”号圈中,英文不需要“”号。 分页查询: clear 清屏命令 oracle表复杂查询

说明:在实际应用中经常需要执行复杂的数据统计,经常需要显示多张表的数据,现在给大家介绍较为复杂的select语句。

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

问题:如何显示所有员工中最高工资和最低工资? SELECT MAX(sal),min(sal) FROM emp e; 最高工资那个人是谁?

select ename,sal from emp where sal=(select max(sal) from emp);

注意:select ename,max(sal)from emp;这语句执行的时候会报错,说ORA-00937;非单组分组函数。因为max是分组函数,而ename不是分组函数。但是select min(sal),max(sal) from emp;这句是可以执行的。因为min和max都是分组函数,就是说:如果列里面有一个分组函数,其他的都必须是分组函数,否则就出错。这是与法规定的。 查询最高工资员工的名字,工作岗位:

SELECT ename,jobsal FROM emp e where sal = (SELECT MAX(sal) FROM emp); 显示工资高于平均工资的员工信息:

SELECT * FROM emp e sal > (SELECT AVG(sal) FROM emp); group(团体) by 和having字句:

group by用于对查询的结果分组统计,having字句用于限制分组显示结果。 问题:如何显示么个部门的平均工资和最高工资?

SELECT AVG(sal),MAX(sal), deptno FROM emp GROUP by deptno;

注意:这里暗藏了一点,如果你要分组查询的话,分组的字段deptno一定要出现在查询的列表里面,否则会报错。因为分组的字段都不出现的话,就没办法分组了。 问题:显示每个部门的每种岗位的平均工资和最低工资?

SELECT min(sal),AVG(sal), deptno,job FROM emp GROUP by deptno,job; 问题:显示平均工资低于2000的部门号和它的平均工资?

SELECT AVG(sal), MAX(sal), deptno FROM emp GROUP by deptno having AVG(sal) < 2000; 对数据分组的总结:

1、分组函数只能出现在选择列表、having、order by子句中(不能出现在where中)

2、如果再select语句中同时包含有group by,having,order by那么他们的顺序是group by,having,order by。

3、在选择列中如果有列、表达式和分组函数,那么这些列和表达式必须有一个出现在group by子句中,否则就会出错。 多表查询:

多表查询是指基于两个以上的表或是视图查询。在实际应用,查询大哥表可能不能满足你的需求,(如显示sales部门位置和其他员工的姓名),在这种情况下需要使用到(dept表和emp表)

问题:显示顾远明,雇员工资及所在部门的工资【笛卡尔积】?

规定:多表查询的条件是 至少不能少于表的个数-1才能排除笛卡尔积。

SELECT e.ename,esal,d.dname FROM emp e,dept d WHERE e.deptno=d.deptno; 问题:显示部门号为10的部门名、员工名和工资?

SELECT d.dname, e.ename, e.sal FROM emp e, dept d WHERE e.deptno = d.deptno and e.deptno = 10;

问题显示各个员工的姓名,工资及工资的级别? 先看salgrade的表结构和记录: select * from salgrade;

SELECT e.ename, e.sal, s.grade FROM emp e, salgrade s WHERE e.sal BETWEEN s.losal AND s.hisal;

问题:显示雇员名,雇员工资及所在部门的名字,并按部门排序?

SELECT e.ename, e.sal, d.dname FROM emp e, dept d WHERE e.deptno = d.deptno ORDER by e.deptno;\\\\如果用group by,一定要把e.deptno放到查询列里面。 自连接:自连接是指在同一张表的连接查询。

问题:显示某个员工的上级领导的姓名?比如显示员工‘FORD的上级’。

SELECT worker.ename, boss.ename FROM emp worker, emp boss WHERE worker.mgr = boss.empno AND worker.ename = ‘FORD’;

子查询:什么是子查询。子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询。 当行子查询:当行子查询是指只返回一行数据的子查询语句,请思考:显示与SMITH同部门的所有员工? 思路:

1、查询出SMITH的部门号

select deptno from emp WHERE ename = ‘SMITH’; 2、显示

SELECT * FROM empWHERE deptno = (select deptno from emp WHERE ename = ‘SMITH’);//数据库在执行sql是从左到右扫描的,如果有括号的话,括号里面的先被优先执行。

多行子查询:多行子查询指返回多行数据的子查询。

请思考:如何查询和部门10的工作相同的雇员的名字、岗位、工资、部门号 SELECT DISTINCT job FROM emp WHERE deptno = 10;

SELECT * FROM emp WHERE job IN (SELECT DISTINCT job FROM emp WHERE deptno = 10);

在多行子查询中使用all操作符。

问题:如何显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号? SELECT ename, sal, deptno FROM emp WHERE sal > all (SELECT sal FROM emp WHERE deptno = 30);

大家想想还有没有别的查询方法。

SELECT ename,sal, deptno FROM emp WHERE sal > (SELECT MAX(sal)FROM emp WHERE deptno = 30);//执行效率上,函数高得多

在多行子查询中使用any操作符,问题:如何显示工资比部门30的任意一个员工的工资高的员工姓名、工资和部门号?

SELECT ename, sal,deptno FROM emp WHERE sal > ANY (SELECT sal FROM emp WHERE deptno = 30); 其他方法:

SELECT ename, sal, deptno FROM emp WHERE sal > (SELECT min(sal) FROM emp WHERE deptno = 30);

多列子查询:单行子查询是指子查询只返回单列、当行数据,多行子查询是指返回单列多行数据,都是针对单列而言的,而多列子查询是指查询返回多个列数据的子查询语句。 请思考如何查询与SMITH的部门和岗位完全相同的所有雇员。 SELECT deptno,job FROM emp WHERE ename = ‘SMITH’;

SELECT * FROM emp WHERE (deptno,job) = (SELECT deptno, job FROM emp WHERE ename = ‘SMITH’);

在from子句中使用子查询,请思考:如何显示高于自己部门平均工资的员工的信息。 思路:

1、查出各个部门的平均工资和部门号。

SELECT deptno, AVG(sal) mysal FROM emp GROUP by deptno; 2、把上面的查询结果看作是一张子表。

SELECT e.ename,e.deptno,e.sal,ds.mysal FROM emp e,(SELECT deptno,AVG(sal) mysal FROM emp GROUP by deptno) ds WHERE e.deptno = ds.deptno AND e.sal > ds.mysal; 如何衡量一个程序员水平?

网络处理能力,数据库,程序代码的优化程序的效率要很高。

总结:别名不能用as,如:SELECT e.ename, e.deptno, e.sal, ds.mysal FROM emp e,(SELECT deptno, AVG(sal) mysal FROM emp GROUP by deptno) as ds WHERE e.deptno = ds.deptno AND e.sal > ds.mysal;

在ds前不能加as,否则会报错 (给表取别名的时候,不能加as;但是给列别名,是可以加as的) 分页查询:

按雇员的id号升序取出。

oracle的分页一共有三种方式: 1、根据rowid来分

select * from t_xiaoxi where rowid in (select rid from (select rownum rn,rid from(select rowid rid, cid from t_xiaoxi order by cid desc)where rownum<10000)where rn>9980) order by cid desc;//执行时间0.03秒 2、按分析函数来分

select * from (select t.*,row_number() over(order by cid desc) rk from t_xiaoxi t) where rk<10000 and rk>9980;//执行时间1.01秒 3、按rownum来分

select * from (select t.*,rownum rn from(select * from t_xiaoxi order by cid desc)t where rownum<10000) where rn>9980;//执行时间0.1秒。

其中t_xiaoxi为表名称,cid为表的关键字段,取按cid降序排序后的第9981-9999条记录,t_xiaoxi表有70000多条记录。(见解:1最好,3次之,2最差。) 下面最主要介绍第三种:按rownum来分 1、rownum分页

SELECT * FROM emp; 2、显示rownum[oracle分配的]

SELECT e.*,ROWNUM rn FROM (SELECT * FROM emp) e;//rn相当于Oracle分配的行的ID号。

3、挑选出6--10条记录 先查出1--10条记录

SELECT e.*,ROWNUM rn FROM (SELECT * FROM emp) e WHERE ROWNUM <=10; 如果后面加上rownum >=6是不行的。 4、然后查出6---10条记录

SELECT * FROM (SELECT e.*,ROWNUM rn FROM (SELECT * FROM emp) e WHERE ROWNUM <=10) WHERE rn >=6; 5、几个查询变化

a、指定查询列,只需要修改最里层的子查询。只查询雇员的编号和工资

SELECT * FROM (SELECT e.*,ROWNUM rn FROM (SELECT ename,sal FROM emp) e WHERE ROWNUM <=10)WHERE rn >= 6;

b、排序查询,只需要修改最里层的子查询。工资排序后查询6---10条数据。

SELECT * FROM (SELECT e.*,ROWRUM (SELECT ename,sal FROM emp ORDER by sal) e WHERE ROWRUM <=10) WHERE rn >=6; 用查询结果创建新表:

这个命令是一种快捷的建表方式

CREATE TABLE mytable (id,name,sal,job,deptno) as SELECT empno,ename,sal,job,deptno FROM emp;//创建好之后,desc mytable;和select * from mytable;看看结果如何? 合并查询:有时在实际应用中,为了合并多个select语句的结果,可以使用集合操作符号union(['ju:niəu]联盟),union all,intersect( [,intə'sekt]相交),minus(['mainəs]减)多用于数据量比较大的数据库,运行速度快。

1、union:该操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中重复行。

SELECT ename,sal,job FROM emp WHERE sal > 2500 UNION SELECT ename,sal,job FROM emp WHERE job = ‘MANAGER’;

2、union all:该操作符与union相似,但是它不会取消重复航,而且不会排序。 SELECT ename,sal,job FROM emp WHERE sal > 2500 UNION ALL

SELECT ename,sal,job FROM emp WHERE job = ‘MANAGER’;

该操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中重复行。 3、intersect:使用该操作符用于取得两个结果集的交集。 SELECT ename,sal,job FROM emp WHERE sal > 2500 INTERSECT

SELECT ename,sal,job FROM emp WHERE job = ‘MANAGER’;

4、nimus:使用该操作符用于取得两个结果集的差集,她只会显示存在第一个集合中,而不存在第二个集合中的数据。

SELECT ename,sal job FROM emp WHERE sal > 2500 MINUS

SELECT ename,sal,job FROM emp WHERE job = ‘MANAGER’;//MINUS就是剑法的意思。

创建数据库有两种方法:

1、通过oracle提供的想到工具:database configuration Assistant 【数据库配置助手】 2、我们可以用手工步骤直接创建。

oracle中事务处理:

什么是事务:事务用于保证数据的一致性,她由一组相关的dml语句组成,改组的dml(数据操作语言,增删改,没有查询)语句要么全部成功,要么全部失败。 如:网上转账就是典型的要用事务来处理,用于保证书的一致性。 dml数据操作语言:银行转账、QQ申请、车票购买。

事务和锁:当执行事务操作时(dml语句),oracle会在被作用的表上枷锁,防止其他用户

修改表的结构。这里对我们的用户来讲是非常重要的。 ......其她进程排序,知道1号进程完成,锁打开,2号进程进入。依次进行,如果有进程级别较高的,可以插队。

提交事务:当执行用commit语句可以调教事务。当执行了commit语句之后,会确认事务

的变化、结束事务。删除保存点、释放锁,当使用commit语句结束事务之后,其他回话将可以查看到事务变化后的新数据。保存点就是为回退做的。保存点个数没有限制。

回退事务:在介绍回退事务前,我们先介绍一下保存点(savepoint)的概念和作用。保存点是事务中的一点。用于却小部分事务,当结束事务时,会自动的删除盖世五所定义的所有保存点。当执行rollback时,通过制定保存点可以回退到制定的点。 事务的及格重要操作:

1、设置保存点:savepoint a; 2、取消部分事务 rollback to a; 3、取消全部事务 rollback;

注意:这个回退事务,必须是没有commit前使用的;如果事务提交了,那么无论你刚才做了多少个保存点,都统统没有了。如果没有手动执行commit,而是exit了,那么会自动提交。

只读事务:只读事务是指只允许执行查询的操作,而不允许执行任何其他dml操作的事务,使用只读事务可以确保用户只能取得某时间点的数据。假定机票代售点每天18点开始统计今天的销售情况,这是可以使用只读事务。在设置了只读事务后,尽管其她会话可能会提交心的事务,到那时只读事务将不会取得最新的变化,从而可以保证取得特定时间点的数据信息。

设置只读事务:set transaction read only;

oracle的函数:

字符函数是oracle中最常用的函数,我们看看有哪些字符函数: lower(char):将字符串转化为小写的格式。 upper(char):将字符串转化为大写的格式。 length(char):返回字符串的长度。

substr(char,m,n):取字符串的子串。

replace(char1,search_string,replace_string):n代表取n个的意思,不是代表取到第n个 instr(char1,char2,[,n[,m] ]):取子串在字符串的位置。 问题:将所有员工的名字按小写的方式显示。 select lower(ename) from emp;

问题:将所有员工的名字按大写的方式显示。 select upper(ename) from emp;

问题:显示正好为5个字符的员工的姓名。 select * from emp where length(ename) = 5; 问题:显示所有员工的前三个字符。 select substr(ename,1,3)from emp;

问题:以首字母大写,后面小写的方式显示所有员工的姓名。

select upper(substr(ename,1,1)) || lower (substr(ename,2,length(ename)-1)) from emp; 问题:以首字母小写,后面大写的方式显示所有员工的姓名。

select lower(substr(ename,1,1)) || upper (substr(ename,2,length(ename)-1)) from emp; 问题:显示所有员工的姓名,用“我是老虎”替换所有“A”。 select replace(ename,‘A’,‘我是老虎’) from emp;

数学函数:数学函数的输入参数和返回值的数据类型都是数字类型的。数学函数包括cos,cosh,exp,ln,log,sin,sinh,sqrt,tan,tanh,acos,asin,atan,round,最常用的: round(n,[m])//该函数用于执行四舍五入,如果省掉m,四舍五入到整数,如果m是整数,

则四舍五入到小数点的m位后。如果m是负数,则四舍五入到小数点的m位前。

trunc(n,[m])//该函数用于截取数字。如果省掉m,就截去小数部分,如果m是正整数就截取到小数点的m位后,如果m是负数,则截取到小数点的前m位。 mod(m,n)

floor(n)//返回小于或是等于n的最大整数。 ceil(n)//返回大于或是等于n的最小整数。

对数字的处理,在财务系统或银行系统中用的最多,不同的处理方法,对财务报表有不同的结果。

问题:显示在一个月为30天的情况下,所有员工的日薪金,忽略余数。

select trunc(sal/30),ename from emp;或者 select floor(sal/30),ename from emp; 在做oracle测试的时候,可以使用dual表。 select mod(10,2) from dual;结果是0 select mod(10,3) from dual;结果是1

其他的数学函数,有兴趣的同学可以自己去看看: abs(n):返回数字n的绝对值。 select abs(-13) from dual; acos(n):返回数字的反余弦值 asin(n):返回数字的反正弦值 atan(n):返回数字的反正切值 cos(n);

exp(n):返回e的n次幂 log(m,n):返回对数值

power(m,n):返回m的n次幂

日期函数:日期函数用于处理date类型的数据。默认情况下日期格式是dd-mon-yy即12-7月-78

1、sysdate:该函数返回系统时间 2、add_months(d,n)

3、last_day(d):返回指定日期所在月份的最后一天 问题:查找已经入职8个月多得员工

select * from emp where sysdate >= add_months(hiredate,8); 问题:显示满10年服务年限的员工的姓名和受雇日期。

select ename,hiredate from emp where sysdate >=add_months (hiredate,12*10); 问题:对于每个员工,显示其加入公司的天数。 select floor(sysdate-hiredate) “入职天数”,ename from emp; 或者

select trunc (sysdate-hiredate) “入职天数”,ename from emp; 问题:找出各月倒数第3天受雇的所有员工。

select hiredate,ename from emp where last_day(hiredate)-2=hiredate;

转换函数:转换函数用于数据类型从一种专为另外一种。在某些情况下,oracle server允许值的数据类型和实际的不一样,这时oracle server会隐含的转化数据类型。 比如:

create table t1 (id int);

insert into t1 values(‘10’);//这样oracle会自动的将‘10’-->10 create table t2 (id varchar2(10));

insert into t2 values(1);//这样oracle就会自动的将1-->‘1’;

注意:尽管oracle可以进行隐含的数据类型的转换,但是它并不适应所有的情况,为了提高程序的可靠性,我们应该使用转换函数进行转换。

to_char:你可以使用select ename,hiredate,sal from emp where deptno = 10;显示信息,可是,在某些情况下,这个并不能满足你的需求。 问题:日期是否可以显示 时/分/秒 select ename,to_char (hiredate,‘yyyy-mm-dd hh24:mi:ss’) from emp; 问题:薪水是否可以显示指定的货币符号。 yy:两位数字的年份2004-->04 yyyy:四位数字的年份 2004年 mm:两位数字的月份8月-->08 dd:两位数字的天30号-->30 hh24:8点-->20 hh12:8点-->08

mi、ss-->显示分钟\\秒

9:显示数字,并忽略前面0。

0:显示数字,如位数不足,则用0补齐。 .(小数点):在指定位置显示小数点。 ,:在指定位置显示逗号。 $:在数字前加美元符号。

L:在数字前面加本地货币符号。 C:在数字前面加国际货币符号。 G:在指定位置显示组分隔符‘、’ D:在指定位置显示小数点符号‘.’

问题:显示薪水的时候,把本地货币单位加在前面。 select ename,to_char(hiredate,‘yyyy-mm-dd hh24:mi:ss’),to_char(sal,‘L99999.99’) from emp;

问题:显示1980年入职的所有员工。 select * from emp where to_char(hiredate,‘yyyy’)=1980; 问题:显示所有12月份入职的员工。 select * from emp where to_char(hiredate,‘mm’)=12;

to_date:函数to_date用于将字符串转换成dae类型的数据。 问题:能否按照中国人习惯的方式年-月-日添加日期。 系统函数:sys_context

1、terminal:当前会话客户所对应的终端的标示符。 2、language:语言。

3、db_name:当前数据库名称

4、nls_date_formal:当前会话客户所对应的日期格式。 5、session_user:当前会话客户所对应的数据库用户名

6、current(['kʌrənt]现在)_schema(['ski:mə]计划):当前会话客户所对应的默认方案名。 7、host:返回数据库所在主机的名称。

通过该函数,可以查询一些重要信息,比如你正在使用哪个数据库。 select sys_context(['kɔntekst]环境)(‘USERENV’,‘db_name’) from dual;

注意:USERENV是固定的,不能改的,db_name可以换成其她,比如select

sys_context(‘USERENV’,‘language’) from dual;又比如select sys_context(‘USERENV’,‘current_schema’) from dual;

数据库管理,表的逻辑备份与恢复

期望目标:

数据库管理员:每个oracle数据应该至少有一个数据库管理员(dba),对于一个小的数据库,一个dba就够了,但是对于一个大的数据库可能需要多个dba分担不同的管理职责。那么一个数据库管理员的主要工作是什么呢! 职责:

1、安装和升级oracle数据库。

2、建库、表空间、表、试图、索引等。 3、指定并实施备份和恢复计划。

4、数据库权限管理,调优,故障排除。

5、对于高级dba,要求参与项目开发,会编写sql语句、存储过程、触发器、规则、约束、包。

管理数据库的用户主要是sys和system(sys好像是董事长,system好像是总经理,董事长比总经理达,但是通常是总经理干事。) 这两个用户,区别主要是:

1、最重要的区别,存储的数据的重要性不同:sys:所有oracle的数据字典基表和视图都存放在sys用户中,这些基表和视图对于oracle的运行时至关重要的,有数据库自己维护,任何用户都不能手动更改。sys用户拥有dba,sysdba,sysoper角色或权限,是oracle权限最高的用户。system:用于存放次一级的内部数据,如oracle的一些特性或工具的管理信息。system用户拥有dba,sysdba角色或系统权限。 2、其次的区别,权限的不同:sys用户必须以as sysdba或as sysoper形式登陆,不能以normal方式登陆数据库。system用户正常登陆,她其实就是一个普通的dba用户,但是如果以as sysdba登陆,其结果实际上她是作为sys用户登陆的。(只要是sysoper拥有的权限,sysdba都有。sysdba可以创建数据库,sysoper不可以创建数据库)

dba权限的用户:dba用户是指具有dba角色的数据库用户,特权用户可以执行启动实例,关闭实例等特殊操作,而dba用户只有在启动数据库后才能执行各种管理工作。(相当于说dba连startup和shutdown这两个权限都没有)

管理初始化参数:管理初始化参数(调优的一个重要知识点,凭什么可以对数据库进行调优呢?是因为他可以对数据库的一些参数进行修改修正)初始化参数用于设置实例或是数据库的特称。oracle9i提供了200多个初始化参数,并且每个初始化参数都有默认值。 显示初始化参数: show parmeter

如何修改参数:需要说明的如果你希望修改这些初始化的参数,可以到文件D:\\oracle\\admin\\myoral\\pfile\\init.ora文件中去修改比如要修改实例的名字。

数据库(表)的逻辑备份与恢复:逻辑备份是指使用工具export将数据对象的结构和数据导出到文件的过程,逻辑恢复是指当数据库对象被误操作而损坏后使用工具import利用备份的文件把数据对象导入到数据库的过程。

物理备份即可在数据库open的状态下进行也可在关闭数据库后进行,但是逻辑备份和恢复只能在open的状态下进行。

导出:导出具体的分为:导出表,导出方案,导出数据库三种方式。导出使用exp命令来完成的,该命令常用的选项有:

userid:用于指定执行导出操作的用户名,口令,连接字符串。 tables:用于指定执行导出操作的表。 owner:用于指定执行导出操作的方案。 full=y:用于指定执行导出操作的数据库。 inctype:用于指定执行导出操作的数据库。

rows:用于指定执行导出操作是否要导出表中的数据。 file:用于指定导出文件名。 导出表:

1、导出自己的表

exp userid=scott/tiger@myoral tables=(emp,dept) file=d:\\e1.dmp; 2、导出其他方案的表

如果用户要导出其他方案的表,则需要dba的权限或是exp_full_database的权限,比如system就可以导出scott的表E:\\oracle\\ora92\\bin>exp userid=system/manager@myoral tables=(scott.emp) file=d:\\e2.emp(特别说明:在导入和导出的时候,要到oracle目录的bin目录下)

3、导出表的结构

exp userid=scott/tiger@accp tables=(emp) file=d:\\e3.dmp rows=n 4、使用直接导出方式

exp userid=scott/tiger@accp tables=(emp) file=d:\\e4.dmp direct=y

这种方式比默认的常规方式速度要快,当数据量大时,可是考虑使用这样的方法。这是需要数据库的字符集要与客户端字符集完全一致,否则会报错......

导出方案:导出方案是指使用export工具导出一个方案或是多个方案中的所有对象(表、索引、约束...)和数据。并存放到文件中。 1、导出自己的方案

exp userid=scott/tiger@myorcl owner=scott file=d:\\scott.dmp

2、导出其他方案:如果用户要导出其她方案,则需要dba的权限或是exp_full_database的权限,比如system用户就可以导出任何方案

exp userid=system/manager@myorcl full=y inctype=complete file=d:\\all.dmp

导入:导入就是使用工具import将文件中的对象和数据导入到数据库中,但是导入要使用的文件必须是export所导出的文件,与导出相似,导入也分为导入表,导入方案,导入数据库三种方式。 imp常用的选项有:

userid:用于指定执行导入操作的用户名,口令,连接字符串 tables:用于指定执行导入操作的表 formuser:用于指定源用户 file:用于指定导入文件名

full=y:用于指定执行导入整个文件

inctype:用于指定执行导入操作的增量类型 rows:指定是否要入表行(数据) ingore:如果表存在,则只导入数据 导入表

1、导入自己的表

imp userid=scott/tiger@myorcl tables=(emp) file=d:\\xx.dmp

2、导入表到其她用户,要求该用户具有dba的权限,或是imp_full_database

imp userid=system/tiger@myorcl tables=(emp) file=d:\\xx.dmp touser=scott 3、导入表的结构,只导入表的结构而不导入数据

imp userid=scott/tiger@myorcl tables=(emp) file=d:\\xx.dmp rows=n 4、导入数据,如果对象(如比表)已经存在可以只导入表的数据 imp userid=scott/tiger@myorcl tables=(emp) file=d:\\xx.dmp ignore=y

导入方案:导入方案是指使用import工具将文件中的对象和数据导入到一个或是多个方案中。如果要导入其他方案,要求该用户具有dba的权限,或是imp_full_database。 1、导入自身的方案

imp userid=scott/tiger file=d:\\xxx.dmp

2、导入其他方案,要求该用户具有dba的权限

imp userid=system/manager file=d:\\xxx.dmp fromuser=system touser=scott 在默认情况下,当导入数据库是,会导入对象结构和数据,案例如下: imp userid=system/manager full=y file=d:\\xxx.dmp

数据字典和动态性能视图:

数据字典是什么:数据字典是oracle数据库中最重要的组成部分,她提供了数据库的一些系统信息。动态性能视图记载了例程启动后的相关信息。

数据字典:数据字典记录了数据库的系统信息,她是只读表和视图的集合,数据字典的所有者为sys用户。用户只能在数据字典上执行查询操作(select语句),而其维护和修改是由系统自动完成的。这里我们谈谈数据字典的组成:数据字典包括字典基表和数据字典视图,其中基表存储数据库的基本信息,普通用户不能直接访问数据字典的基表。数据字典视图是基于数据字典基表所建立的视图,普通用户可以通过查询字典视图取得系统信息。数据字典视图主要包括user_xxx,all_xxx,dba_xxx三种类型。 user_tables

用于显示当前用户所拥有的所有表,它只返回用户所对应方案的所有表。 比如:select table_name from user_tables;

all_tables:用于显示当前用户可以访问的所有,她不仅返回当前用户方案的所有表,还返回当前可以访问的其他方案的表。

比如:select table_name from all_tables;

dba_tables:她会显示所有方案拥有的数据库表。但是查询这种数据库字典视图,要求用户必须是dba角色或是有select any table系统权限。例如:当用system用户查询数据字典视图dba_tables时,会返回system,sys,scott...方案所对应的数据库表。

用户名,权限角色:在建立用户是,oracle会把用户的信息存放到数据字典中,当给用户授予权限或是角色是,oracle会将权限和角色的信息存放到数据字典。 通过查询dba_users可以显示所有数据库用户的详细信息;

通过查询数据字典视图dba_sys_privs,可以显示用户所具有的系统权限; 通过查询数据字典视图dba_tab_privs,可以显示用户具有的对象权限; 通过查询数据字典dba_col_privs可以显示用户具有的列权限;

通过查询数据库字典视图dba_role_privs可以显示用户所具有的角色。 这里给大家介绍角色和权限的关系。

例如:要查看scott具有的角色,可查询dba_role_privs;

select * from dba_role(角色)_privs where grantee(被授与者)=‘scott’;

select * from system_privilege(['privilidʒ]特权)_map order by name;//查询oracle中所有的系统权限,一般是dba。

select distinct privilege from dba_tab_privs;//查询oracle中所有对象权限,一般是dba。 select * from dba_roles;//查询oracle中所有的角色,一般是dba。 select tablespace_name from dba_tablespaces;//查询数据库的表空间。 问题1:如何查询一个角色包括的权限? a.一个角色包含的系统权限

select * from dba_sys_privs where grantee=‘角色名’ 另外也可以这样查看:

select * from role_sys_privs where role=‘角色名’ b.一个角色包含的对象权限

select * from dba_tab_privs where grahtee=‘角色名’ 问题2:oracle究竟有多少种角色? select * from dba_roles;

问题3:如何查看某个用户,具有什么样的角色? select * from dba_role_privs where grantee=‘用户名’ 显示当前用户可以访问的所有数据字典视图。

select * from dict where comments(注释) like ‘%grant%’; 显示当前数据库的全称

select * from global(['ɡləubəl]总体的)_name;

其他说明:数据字典记录有oracle数据库的所有系统信息。通过查询数据字典可以取得以下系统信息。比如: 1、对象定义情况。 2、对象占用空间大小 3、列信息

4、约束信息...但是因为这些个信息,可以通过pl/sql developer工具查询得到。

动态性能视图:动态性能视图用于记录当前例程的活动信息,当启动oracle server时,系统会建立动态性能视图;当停止oracle server时,系统会删除动态性能视图。oracle的所有动态性能视图是以v_$考试的,并且oracle为每个动态性能视图都提供了相应的同义词,并且其同义词是v$开始的,例如v_$datafile的同义词为v$datefile;动态性能视图的所有者为sys,一般情况下,由dba或是特权用户来查询动态性能视图。

数据库管理——管理表空间和数据文件:

表空间是数据库的逻辑组成部分。从物理上讲,数据库数据存放在数据文件中;从逻辑上讲,数据库则是存放在表空间中,表空间由一个或多个数据文件组成。

说句库的逻辑结构:oracle中逻辑结构包括表空间、段、区和块。说明一下数据库由表空间构成,而表空间又是有段构成,而段又是由区构成,而区又是由oracle块构成的这样的一种结构,可以提高数据库的效率。 表空间:表空间用于从逻辑上组织数据库的数据。数据库逻辑上是由一个或多个表空间组成的。通过表空间可以达到以下作用: 1、控制数据库占用的磁盘空间

2、dba可以将不同数据类型部署道不同的位置,这样有利于i/o性能,同时利于备份和恢复等管理操作。

建立表空间:建立表空间是使用create tablespace命令完成的,需要注意的是,一般情况下,建立表空间是特权用户或是dba来执行的,如果其他用户来创建表空间,则用户必须要具有create tablespace的系统权限。

建立数据表空间:在建立数据库后,为便于管理表,最好建立自己的表空间。 create tablespace data01 datafile ‘d:\est\\data01.dbf’size 20m uniform 128k; 说明:执行完上述命令后,会建立名称为data01的表空间,并为该空间建立名称为data01.dbf的数据文件,区的大小为128k。 使用数据表空间

create table mypart(deptno number(4),dname varchar2(14),loc varchar2(13) tablespace data01; 改变表空间的状态:在建立表空间时,表空间处于练级的(online)状态,此时该表空间是可以访问的,并且该表空间是可以读写的,即可以查询该表空间的数据,而且还可以在表空间执行各种语句。但是在进行系统维护或是数据维护时,可能需要改变表空间的状态。一般情况下,由特权用户或是dba来操作。 1、使表空间脱机

alter tablespace 表空间名 offline; 2、使表空间联机

alter tablespace 表空间名 online;

3、只读表空间:当建立表空间是,表空间可以读写,如果不希望在该表空间上执行update,delete,insert操,那么可以将表空间修改为只读。 alter tablespace 表空间名 read only;(修改为可写是alter tablespace 表空间名 read write;) 改变表空间的状态:

我们给大家举一个实例,说明只读特性:

1、知道表空间名,显示该表空间包括的所有表

select * from all_tables where tablespace_name=‘表空间名’; 2、知道表名,查看那该表属于哪个表空间

select tablespace_name,table_name from user_tables where table_name=‘emp’;

通过2、我们可以知道scott.emp是在system这个表空间上,现在我们可以将system改为只读的但是我们不会成功,因为system是系统表空间,如果是普通表空间,那么我们就可以将其设为只读的,给大家做一个掩饰,可以加强理解。 3、使表空间可读写

alter tablespace 表空间名 read write;

删除表空间:一般情况下,由特权用户或是dba来操作,如果是其他用户操作,那么要求用户具有drop tablespace系统权限。

drop tablespace ‘表空间’ including([in'klu:diŋ]包含) contents and datafiles;

说明:including contents 表示删除表空间是,删除该空间的所有数据对象,而datafiles表示将数据库文件也删除。 扩展表空间:表空间是由数据文件组成的,表空间的大小实际上就是数据文件相加后的大小,那么我们可以想象,家丁表employee存放到data01表空间上,初始大小就是2M,当数据满2M空间后,如果在向employee表插入数据,这样就会显示空间不足的错误。 案例说明:

1、建立一个表空间sp01

2、在该表空间上建立一个普通表mydment,其结构和dept一样 3、向该表中加入数据insert into mydment select * from dept; 4、当一定时候就会出现无法扩展的问题,怎么办?

5、就扩展该表空间,为其增加更多的存储空间。有三种方法: (1)增加数据文件

alter tablespace sp01 add datafile‘d:\est\\sp01.dbf’size 20m;

(2)增加数据文件的大小

alter tablespace 表空间名 ‘d:\est\\sp01.dbf’resize 20m;//这里需要注意的是数据文件的大小不要超过500m

(3)设置文件的自动增长

alter tablespace 表空间名 ‘d:\est\\sp01.dbf’autoextend on next 10m maxsize 500m;

移动素具文件:有事,如果你的数据文件所在的磁盘损坏时,该数据文件将不能再使用,为了能够重新使用,需要将这些文件的副本移动到其她的其他,然后恢复。 下面以移动数据文件sp01.dbf为例来说明: 1、确定数据文件所在的表空间

select tablespace_name from dba_data_files where file_name=‘d:\est\\sp01.dbf’; 2、使表空间脱机,确保数据文件的一致性,将表空间转变为offline的状态。 alter tablespace sp01(表空间名) offline

3、使用命令移动数据文件到制定的目标位置 host move d:\est\\sp01.dbf c:\est\\sp01.dbf

4、执行alter tablespace命令,在物理上移动了数据后,还必须执行alter tablespace命令对数据库文件进行逻辑修改。

alter tablespace sp01 rename datafile ‘d:\est\\sp01.dbf’ to ‘c:\est\\sp01.dbf’;

5、使得表空间联机,在移动了数据文件后,为了使用户可以访问该表空间,必须将其转变为online状态。

alter tablespace sp01(表空间名) online; 显示表空间信息

查询数据字典视图dba_tablespace,显示表空间信息。 select tablespace_name from dba_tablespace;

显示表空间所包含的数据文件,查询数据字典视图dba_data_files,可显示表空间所包含的数据文件,如下:

select file_name,bytes from dba_data_files where tablespace_name=‘表空间’; 表空间小结:

1、了解表空间和数据文件的作用

2、掌握常用的表空间,undo表空间和临时表空间的简历方法

3、了解表空间的各个状态(online、offline、read write、read only)的作用,及如何改变表空间的状态的方法。 4、了解移动数据文件的原因,及使用alter tablespace和alter dataable命令移动数据文件的方法。

其他表空间:除了最常用的数据表空外,还有其她类型表空间。(了解,感兴趣的同学可以自己学学)

1、 索引表空间 2、 undo表空间 3、 临时表空间

4、 非标准块的表空间

约束:

期望目标:

1、 掌握维护oracle数据完整性的技巧 2、 理解索引概念,会建立索引

3、 管理oracle的权限和角色 维护数据的完整性

数据的完整性用于确保数据库数据遵从一定的商业和逻辑规则,在oracle中,数据完整性可以使用约束、触发器、应用程序(过程、函数)三种方法实现,在这三种方法中,因为约束易于维护,并且具有最好的性能,所以作为维护 完整性的首选。

约束:约束用于确保数据库数据满足特定的商业规则。在oracle中, 约束包括:not null、unique ([ju:'ni:k]独特的),、primary(主要的) key、foreign(外部) key和check五种。 使用:

Not null(非空):如果列上定义了not null,那么当插入数据时,必须为列提供数据。 Unique(唯一):当定义了唯一约束后,该列值是不能重复的,但是可以为null。

Primary key(主键):用于唯一的标示表行的数据,当定义主键约束后,该列不但不能重复而且不能为null。(需要说明的是:一张表最多只能有一个主键,但是可以有多个unique约束) Foreign key(外键):用于定义表和从表之间的关系。外键约束要定义在从表上,主表则ixu具有主键约束或是unique约束,当地应以外键约束后,要求外键列数据必须在主表的主键列存在或是为null。

Check:用于强制性数据必须满足的条件,假定在sal列上定义了check约束,并要求sal列值在1000-2000之间如果不在1000-2000之间就会提示出错。 例子:商店售货系统表设计

现有一个商店的数据库,记录客户及其购物情况,由下面三个表组成:商品goods(商品号goodsId,商品名goodName,单价unitprice,商品类型category,供应商provider);

客户customer(客户号customerId,姓名name,住在address,电邮email,性别sex,身份证cardId);

购买purchase(客户号customerId,商品号goodsId,购买数量nums); 请用SQL语言完成下列功能: 1、建表,在定义中要求声明: (1).每个表的主外键

(2).客户的姓名不能为控制;

(3).单价必须大于0,购买数量必须在1到30之间; (4).电邮不能够重复;

(5).客户的性别必须是男或者是女,默认是男;

Create table goods(goodsId char(8) primary key, -----主键 goodsName varchar2(30) unitprice number(10,2) check(unitprice>0), category varchar2(8), provider varchar2(30) );

Create table customer(customerId char(8) primary key,-----主键 name varchar2(50) not null,----不为空 address varchar2(50), email varchar2(50) unique, sex char(2) default ‘男’check(sex in (‘男’,‘女’)),------一个char能存半个汉字,两位char能存一个汉字 cardId char(18)

);

Create table purchase(customerId char(8) references customer(customerId), GoodsId char(8) references goods(goodsId), Nums number(10) check (nums between 1 and 30) );

表是默认建在SYSTEM表空间的 维护:

商店售货系统表设计案例(2)

如果在建表忘记建立必须的约束,则可以在建表后使用alter table 命令为表增加约束。但是要注意:增加not null约束时,需要使用modify选项,而增加其他四种约束使用add选线。 1、增加商品名也不能为空

Alter table goods modify goodsName not null; 2、增加身份证也不能重复

Alter table customer add constraint xxxxxx unique(cardId); 3、 增加客户的住址只能是‘海淀’,‘朝阳’,‘东城’,‘西城’,‘通州’,‘崇文’,‘昌平’; Alter table customer add constraint yyyyyy check(address in(‘海淀’,‘朝阳’,‘东城’,‘西城’,‘通州’,‘崇文’,‘昌平’));

删除约束:当不需要某个约束时,可以删除。 alter table 表名 drop constraint 约束名称;

特别说明一下:在删除主键约束的时候,可能有错误,比如:

alter table 表明 drop primary key;//这是因为如果在两张表存在主从关系,那么在删除主表的主键约束是,必须带上cascade选项,如像:alter table 表名 drop primary key cascade; 显示约束信息:

1、 显示约束信息:通过查询数据字典试图user_constraints,可以显示当前用户所有的约束的

信息。

Select constraint_name,constraint_type,status,validated from user_constraints where table_name=‘表明’;

2、显示约束列:通过查询数据字典视图user_cons_columns,可以显示约束所对应的表列信息。

select column_name,position from user_cons_columns where constraint_name=‘约束名’; 列级定义:列级定义实在定义列的同时定义约束。 如果在department表定义主键约束:

Create table department4(dept_id number(12) constraint pk_department primary key,name varchar2(12),loc varchar2(12));

表级定义:表级定义是指在定义了所有列侯,再定义约束。这里需要注意:

not null约束只能在列级上定义,以在建立employee2表时定义主键约束和外键约束为例: create table employee(emp_id number(4),name varchar2(15)), dept_id number(2),constraint pk_employee primary key (emp_id),

constraint fk_department foreigh key (dept_id) references department4(dept_id);

oracle索引、权限:

管理索引—原理介绍:索引是用于加速数据存取的数据对象。合理的使用所以可以大大降低i/o次数,从而提高数据访问性能。索引有很多种我们主要介绍常用的几种:

为什么添加了索引后,会加快查询速度呢? 创建索引:

单列索引:单列索引是基于单个列所建立的索引,比如: Create index 索引名 on 表名(列名);

复合索引:复合索引是基于两列或是多列的索引。在同一张表上可以有多个索引,但是要求列的组合不同,比如:

Create index emp_idx1 on emp (ename,,ob); Create index emp_idx1 on emp (job,ename); 使用原则:

1、 在大表上建立索引才有意义

2、 在where自居或是连接条件上经常引用的列上建立索引 3、 索引的乘此不要超过4层

这里能不能给学生演示这个效果呢? 如何构建一个大表呢? 索引的缺点:

索引有一些先天不足:

1、 建立索引,系统占用大约为表1.2倍的硬盘和内存空间来保存索引。

2、 更新数据的时候,系统必须要有额外的时间来同时对索引进行更新,以维持数据和索引

的一致性。 实践表明,不恰当的索引不但于事无补,反而会降低系统性能。因为大量的索引在进行插入、修改和删除时比没有索引话费更多的系统时间。 比如在如下字段建立索引应该是不恰当的: 1. 很少或从不引用的字段;

2. 逻辑性的字段,如男或女(是或否)等。

综上所述,提高查询效率是以消耗一定的系统资源为代价的,索引不能盲目的建立,这是考验一个DBA是否优秀的很重要的指标。 其他索引:

按照数据存储方式,可以分为B*数、反向索引、位图索引; 按照索引列的个数分类,可以分为单列索引、复合索引; 按照索引列值的唯一性,可以分为唯一索引和非唯一索引。 此外还有函数索引,全局索引,分区索引…

对于索引:在不同的情况,我们会在不同的列上建立索引,甚至建立不同种类的索引,请记住,技术是死的,人是活的。比如B*树索引建立在重复值很少的列上,而位图索引则建立在重复值很多、不同值相对固定的列上。

显示索引信息:在同一张 可以有多个索引,通过查询数据字典试图dba_indexs和user_indexs,可以显示索引信息。其中dba_indexs用于显示数据库所有的索引信息,而user_index用于显示当前用户的索引信息:

Select index_name,index_type from user_indexes where table_name=‘表名’;

显示索引列:通过查询数据字典试图user_ind_columns,可以显示索引对应的列的信息。 Select table_name,column_name from user_ind_columns where index_name = ‘IND_ENAME’; 管理权限和角色

这一部分我们主要看看oracle中如何管理权限和角色,权限和角色的区别在哪里?

当刚刚建立用户时,用户没有任何权限,也不能执行任何操作。如果要执行某种特定的数据

库操作,则必须为其授予系统的权限;如果用户要访问其她方案的对象,则必须为其授予对象的权限。为了简化权限的管理,可以使用角色。

权限:权限是指执行特定类型sql命令或是访问其她方案对象的权利,包括系统权限和对象权限两种。

系统权限:系统权限是指执行特定类型sql命令的权利。她用于控制用户可以执行的一个或是一组数据库操作。比如用户具有create table 权限是,可以在其他方案中间表,当用户具有create any table权限时,可以在任何方案中建表。Oracle提供了100多种系统权限。 常用的有:

Create session 连接数据库 create table 建表

Create view 建视图 create public synonym 建同义词 Create procedure 建过程、函数、包 create trigger 建触发器 Create cluster 建簇

显示系统权限:oracle提供了100多种系统权限,而且oracle的版本越高,提供的系统权限就越多,我们可以查询数据字典试图。

System_privilege_map:可以显示所有系统权限 Select * from system_privilege_map order by name; 授予系统权限:一般情况,授予系统权限是由dba完成的,如果用其他用户来授予系统权限,则要求该用户必须具有grant any privilege的系统权限。在授予系统权限是,可以带有with admin option选线,这样,被授予权限的用户或是角色还可以将该系统权限授予其她的用户或是角色。举例:

1、 创建两个用户ken,tom。初始阶段他们没有任何权限,如果登录就会给出错误的信息。 Create user ken identified by ken; 2、 给用户ken授权

1). Grant create session,create table to ken with admin option; 2). Grant create view to ken;

3、给用户tom授权,我们可以通过ken给tom授权,因为with admin option是加上的。当然也可以通过dba给tom授权,我们就用ken给tom授权: (1).grant create session,create table to tom; (2).grant create view to ken; ---ok吗?不ok

回收系统权限:一般情况下,回收系统权限是dba来完成的,如果其她的用户来回收系统权限,要求该用户必须具有相应的系统权限及转授系统权限的选项(with admin option)。回收系统权限使用revoke来完成。当回收了系统权限后,用户就不能执行相应的操作了,但是请注意,系统权限级联收回的问题?[不是级联回收!] System---------ken------------tom

(create session) (create session) (create session) 用system执行如下操作:

Revoke create session from ken;-----请思考tom还能登陆吗? 答案:能,可以登录

对象权限:只访问其她方案对象的权利,用户可以直接访问自己方案的对象,但是如果要访问别的方案的对象,则必须具有对象的权限。比如smith用户要访问scott.emp表(scott:方案,emp:表) 常用的有:

Alter 修改delete 删除 select 查询 insert 添加

Update 修改 index 索引 references 引用 execute 执行

显示对象权限:通过数据字段试图可以显示用户或是角色所具有的对象权限。试图为dba_tab_privs。

Conn system/manager;

Select distinct privilege from dba_tab_privs;

Select grantor,owner,table_name,privilege from dba_tab_privs where grantee=‘BLAKE’; 1、 授予对象权限:在oracle9i前,授予对象权限是由对象的所有者来完成的,如果用其她

的也难怪乎来操作,则需要用户具有相应的(with grant option) 权限,从oracle9i开始,dba用户(sys,system)可以将任何对象上的对象权限授予其他用户。授予对象权限是用grant命令来完成的。对象权限可以授予用户,角色,和public。在授予权限时,如果带有with grant option选项,则可以将该权限转授给其她用户。但是要注意with grant option选项不能被授予角色。

1. Monkey用户要操作scott.emp表,则必须授予相应的对象权限 1).希望monkey可以查询scott.emp表的数据,怎样操作? Grant select on emp to monkey;

2).希望monkey可以修改scott.emp的表数据,怎样操作? Grant update on emp to monkey;

3) .希望monkey可以删除scott.emp的表数据,怎样操作? Grant all on emp to monkey;

4).有没有更加简单的方法,一次把所有权限赋给monkey? Grant all on emp to monkey;

2、 能否对monkey访问权限更加精细控制。(授予列权限)

1).希望monkey只可以修改scott.emp的表的sal字段,怎样操作? Grant update on emp(sal) to monkey

2).希望monkey 只可以查询scott.emp的表的ename,sal数据,怎样操作? Grant select on emp(ename,sal) to monkey

3、 授予alter权限,如果black用户要修改scott.emp表的结构,则必须授予alter对象权限 Conn scott/tiger

Grant alter on emp to blake;//当然也可以用system,sys来完成这件事。

4、 授予execute权限,入股用户想要执行其她方案的包/过程/函数,则须有execute权限。 比如为了让ken可以执行包dbms_transaction,可以授予execute权限。 Conn system/manager;

Grant execute on dbms_transaction to ken;

5授予index权限,如果想在别的方案的表上建立索引,则必须具有index对象权限。如果为了让black可以在scott.emp表上建立索引,就给其index的对象权限。 Conn scott/tiger;

6、Grant index on scott.emp to black;

使用with grant option 选项该选项用于转授对象权限。但是该选项只能被授予用户,而不能授予角色

Conn scott/tiger;

Grant select on emp to black with grant option; Conn black/密码;

Grant select on scott.emp to jones;

回收对象权限:在oracle9i中,回收对象的权限可以由对象的所有者来完成,也可以用dba用户(sys,system)来完成。这里说明的是:回收对象权限后,用户就不能执行相应的sql命

令,但是要注意的是对象的权限是否会被级联回收?[级联回收] 如:scott--------------blake-----------jones

Select on emp select on emp select on emp Conn scott/tiger@accp

Revoke select on emp from black

请大家思考,jones能否查询scott.emp表数据。 答案:不能(和系统权限不一样,刚好相反)

角色:

角色就是相关权限的命令集合,使用角色的主要目的就是为了简化权限的管理,假定有用户a,b,c为了让他们都拥有权限 1、 连接数据库

2、 在scott.emp表上select,insert,update。如果采用直接授权操作,所以比较麻烦!怎么

办?

如果我们采用角色就可以简化,首先将create session,select on scott.emp,insert on scott.emp,update on scott.emp授予角色,然后将该角色授予a,b,c用户,这样就可以三次授予搞定。

角色分为预定义和自定义角色两类: 预定义角色:预定义角色是指oracle所提供的角色,每种角色都用于执行一些特定的管理任务,下面我们介绍常用的预定义角色connect,resource,dba 1、 connect角色

connect角色具有一般应用开发人员需要的大部分权限当建立了一个用户后,多数情况下,只要给用户授予connect和resource角色就够了,那么connect角色具有哪些系统权限呢?

Alter session Create cluster

Create database link Create session Create table Create view Create sequence

2、resource角色,resource角色具有应用开发人员所需要的其她权限,比如建立存储过程,触发器等。这里需要注意的是resource角色隐含了unlimited tablespace系统权限。 Resource角色包含以下系统权限: Create cluster Create indextype Create table Create sequence Create type

Create procedure Create trigger

3、 dba角色:dba角色具有所有的系统权限,及with admin option选项,默认的dba用户为

sys和system,她们可以将任何系统权限授予其她用户。但是要注意的是dba角色不具备sysdba和sysoper的特权(启动和关闭数据库)。

自定义角色:顾名思义就是自己定义的角色,根据自己的需要来定义。一般是dba来建立,如果永别的用户来建立,则需要具有create role的系统权限。在建立角色是可以指定验证方式(不验证,数据库验证等。) 1. 建立角色(不验证)

如果角色是公用的角色,可以采用不验证的方式建立角色。 Create role 角色名 not identified; 2、 建立角色(数据库验证)

采用这样的方式时,角色名、口令存放在数据库中。当激活该角色时,必须提供口令。在建立这种角色时,需要为其提供口令。 Create role 角色名 identified by 密码;

角色授权:当建立角色时,角色没有任何权限,为了使得角色完成特定任务,必须为其授予相应的系统权限和对象权限。 1、给角色授权:给角色授予权限和用户授权没有太多区别,但是要注意,系统权限的unlimited tablespace和对象权限的with grant option选项是不能授予角色的。 conn system/manager;

grant create session to 角色名 with admin option conn scott/tiger@myoral;

grant select on scott.emp to 角色名;

grant insert,update,delete on scott.emp to 角色名;//通过上面的步骤,就给角色授权了。 2、分配角色给某个用户:一般分配角色是由dba来完成的,如果要以其她用户身份分配角色,则要求用户 必须具有grant any role的系统权限。 conn system/manager;

grant 角色名 to black with admin option;

因为我给了with admin option选项所以,black可以把system分配给她的角色分配给别的用户。

删除角色:使用drop role,一般是dba来执行,如果其她用户则要求改用户具有 drop any role 系统权限。

conn system/manager; drop role 角色名;

问题:如果角色被删除,那么被授予角色的用户是否还具有之前角色里的权限? 答案:不具有了。 显示角色信息 1、显示所有角色

select * from dba_roles;

2、显示角色具有的系统权限

select privilege,admin_option from role_sys_privs where role=‘角色名’;

3、显示角色具有的对象权限:通过查询数据字典视图dba_tab_privs可以查看角色具有的对象权限或是列的权限。

4、显示用户具有的角色,及默认角色:当以用户的身份连接到数据库时,oracle会自动的激活默认的角色,通过查询数据字典视图dba_role_privs可以显示某个用户具有的所有角色及当前默认的角色。

select granted_role,default_role from dba_role_privs where grantee=‘用户名’;

精细访问控制:精细访问控制是指用户可以使用函数,策略实现更加细微的安全访问控制。如果使用精细访问控制,则当在客户端发出sql语句(select,insert,update,delete)时,oracle

会自动在sql语句后追加谓词(where子句),并执行新的sql语句,通过这样的控制,可是不同的数据库用户在访问相同表时,返回不同的数据信息。

pl/sql快的结构和实例:

期望目标:

1、理解oracle的pl/sql概念

2、掌握pl/sql编程技术(包括编写过程、函数、触发器......) pl/sql(procedural language/sql)是oracle在标准的sql语言上的扩展。pl/sql不仅允许嵌入sql语言,还可以定义变量和常量,允许使用条件语句和循环语句,允许使用例外处理各种错误,这样使得她的功能变得更加强大。 为什么学pl/sql,学习必要性。 1、提高应用程序的运行性能

2、模块化的设计思想[分页的过程,订单的过程,转账的过程...] 3、减少网络传输量

4、提高安全性(sql会包括表名,有时还可能有密码,传输的时候会谢落。pl/sql就不会) pl/sql缺点:移植性不好(换数据库就用不了了) 用什么编写pl/sql

sqlplus开发工具:sqlplus是oracle公司提供的一个工具。 举一个简单的案例额:

编写一个存储过程,该过程可以向某表中添加记录。 1、创建一个简单的表

create table mytest(name varchar2(30),passwd varchar2(30)); 2、创建过程

create or replace procedure sp_prol is begin -----执行过程

insert into mytest values(‘小明’,‘m1234’); end; /

replace:表示如果有sp_prol,就替换 如何查看错误信息:show error; 如何调用该过程:

1)exec过程名(参数值1,参数值2...); 2)call过程名(参数值1,参数值2....); pl/sql developer开发工具:pl/sql developer是用于开发pl/sql块的集成开发环境(ide),她是一个独立的产品,而不是oracle的一个附带品。 举一个简单案例:

编写一个存储过程,该过程可以删除某表记录。 create or replace procedure sp_pro2 is begin ----执行部分

delete from mytest where name=‘小明’; end;

pl/sql基础:

pl/sql介绍:开发人员使用pl/sql编写应用模块时,不仅需要掌握sql语句的编写方法,

还要掌握pl/sql语句及语法规则。pl/sql编程可以使用变量和逻辑控制语句,从而可以编写非常有用的功能模块。比如:分页存储过程模块、订单存储过程模块、转账存储过程模块。而且如果使用pl/sql编程,我们可以轻松地完成非常复杂的查询要求。

pl/sql可以做什么

简单分类 |------过程(存储过程) | |-------函数 块(编程)-------------| |------触发器 | |------包 编写规范: 1、注释

单行注释 ——

select * from emp where empno=7788;——取得员工信息 多行注释/*...*/来划分 2、标志符号的命名规范

1).当定义变量时,建议用v_作为前缀v_sal 2).当定义变量时,建议用c_作为前缀c_rate

3).当定义游标时,建议用_cursor作为后缀emp_cursor 4).当定义例外是,建议用e_作为前缀e_error

pl/sql块介绍

块(block)是pl/sql的基本程序单元,编写pl/sql程序实际上就是编写pl/sql块,要完成相对简单的应用功能,可能只需要编写一个pl/sql块,但是如果想要实现复杂的功能,可能需要在一个pl/sql块中嵌套其他的pl/sql块。

pl/sql块有三个部分构成:定义部分,执行部分,例外处理部分。 如下所示: declare

/*定义部分——定义常量、变量、游标、复杂数据类型*/ exception

/*例外处理部分——处理运行的各种错误*/ end;

定义部分是从declare开始的,该部分是可选的; 执行部分是从begin开始的,该部分是必须的;

例外处理部分是从exception开始的,该部分是可选的。 可以和java编程结构做一个简单的比较。 pl/sql块的实例(1)

实例1——指包括执行部分的pl/sql块 set serveroutput on---打开输出选项 begin

dbms_output.put_line(‘hello’); end;

相关说明:dbms_output是oracle所提供的包(类似java的开发包),该包包含一些过程,put_line就是dbms_output包的一个过程。 pl/sql块的实例(2)

实例2——包含定义部分和执行部分的pl/sql块 declare

v_ename varchar2(5);----定义字符串变量 begin

select ename into v_ename from emp where empno=&aa; dbms_output.put_line(‘雇员名:’|| v_ename); end; /

如果要把薪水也显示出来,那么执行部分就应该这么写:

select ename,sal into v_ename,v_sal from emp where empno=&aa; 相关说明:&表示要接受从控制台输入的变量。 pl/sql块的实例(3)

实例3——包含定义部分,执行部分和例外处理部分

为了避免pl/sql程序的运行错误,提高pl/sql的健壮性,应该对可能错的错误进行处理,这个很有必要。

1、比如在实例2中,如果说人了不存的雇员名,应当做例外处理。 2、有时出现异常,希望用另外的逻辑处理。 相关说明:

oracle事先预定义了一些例外,no_data_found就是找不到数据的例外。 declare

-----定义变量

v_ename varchar2(5); v_sal number(7,2); begin

---执行部分

select ename,sal into v_ename,v_sal from emp where empno=&aa; ---在控制台显示用户名

dbms_output.put_line(‘用户名是:’|| v_ename || ‘工资:’ || v_sal); --异常处理 exception

when no_data_found then

dbms_output.put_line(‘朋友,你的编号输入有误!’); end; /

pl/sql分类——过程、函数、包、触发器:

过程:过程对于执行特定的操作,当建立过程时,既可以指定输入参数(in),也可以指定输出参数(out),通过在过程中使用输入参数,可以将数据传递到执行部分;通过使用输出参数,可以将执行部分的数据传递到应用环境。在sqlplus中可以使用create procedure命令来建立过程。 实例如下:

1、请考虑编写一个过程,可以输入雇员名,新工资,可修改雇员的工资 2、如何调用过程两种方法:exec call 3、如何在java程序中调用一个存储过程 问题:如何使用过程返回值?

create procedure sp_pro3(spName varchar2,newSal number) is

——不要写成number(3,2),表名类型就可以了,不需要大小。就好像java写方法时的参数一样。 begin

——执行部分,根据用户名去修改工资 update emp set=newSal where ename=spName; end; /

函数:函数用于返回特定的数据,当建立函数是,在函数头部必须包含return子句。而在函数体内必须包含return语句返回的数据。我们可以使用create function来建立函数,实际案例:

——输入雇员的姓名,返回该雇员的年薪 create function annual_incomec(name varchar2) return number is

annual_salazy number(7,2); begin ——执行部分 select sal*12+nvl(comm,0) into annual_salazy form emp where ename=name; return annual_salazy; end; /

如果函数创建过程有编译错误,可以使用show error;命令显示错误 在sqlplus中调用函数 var income number; call annual_incomec(‘scott’)into:income; print income

包:包用于在逻辑上组合过程和函数,她由包来规范包体两部分组成。 1、我们可以使用create package命令来创建包。 实例:

——创建一个包sp_package

——声明该报有一个过程update_sal ——声明该报有一个函数annual_income create package sp_package is

procedure update_sal (name varchar2,newsal number); function annual_income (name varchar2) return number; end;

包的规范只包含了过程和函数的说明,但是没有过程和函数的实现代码。包体用于实现包规范中的过程和函数。

2、建立包体可以使用create package body命令 ——给包sp_package实现包体

create or repalce package body sp_package is

procedure update_sal (name varchar2,newsal number) is

begin

update emp set sal=newsal where ename=name; end;

function annual_income(name varchar2) return number is annual_salary number; begin

select sal * 12 + nvl(comm,0) into annual_salary from emp where ename = name; return annual_salary; end; /

3、如何调用包的过程或是函数:当调用包的过程或是函数时,在过程和函数前需要带有包名,如果要访问其他方案的包,还需要在包名前加方案名。 如:

call sp_package.update_sal(‘SCOTT’,1500);

触发器:触发器是指隐含的执行的存储过程。当定义触发器时,必须要指定触发的事件和触发的操作,常用的触发事件包括insert,update,delete语句,而触发操作实际就是一个pl/sql块。可以使用create trigger来建立触发器。

定义并使用变量,复合类型:

定义并使用变量:

在编写pl/sql程序时,可以定义变量和常量;在pl/sql程序中包括有: 1、标量类型(scalar) 2、复合类型(composite) 3、参照类型(reference) 4、lob(large object)

标量(scalar)——常用类型

在编写pl/sql块是,如果要使用变量,需在定义部分定义变量。pl/sql中定义变量和常量的语法如下:

identifier [constant] datatype [not null] [:=| default expr] identifier:名称

constant:指定常量。需要指定她的初始值,且其值是不能改变的 datatype:数据类型

not null:指定变量不能为null :=给变量或是常量指定初始值 default 用于指定初始值

expr:指定初始值的pl/sql表达式,可是文本值、其他变量、函数等。 标量定义的案例:

1、定义一个边长字符串 v_ename varchar2(20)

2、定义一个小数,范围-9999.99~9999.99

v_sal number(6,2)

3、定义一个小数并给一个初始值为5.4:=是pl/sql的赋值号 v_sal2 number(6,2):=5.4; 4、定义一个日期类型的数据 v_hiredate date;

5、定义一个布尔变量,不能为空,初始值为false v_valid boolean not null default false; 标量(scalar)——使用标量

在定义好变量后,就可以使用这些变量。这里需要说明的是pl/sql块为变量赋值不同于其她的编程语言,需要在等号前面加冒号(:=) declare

c_tax_rate_number(3,2):=0.03; ——用户名

v_ename varchar2(5); v_sal number(7,2); v_tax_sal number(7,2); begin ——执行

select ename,sal into v_ename,v_sal from emp where empno=&no; ——计算所得税

v_tax_sal:=v_sal*c_tax_rate; ——输出

dbms_output.put_line(‘姓名是:’||v_ename||‘工资’|| v_sal ||‘交税:’ v_tax_sal); end; /

标量(scalar)——使用%type类型 对于上面的pl/sql块有一个问题:

就是如果员工的姓名超过了5个字符的话,就会有错误,为了降低pl/sql程序需的维护工作量,可以使用%type属性定义变量,这样她会按照数据库列来确定你定义的变量的类型和长度。

我们看看这个怎么使用: 标识符名 表名.列明%type;

如上例的v_ename,这样定义:v_ename emp.ename%type; 复合变量(composite)——介绍

用于存放多个值的变量。主要包括这几种: 1、pl/sql记录 2、pl/sql表 3、嵌套表 4、varray

复合类型——pl/sql记录

类似于高级语言中的结构体,需要注意的是,当引用pl/sql记录成员时,必须要加记录变量作为前缀(记录变量.记录成员)如下: declare

——定义一个pl/sql记录类型emp_record_type,类型包含3个数据name,salary,title。说

白了,就是一个类型可以存放3个数据,主要是为了好管理 type emp_record_type is record( name emp.ename%type salary emp.sal%type title emo.job%type);

——定义了一个sp_record变量,这个变量的类型是emp_record_type sp_record emp_record_type; begin

select ename,sal,job into sp_record from emp where empno = 7788; dbms_output.put_line (‘员工名:’|| sp_record.name); end;

复合类型——pl/sql表:相当于高级语言中的数组,但是需要注意的是在高级语言中数据的下标不能为负数,而pl/sql是可以为负数的,并且表元素的下表没有限制。实例如下: declare

——定义了一个pl/sql表类型sp_table_type,该类型是用于存放emp.ename%type ——index by binary_integer 表示下标是整数 type sp_table_type is table of emp.ename%type index by binary_integer;

——定义一个pl_table变量,这个变量的类型是sp_table_type sp_table sp_table_type; begin

select ename into sp_table(-1)from emp where empno = 7788; dbms_output.put_line(‘员工号:’ || sp_table(-1)); end; 说明:

sp_table_type是pl/sql表类型

emp.ename%type指定了表的元素的类型和长度 sp_table为pl/sql表变量 sp_table为pl/sql表变量

sp_table(0)则表示下标为0的元素

注意:如果把select ename into sp_table(-1) from emp where empno =7788;变成select ename into sp_table(-1) from emp;则运行时会出现错误,错误如下:

ORA-01422:实际返回的行数超出请求的行数//解决方法是:使用参照变量。 复合变量——嵌套表(nested table) 复合变量——边长数据(varray)

参照变量:参照变量是指用于存放数据指针的变量。通过使用参照变量,可以使得应用程序共享相同对象,从而降低占用的空间。在编写pl/sql程序时,可以使用游标变量(ref cursor)和对象类型变量(ref obj_type)两种参照变量类型。 参照变量——ref cursor游标变量

使用游标时,当定义游标时不需要指定相应的select语句,但是当使用游标时(open时)需要指定select语句,这样一个游标就与一个select语句结合了。示例如下:

1、请使用pl/sql编写一个快,可以输入部门号,并显示该部门所有员工姓名和他的工资。 2、在1的基础上,如果某个员工的工资低于200元,就添加100元。 1.

declare

——定义游标sp_emp_cursor

type sp_emp_cursor is ref cursor; ——定义一个游标变量

test_cursor sp_emp_cursor; ——定义变量

v_ename emp.ename%type; v_sal emp.sal%type; begin ——执行

——把test_cursor和一个select结合

open test_cursor for select ename,sal from emp where deptno=&no; ——循环取出 loop

fetch test_cursor into v_ename,v_sal; ——判断是否test_cursor为空

exit when test_cursor%notfound; dbms_output.put_line(‘名字:’|| v_ename ||‘工资:’|| v_sal); end loop; end; /

pl/sql的进阶——控制结构(分支,循环,控制):

在任何计算机语言(c,java,pascal)都有各种控制语句(条件语句,循环结构,顺序控制结构....)在pl/sql中也存在这样的控制结构。 在本部分学习完成后,希望大家达到: 1、使用各种if语句 2、使用循环语句

3、使用控制语句——goto和null; 条件分支语句

pl/sql中提供了三种条件分支语句if--then,if - then - else,if - then - elsif -then 简单的条件判断if - then

问题编写一个工程,可以输入一个雇员名,如果该雇员的工资低于2000,就给员工工资增加10%。

create or replace procedure sp_pro6(spName varchar2) is ——定义

v_sal emp.sal%type; begin

——执行

select sal into v_sal from emp where ename=spName; ——判断

if v_sal<2000 then

update emp set sal=sal+sal*10% where ename=spName; end if;

end; /

二重条件分支if - then - else

问题:编写一个过程,可以输入一个雇员名,如果该雇员的补助不是0就在原来的基础上增加100:如果补助为0就把补助设为200;

create or replace procedure sp_pro6(spName varchar2) is ——定义

v_comm emp.comm%type; begin

——执行

select comm into v_comm from emp where ename=spName; ——判断

if v_comm<>0 then

update emp set comm=comm+100 where ename=spName; else

update emp set comm=comm+200 where ename=spName; end if; end; /

多重条件分支if - then - elsif - then

问题:编写一个过程,可以输入一个雇员编号,如果该雇员的职位是PRESIDENT就给他的工资增加1000,如果该雇员的职位是MANAGER就给他的工资增加500,其他职位的雇员工资增加200。

create or replace procedure sp_pro6(spNo number) is ——定义

v_job emp.job%type; begin

——执行

select job into v_job from emp where empno=spNo; if v_job=‘PRESIDENT’then

update emp set sal=sal+1000 where empno=spNo; elsif v_job=‘MANAGER’then

update emp set sal=sal+500 where empno=spNo; else

update emp set sal=sal+200 where empno=spNo; end if; end; /

循环语句——loop

是pl/sql中最简单的循环语句,这种循环语句以loop开头,以end loop结尾,这种循环至少会被执行一次。

案例:现有一张表users,表结构如下: 用户id | 用户名 |

轻便鞋一个过程,可以输入用户名,并循环添加10个用户到users表中,用户编号从1开始增加。

create or replace procedure sp_pro6(spName varchar2)is ——定义 :=表示赋值 v_num number:=1; begin loop

insert into users values(v_num,spName); ——判断是否要退出循环 exit when v_num=10; end loop; end; /

环语句——while循环

基本循环至少要执行循环一次,而对于while循环来说,只要条件为true时,才会执行循环语句,while循环以while...loop开始以end loop结束。 案例:现有一张表users,表结构如下: 用户 id 用户名

问题:请编写一个过程,可以输入用户名,并循环添加10个用户到users表中,用户编号从11开始增加。

create or repalce procedure sp_pro6(spName varchar2) is ——定义 :=表示赋值 v_num number:=11; begin

while v_num<=20 loop ——执行

insert into users values(v_num,spName); v_num:=v_num+1; end loop; end; /

循环语句 - for循环

基本for循环的基本结构如下: begin

for i in reverse 1..10 loop

insert into users values (i,‘xiaoming’); end loop; end;

我们可以看到控制变量i,在隐含中就在不停地增加。 顺序控制语句——goto,null

1、goto语句:goto语句用于跳转到特定符号去执行语句。注意由于使用goto语句会增加程序的复杂性,并使得应用程序可读性变差,所以在做一般应用开发时,建议大家不要使用goto语句。

基本语法如下goto lable,其中lable是已经定义好的标号名,

declare

i int:=1; begin loop

dbms_output.put_line(‘输入i=’|| i); if i = 1{} then

goto end_loop; end if; i:=i+1; end loop; <>

dbms_output.put_line(‘循环结束’); end;

2、null:null语句不会执行任何操作,并且会直接控制传递到吓一跳语句。使用null语句的主要好处是可以提高pl/sql的可读性。 declare

v_sal emp.sal%type;

v_ename emp.ename%type; begin

select ename,sal into v_ename,v_sal from emp where empno = &no; if v_sal < 3000 then

update emp set comm =sal * 0.1 where ename = v_ename; else null; end if; end;

pl/sql分页:

编写分页过程:分页任何一个网站(bbs,网上商城,blog)都会使用到的技术,因此学习pl/sql编程开发就一定要掌握该技术。

无返回值的存储过程:古人云:欲速则不达,为了让大家比较容易接受分页过程编写,我还是从简单到复杂,循序渐进的给大家讲解。首先是掌握最简单的存储过程,无返回值的存储过程:

案例:现有一张表book,表结构如下: 书号 书名 出版社

请写一个过程,可以向book表添加数.

——in:表示这是一个输入参数,默认为in ——out:表示一个输出参数

create or replace procedure sp_pro7(spBookId in number,spbookName in varchar2,sppulishHouse in varchar2) is begin

insert into book values(spBookId,spbookName,sppublishHouse); end; /

有返回值的存储过程(飞列表)

再看如何处理有返回值的存储过程:

案例额:编写一个过程,可以输入雇员的编号,返回该雇员的姓名。 案例额扩张:编写一个过程,可以输入雇员的编号,返回该雇员的姓名。

案例扩张:编写一个过程,可以输入雇员的编号,返回该雇员的姓名、工资和岗位。 ——有输入和输出的存储过程 create or replace procedure sp_pro8

(spno in number, spName out varchar2)is begin

select ename into spName from emp where empno=spno; end; /

案例扩张:编写一个过程,可以输入雇员的编号,返回该雇员的姓名、工资和岗位。 ——有输入和输出的存储过程 create or replace procedure sp_pro8

(spno in number,spName out varchar2,spSal out number,spJob out varchar2) is begin

select ename,sal,job into spName,spSal,spJob from emp where empno=spno; end; /

有返回值的存储过程(列表[结果集])

案例:编写一个过程,输入部门号,返回该部门所有雇员信息。 对该题分析如下:

由于oracle存储过程没有返回值,她的所有返回值都是通过out参数来替代的,列表同样也不例外,但由于是集合,所以不能用一般的参数,必须用pagkage了。所以要分两部分: 返回结果集的过程

1、建立一个包,在该包中,我定义类型test_cursor,是个游标。如下: create or replace package testpackage as TYPE test_cursor is ref cursor; end testpackage;

2、建立存储过程。如下:

create or replace procedure sp_pro9(spNo in number,p_cursor out testpackage,test_cursor) is begin

open p_cursor for

select * from emp where deptno=spNo; end sp_pro9;

编写分页过程:有了上面的基础,相信大家可以完成分页存储过程了。

要求,请大家编写一个存储过程,要求可以输入表名、每页显示记录数、当前页。返回总记录数,总页数,和返回的结果集。 ——oracle的分页

select t1.*,rownum rn from (select * from emp) t1 where rownum<=10; ——在分页时,大家可以把下面的sql语句当做一个模板使用 select * from

(select t1.*,rownum rn from (select * frm emp) t1 where rownum<=10)

where rn>=6; ——开发一个包

——建立一个包,在该包中,我定义了类型test_cursor,是个游标如下: create or replace package testpackage as TYPE test_cursor is ref cursor; end testpackage;

——开始编写分页的过程

create or replace procedure fenye (tableName in varchar2,

Pagesize in number,——页显示记录数 pageNow in number,

myrows out number,——总记录数 myPageCount out number,——总页数

p_cursor out testpackage,test_cursor——返回的记录集 ) is

——丁一部分

——定义sql语句 字符串 v_sql varchar2(1000); ——定义两个整数

v_begin number:=(pageNow-1)*Pagesize+1; v_end number:=pageNow*Pagesize; begin

——执行部分 v_sql:=‘select * from (select t1.*,rownum rn from (select * from ‘||tableName||’) t1 where rownum<=‘||v_end||’)where rn>=’||v_begin; ——把游标和sql关联 open p_cursor fro v_sql;

——计算myrows和myPageCount ——组织一个sql语句

v_sql:=‘select count(*) from’|| tableName; ——执行sql,并把返回的值,赋给myrows; execute inmediate v_sql into myrows; ——计算myPageCount

——if myrows%Page四则=0 then这样写是错的 if mod(myrows,Pagesize)=0 then myPageCount:=myrows/Pagesize; else

myPageCount:=myrows/Pagesize+1 end if; /

例外处理:

例外处理 例外的分类:

oracle将例外分为预定义例外,非预定义例外和自定义例外三种。 预定义例外用于处理常见的oracle错误

非预定义例外用于处理预定义例外不能处理的例外 自定义例外用于处理与oracle错误无关的其他情况 例外传递:

如果不处理例外我们看看会出现什么情况:

案例,编写一个过程,可接收雇员的编号,并显示该雇员的姓名。 问题是,如果输入的雇员编号不存在,怎样去处理呢? ——例外案例 declare ——定义

v_ename emp.ename%type; begin ——

select ename into v_ename from emp where empno=&gno; dbms_output.put_line(‘名字:’|| v_ename) /

随便数个不存在的编号,回车,会报出异常,显示: ORA-01403:未找到数据 ORA-06512:在line6 declare ——定义

v_ename emp.ename%type; begin ——

select ename into v_ename from emp where empno=&gno; dbms_output.put_line(‘名字:’||v_ename) exception

when no_data_found then

dbms_output.put_line(‘编号没有!’); /

执行,输入一个不存在的编号,回车,显示:编号没有! 处理预定义例外:预定义例外是由pl/sql所提供的系统例外。当pl/sql应用程序违反了oracle规定的限制时,则会隐含的触发一个内部例外。pl/sql为开发人员提供了二十多个预定义例外。我们给大家介绍常用的例外。

预定义例外case_not_found:在开发pl/sql块中编写case语句是,如果在when子句中没有包含必须的条件分支,就会触发case_not_found的例外: create or replace procedure sp_pro6(spno number) is v_sal emp.sal%type; begin

select sal into v_sal from emp where empno = spno; case

when v_sal < 1000 then update emp set sal = sal+100 where empno = spno;

when v_sal < 2000 then

update emp set sal = sal +200 where empno = spno; end case; exception

when case_not_found then

dbms_output.put_line(‘case语句没有与’|| v_sal || ‘相匹配的条件’); end;

预定义例外cursor_already_open:当重新打开已经打开的游标时,会隐含的触发例外cursor_already_open ceclare

cursor emp_cursor is select ename,sal from emp; begin

open emp_cursor;

for emp_record1 in emp_cursor loop

dbms_output.put_line(emp_record1.ename); end loop; exception

when cursor_already_open then

dbms_output.put_line(‘游标已经打开’); end; /

预定义例外dup_val_on_index:在唯一索引所对应的列上插入重复的值时,会隐含的触发例外dup_val_on_index例外 begin

insert into dept values (10,‘公关部’,‘北京’); exception

when dup_val_on_index then

dbms_output.put_line(‘在deptno列上不能出现重复值’); end;

预定义例外invalid_cursor:当试图在不合法的游标上执行操作时,会触发该例外 例如:试图从没有打开的游标提取数据,或是关闭没有打开的游标。则会触发该例外 declare

cursor emp_cursor is select ename,sal from emp; emp_recourd emp_cursor%rowtype; begin

——open emp_cursor;——打开游标 fetch emp_cursor into emp_record;

dbms_output.put_line(emp_record.ename); close emp_cursor; exception

when invalid_cursor then

dbms_output.put_line(‘请检测游标是否打开’); end;

预定义例外invalid_number:当输入的数据有误时,会触发该例外

比如:数字100写成了1oo就会触发该例外 begin

update emp set sal=sal+‘1oo’; exception

when invalid_number then dbms_output.put_line(‘输入的数字不正确’); end;

预定义例外no_data_found:下面是一个pl/sql块,当执行select into没有返回行,就会触发该例外。 declare

v_sal emp.sal%type begin

select sal into v_sal from emp when ename=‘&name’; exception

when no_data_found then dbms_output.put_line(‘不存在该员工’); end;

预定义例外too_many_rows:当执行select into语句时,如果返回超过了一行,则会触发该例外。 declare

select ename into v_ename from emp; exception

when too_many_rows then

dbms_output.put_line(‘返回了多行’); end;

预义例外zero_divide:当执行2/0语句时,则会触发该例外。

预定义例外value_error:挡在执行赋值操作时,如果变量的长度不足以容纳实际数据,则会触发该例外value_error,比如: declare

v_ename varchar2(5); begin

select ename into v_ename from emp where empno = &nol; dbms_output.put_line(v_ename); exception

when value_error then dbms_output.put_line(‘变量尺寸不足’); end;

其她预定义例外(这些例外不是在pl/sql里触发的,而是在用oracle时触发的,所以取名叫其她预定义例外)

1、login_denied:当用户非法登陆时,会触发该例外

2、not_logged_on:如果用户没有登陆就执行dml操作,就会触发该例外 3、storage_error:如果超过了内存空间或是内存被损坏,就触发该例外

4、timeout_on_resource:如果oracle在等待资源时,出现了超时就触发该例外

非预定义例外:非预定义例外用于处理与预定义例外无关的oracle错误。使用预定义例外只能处理21个oracle错误,而当使用pl/sql开发应用程序时,可能会遇到其她的一些oracle错误。比如在pl/sql块中执行dml语句是,违反了约束规定等等。在这样的情况下,也可以处理oracle的各种例外,因为非预定例外用的不多,这里我就不举例了。

处理自定义例外:预定义例外和自定义例外都是oracle错误相关的,并且出现的oracle错误会隐含的触发相应的例外:而自定义例外与oracle错误没有任何关联,她是由开发人员为特定情况所定义的例外。

问题:请编写一个pl/sql块,接受一个雇员的编号,并给该雇员工资增加1000元,如果该雇员不存在,请提示。 ——自定义例外

create or replace procedure ex_test(spNo number) is begin

——更新用户sal

update emp set sal=sal+1000 where empno=spNo; end; /

运行,该过程被成功创建。 SQL> exec ex_test(56);

PL/SQL过程被成功完成,这里,编号为56是不存在的,刚才的报异常了,为什么现在不报异常呢?

因为刚才的是select语句

怎么解决这个问题呢?修改代目,如下: ——自定义例外

create or replace procedure ex_test(spNo number) is

——定义一个例外 myex exception; begin

——更新用户sal

update emp set sal=sal+1000 where empno=spNo; ——sal%notfound这是表示没有update ——raise myex;触发myex if sql%notfound then raise myex; end if; exception

when myex then

dbms_output.put_line(‘没有更新任何用户’); end; /

现在再测试一次:

SQL> exec ex_test(56); 没有更新任何用户

oracle的视图

oracle的视图:视图是一个虚拟表,其内容有查询定义,同真是的表一样,视图包含一系列带有名称的列和行数据。但是,视图并不在数据库中以存储的数据值集形式存在。行和列数据来自由定义视图的查询所引用的表,并且在引用视图是动态生成。(视图不是真实存在磁盘上的)

视与表的区别:

1、表需要占用磁盘空间,视图不需要

2、视图不能添加索引(所以查询速度略微慢点)

3、使用视图可以简化,复杂查询(比如:学生选课系统) 4、视图的使用利于提高安全性(比如:不同用户查看不同视图) 创建/修改视图 创建视图:

create view 视图名 as select 语句 [with read only] 创建或修改视图:

create or replace view 视图名 as select 语句 [with read only] 删除视图:

drop view 视图名

当表结构过于复杂,请使用视图吧!

——创建视图,把emp表的sal < 1000的雇员映射到该视图(view) create view myview as select * from emp where sal<1000;

——为简化操作,用一个视图解决 显示雇员编号,姓名和部门名称

create view myview2 as select emp.empno,emp.ename,dept.dname from emp,dept where emp.deptno=dept.deptno; 视图之间也可以做联合查询

因篇幅问题不能全部显示,请点此查看更多更全内容