Oracle学习笔记(最重要的是PL/SQL编程)

本文详细介绍了Oracle数据库的管理,包括用户管理、基本命令、表的管理及数据操作。重点讲述了PL/SQL编程,如创建用户、修改权限、解锁账户、管理口令、处理查询异常。此外,还探讨了视图的概念和创建,强调了视图在简化复杂查询和提升安全性方面的作用。
摘要由CSDN通过智能技术生成

一:Oracle认证,与其它数据库比较,安装

Oracle安装会自动的生成sys用户和system用户: 

(1) sys用户是超级用户,具有最高权限,具有sysdba角色,有create database的权限,该用户默认的密码是change_on_install 

(2) system用户是管理操作员,权限也很大。具有sysoper角色,没有create database的权限,默认的密码是manager 

(3) 一般讲,对数据库维护,使用system用户登录就可以拉 

也就是说sys和system这两个用户最大的区别是在于有没有create database的权限。

 

二: Oracle的基本使用--基本命令

sql*plus的常用命令 
连接命令 

1.conn[ect] 
用法:conn 用户名/密码@网络服务名[as sysdba/sysoper]当用特权用户身份连接时,必须带上as sysdba或是as sysoper 
2.disc[onnect] 
说明: 该命令用来断开与当前数据库的连接 
3.psssw[ord] 
说明: 该命令用于修改用户的密码,如果要想修改其它用户的密码,需要用sys/system登录。 
4.show user 
说明: 显示当前用户名 
5.exit 
说明: 该命令会断开与数据库的连接,同时会退出sql*plus 
文件操作命令 
1.start和@ 
说明: 运行sql脚本 
案例: sql>@ d:\a.sql或是sql>start d:\a.sql 
2.edit 
说明: 该命令可以编辑指定的sql脚本 
案例: sql>edit d:\a.sql,这样会把d:\a.sql这个文件打开 
3.spool 
说明: 该命令可以将sql*plus屏幕上的内容输出到指定文件中去。 
案例: sql>spool d:\b.sql 并输入 sql>spool off 
交互式命令 
1.& 

说明:可以替代变量,而该变量在执行时,需要用户输入。 
select * from emp where job='&job'; 
2.edit 
说明:该命令可以编辑指定的sql脚本 
案例:SQL>edit d:\a.sql 
3.spool 
说明:该命令可以将sql*plus屏幕上的内容输出到指定文件中去。 
spool d:\b.sql 并输入 spool off 
显示和设置环境变量 

概述:可以用来控制输出的各种格式,set show如果希望永久的保存相关的设置,可以去修改glogin.sql脚本 

1.linesize 

说明:设置显示行的宽度,默认是80个字符 

show linesize 

set linesize 90 

2.pagesize说明:设置每页显示的行数目,默认是14 

用法和linesize一样 

至于其它环境参数的使用也是大同小异 

 

三:oracle用户管理

oracle用户的管理 
创建用户 
概述:在oracle中要创建一个新的用户使用create user语句,一般是具有dba(数据库管理员)的权限才能使用。 
create user 用户名 identified by 密码; (oracle有个毛病,密码必须以字母开头,如果以字母开头,它不会创建用户) 
给用户修改密码 
概述:如果给自己修改密码可以直接使用 
password 用户名 
如果给别人修改密码则需要具有dba的权限,或是拥有alter user的系统权限 
SQL> alter user 用户名 identified by 新密码 
 删除用户 
概述:一般以dba的身份去删除某个用户,如果用其它用户去删除用户则需要具有drop user的权限。 
比如 drop user 用户名 【cascade】 
在删除用户时,注意: 
如果要删除的用户,已经创建了表,那么就需要在删除的时候带一个参数cascade; 
用户管理的综合案例 
概述:创建的新用户是没有任何权限的,甚至连登陆的数据库的权限都没有,需要为其指定相应的权限。给一个用户赋权限使用命令grant,回收权限使用命令revoke。 
为了给讲清楚用户的管理,这里我给大家举一个案例。 
SQL> conn xiaoming/m12; 
ERROR: 
ORA-01045: user XIAOMING lacks CREATE SESSION privilege; logon denied 
警告: 您不再连接到 ORACLE。 
SQL> show user; 
USER 为 "" 
SQL> conn system/p; 
已连接。 
SQL> grant connect to xiaoming; 
授权成功。 
SQL> conn xiaoming/m12; 
已连接。 
SQL> 
注意:grant connect to xiaoming;在这里,准确的讲,connect不是权限,而是角色。。 看图: 

现在说下对象权限,现在要做这么件事情: 
* 希望xiaoming用户可以去查询emp表 
* 希望xiaoming用户可以去查询scott的emp表 
  grant select on emp to xiaoming 
* 希望xiaoming用户可以去修改scott的emp表 
  grant update on emp to xiaoming 
* 希望xiaoming用户可以去修改/删除,查询,添加scott的emp表 
  grant all on emp to xiaoming 
* scott希望收回xiaoming对emp表的查询权限 
  revoke select on emp from xiaoming 

//对权限的维护。 
* 希望xiaoming用户可以去查询scott的emp表/还希望xiaoming可以把这个权限继续给别人。 
--如果是对象权限,就加入 with grant option 
  grant select on emp to xiaoming with grant option 
我的操作过程: 
SQL> conn scott/tiger; 
已连接。 
SQL> grant select on scott.emp to xiaoming with grant option; 
授权成功。 
SQL> conn system/p; 
已连接。 
SQL> create user xiaohong identified by m123; 
用户已创建。 
SQL> grant connect to xiaohong; 
授权成功。 
SQL> conn xiaoming/m12; 
已连接。 
SQL> grant select on scott.emp to xiaohong; 
授权成功。 

--如果是系统权限。 
system给xiaoming权限时: 
grant connect to xiaoming with admin option 

问题:如果scott把xiaoming对emp表的查询权限回收,那么xiaohong会怎样? 
答案:被回收。 

下面是我的操作过程: 
SQL> conn scott/tiger; 
已连接。 
SQL> revoke select on emp from xiaoming; 
撤销成功。 
SQL> conn xiaohong/m123; 
已连接。 
SQL> select * from scott.emp; 
select * from scott.emp 
第 1 行出现错误: 
ORA-00942: 表或视图不存在 

结果显示:小红受到诛连了。

使用profile管理用户口令 
概述:profile是口令限制,资源限制的命令集合,当建立数据库的,oracle会自动建立名称为default的profile。当建立用户没有指定profile选项,那么oracle就会将default分配给用户。 
1.账户锁定 
概述:指定该账户(用户)登陆时最多可以输入密码的次数,也可以指定用户锁定的时间(天)一般用dba的身份去执行该命令。 
例子:指定scott这个用户最多只能尝试3次登陆,锁定时间为2天,让我们看看怎么实现。 
创建profile文件 
SQL> create profile lock_account limit failed_login_attempts 3 password_lock_time 2; 
SQL> alter user scott profile lock_account; 
2.给账户(用户)解锁 
SQL> alter user tea account unlock; 
3.终止口令 
为了让用户定期修改密码可以使用终止口令的指令来完成,同样这个命令也需要dba的身份来操作。 
例子:给前面创建的用户tea创建一个profile文件,要求该用户每隔10天要修改自己的登陆密码,宽限期为2天。看看怎么做。 
SQL> create profile myprofile limit password_life_time 10 password_grace_time 2; 
SQL> alter user tea profile myprofile; 

口令历史 
概述:如果希望用户在修改密码时,不能使用以前使用过的密码,可使用口令历史,这样oracle就会将口令修改的信息存放到数据字典中,这样当用户修改密码时,oracle就会对新旧密码进行比较,当发现新旧密码一样时,就提示用户重新输入密码。 
例子: 
1)建立profile 
SQL>create profile password_history limit password_life_time 10 password_grace_time 2 password_reuse_time 10 
password_reuse_time //指定口令可重用时间即10天后就可以重用 
2)分配给某个用户 
删除profile 
概述:当不需要某个profile文件时,可以删除该文件。 
SQL> drop profile password_history 【casade】 
注意:文件删除后,用这个文件去约束的那些用户通通也都被释放了。

加了casade,就会把级联的相关东西也给删除掉

 

四:oracle表的管理(数据类型,表创建删除,数据CRUD操作

oracle的表的管理 

表名和列的命名规则 

· 必须以字母开头 

· 长度不能超过30个字符 

· 不能使用oracle的保留字 

· 只能使用如下字符 A-Z,a-z,0-9,$,#等 

oracle支持的数据类型
字符类 
char    定长 最大2000个字符。 
例子:char(10)  ‘小韩’前四个字符放‘小韩’,后添6个空格补全 如‘小韩’ 
varchar2(20)  变长  最大4000个字符。 
例子:varchar2(10) ‘小韩’ oracle分配四个字符。这样可以节省空间。 
clob(character large object) 字符型大对象 最大4G 
char 查询的速度极快浪费空间,查询比较多的数据用。 
varchar 节省空间 

数字型
number范围 -10的38次方 到 10的38次方 
可以表示整数,也可以表示小数 
number(5,2) 
表示一位小数有5位有效数,2位小数 
范围:-999.99到999.99 
number(5) 
表示一个5位整数 
范围99999到-99999 

日期类型 
date 包含年月日和时分秒   oracle默认格式  1-1月-1999 
timestamp 这是oracle9i对date数据类型的扩展。可以精确到毫秒。 
图片
blob 二进制数据 可以存放图片/声音  4G   一般来讲,在真实项目中是不会把图片和声音真的往数据库里存放,一般存放图片、视频的路径,如果安全需要比较高的话,则放入数据库。 

怎样创建表 
 建表
--学生表 
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) 

); 

修改表 
 添加一个字段

SQL>ALTER TABLE student add (classId NUMBER(2)); 
修改一个字段的长度 
SQL>ALTER TABLE student MODIFY (xm VARCHAR2(30)); 
修改字段的类型/或是名字(不能有数据) 不建议做 
SQL>ALTER TABLE student modify (xm CHAR(30)); 
删除一个字段  不建议做(删了之后,顺序就变了。加就没问题,应为是加在后面)
SQL>ALTER TABLE student DROP COLUMN sal; 
 修改表的名字   很少有这种需求n 
SQL>RENAME student TO stu; 
 删除表n 
SQL>DROP TABLE student; 

添加数据 
所有字段都插入数据n 
INSERT INTO student VALUES ('A001', '张三', '男', '01-5月-05', 10); 
oracle中默认的日期格式‘dd-mon-yy’ dd日子(天) mon 月份  yy  2位的年  ‘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); 
 插入部分字段n 
INSERT INTO student(xh, xm, sex) VALUES ('A003', 'JOHN', '女'); 
 插入空值n 
INSERT INTO student(xh, xm, sex, birthday) VALUES ('A004', 'MARTIN', '男', null); 
问题来了,如果你要查询student表里birthday为null的记录,怎么写sql呢? 
错误写法:select * from student where birthday = null; 
正确写法: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值的数据 
不要用 = null 而是用 is 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)

oracle表基本查询 
介绍

在我们讲解的过程中我们利用scott用户存在的几张表(emp,dept)为大家演示如何使用select语句,select语句在软件编程中非常有用,希望大家好好的掌握。 
emp 雇员表 
clerk  普员工 
salesman 销售 
manager  经理 
analyst 分析师 
president  总裁 
mgr  上级的编号 
hiredate 入职时间 
sal 月工资 
comm 奖金 
deptno 部门 
dept部门表 
deptno 部门编号 
accounting 财务部 
research  研发部 
operations 业务部 
loc 部门所在地点 
salgrade   工资级别 
grade    级别 
losal    最低工资 
hisal    最高工资 

简单的查询语句 
查看表结构

DESC emp; 
查询所有列
SELECT * FROM dept; 
切忌动不动就用select * 
SET TIMING ON; 打开显示操作时间的开关,在下面显示查询时间。 
CREATE TABLE users(userId VARCHAR2(10), uName VARCHAR2 (20), uPassw VARCHAR2(30)); 
INSERT INTO users VALUES('a0001', '啊啊啊啊', 'aaaaaaaaaaaaaaaaaaaaaaa'); 
--从自己复制,加大数据量 大概几万行就可以了  可以用来测试sql语句执行效率 
INSERT INTO users (userId,UNAME,UPASSW) SELECT * FROM users; 
SELECT COUNT (*) FROM users;统计行数 

 查询指定列
SELECT ename, 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 'S%'; 
如何显示第三个字符为大写O的所有员工的姓名和工资? 
SELECT ename,sal FROM emp WHERE ename like '__O%'; 

 在where条件中使用inn 
问题:如何显示empno为7844, 7839,123,456 的雇员情况? 
SELECT * FROM emp WHERE empno in (7844, 7839,123,456); 
 使用is null的操作符n 
问题:如何显示没有上级的雇员的情况? 
错误写法:select * from emp where mgr = ''; 
正确写法: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 byn 字句   默认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; 
别名需要使用“”号圈中,英文不需要“”号 

 分页查询n 
等学了子查询再说吧。。。。。。。。 

Clear 清屏命令 

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

数据分组 ——max,min, avg, sum, count 
问题:如何显示所有员工中最高工资和最低工资? 
SELECT MAX(sal),min(sal) FROM emp e; 
      最高工资那个人是谁? 
错误写法:select ename, sal from emp where sal=max(sal); 
正确写法: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, job, sal FROM emp e where sal = (SELECT MAX(sal) FROM emp); 
显示工资高于平均工资的员工信息 
SELECT * FROM emp e where sal > (SELECT AVG(sal) FROM emp); 

group by 和 having子句n 
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; 

 对数据分组的总结n 
1 分组函数只能出现在选择列表、having、order by子句中(不能出现在where中) 
2 如果在select语句中同时包含有group by, having, order by 那么它们的顺序是group by, having, order by 
3 在选择列中如果有列、表达式和分组函数,那么这些列和表达式必须有一个出现在group by 子句中,否则就会出错。 
如SELECT deptno, AVG(sal), MAX(sal) FROM emp GROUP by deptno HAVING AVG(sal) < 2000; 
这里deptno就一定要出现在group by 中 

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

问题:显示雇员名,雇员工资及所在部门的名字【笛卡尔集】? 
规定:多表查询的条件是 至少不能少于 表的个数-1 才能排除笛卡尔集 
(如果有N张表联合查询,必须得有N-1个条件,才能避免笛卡尔集合) 
SELECT e.ename, e.sal, 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的表结构和记录 
SQL>select * from salgrade; 
    GRADE         LOSAL          HISAL 
-------------   -------------   ------------ 
        1          700           1200 
        2          1201          1400 
        3          1401          2000 
        4          2001          3000 
        5          3001          9999 
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 emp WHERE 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); 
(注意:不能用job=..,因为等号=是一对一的) 

 在多行子查询中使用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; 

如何衡量一个程序员的水平? 
网络处理能力, 数据库, 程序代码的优化程序的效率要很高 

小总结: 
在这里需要说明的当在from子句中使用子查询时,该子查询会被作为一个视图来对待,因此叫做内嵌视图,当在from子句中使用子查询时,必须给子查询指定别名。 
注意:别名不能用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最差。 

//测试通过的分页查询okokok 
select * from (select a1.*, rownum rn from(select ename,job from emp) a1 where rownum<=10)where rn>=5; 

下面最主要介绍第三种:按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.*, ROWNUM rn FROM (SELECT ename, sal FROM emp ORDER by sal) e WHERE ROWNUM <= 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,union all,intersect,minus 
多用于数据量比较大的数据局库,运行速度快。 
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). minus 
使用改操作符用于取得两个结果集的差集,他只会显示存在第一个集合中,而不存在第二个集合中的数据。 
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).我们可以用手工步骤直接创建。

 

七:Java操作oracle

java连接oracle 
 介绍:前面我们一直在plsql中操作oracle,那么如何在java 程序中操作数据库呢? 下面我们举例说明,写一个java,分页显示emp表的用户信息。 

Java代码 

1. package com.sp;   

2.   

3. import java.sql.Connection;   

4. import java.sql.DriverManager;   

5. import java.sql.ResultSet;   

6. import java.sql.Statement;   

7.   

8. //演示  如何使用 jdbc_odbc桥连接方式   

9. public class TestOracle {   

10.   

11.     public static void main(String[] args) {   

12.         try {   

13.   

14.             // 1.加载驱动   

15.             Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");   

16.   

17.             // 2.得到连接   

18.             Connection ct = DriverManager.getConnection(   

19.                     "jdbc.odbc:testConnectOracle", "scott",    

20.   

21. "tiger");   

22.   

23.             // 从下面开始,和SQL Server一模一样   

24.             Statement sm = ct.createStatement();   

25.             ResultSet rs = sm.executeQuery("select * from emp");   

26.             while (rs.next()) {   

27.                 //用户名   

28.                 System.out.println("用户名: "+rs.getString(2));   

29.                 //默认是从1开始编号的   

30.             }   

31.         } catch (Exception e) {   

32.             e.printStackTrace();   

33.         }   

34.     }   

35. }  

package com.sp;

 

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.ResultSet;

import java.sql.Statement;

 

//演示  如何使用 jdbc_odbc桥连接方式

public class TestOracle {

 

public static void main(String[] args) {

try {

 

// 1.加载驱动

Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");

 

// 2.得到连接

Connection ct = DriverManager.getConnection(

"jdbc.odbc:testConnectOracle", "scott", 

 

"tiger");

 

// 从下面开始,和SQL Server一模一样

Statement sm = ct.createStatement();

ResultSet rs = sm.executeQuery("select * from emp");

while (rs.next()) {

//用户名

System.out.println("用户名: "+rs.getString(2));

//默认是从1开始编号的

}

} catch (Exception e) {

e.printStackTrace();

}

}

}

在得到连接那里,要去配置数据源,点击控制面板-->系统和安全-->管理工具-->数据源(ODBC),打开后点添加,如图: 

可以看到,有个Oracle in OraDb10g_home1的驱动,它是Oracle安装完后自动加上去的。 选中后,点完成,再填如下信息,如图: 
这样配好后基本就可以了,但为了安全起见,建议大家测试一下,点击 Test Connection按钮, 测试通过后点ok,然后数据源就生成了,如图: 
然后把数据源名称写进jdbc.odbc:里。 

这里要注意:jdbcodbc能不能远程连接呢?不能远程连接,也就是你这样写的话就意味着java程序和oracle数据库应该是在同一台机器上,因为这里没有指定IP地址,肯定默认就是本地。如果要远程连,就用jdbc,jdbc是可以远程连的。 

运行TestOracle.java,控制台输出....................... 

可惜我没运行成功,说 

java.sql.SQLException: No suitable driver found for jdbc.odbc:testConnectOracle 
at java.sql.DriverManager.getConnection(Unknown Source) 
at java.sql.DriverManager.getConnection(Unknown Source) 
at com.sp.TestOracle.main(TestOracle.java:18) 
不知道为什么。。。 

接下来讲解用JDBC的方式连接Oracle 

Java代码 

1. package com.sp;   

2.   

3. import java.sql.Connection;   

4. import java.sql.DriverManager;   

5. import java.sql.ResultSet;   

6. import java.sql.Statement;   

7.   

8. //使用 jdbc连接oracle   

9. public class TestOracle2 {   

10.   

11.     public static void main(String[] args) {   

12.         try {   

13.   

14.             // 1.加载驱动   

15.             Class.forName("oracle.jdbc.driver.OracleDriver");   

16.   

17.             // 2.得到连接   

18.             Connection ct = DriverManager.getConnection   

19.   

20. ("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "scott", "tiger");   

21.   

22.             // 从下面开始,和SQL Server一模一样   

23.             Statement sm = ct.createStatement();   

24.             ResultSet rs = sm.executeQuery("select * from emp");   

25.             while (rs.next()) {   

26.                 //用户名   

27.                 System.out.println("用户名: "+rs.getString(2));   

28.                 //默认是从1开始编号的   

29.             }   

30.         } catch (Exception e) {   

31.             e.printStackTrace();   

32.         }   

33.     }   

34. }  

package com.sp;

 

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.ResultSet;

import java.sql.Statement;

 

//使用 jdbc连接oracle

public class TestOracle2 {

 

public static void main(String[] args) {

try {

 

// 1.加载驱动

Class.forName("oracle.jdbc.driver.OracleDriver");

 

// 2.得到连接

Connection ct = DriverManager.getConnection

 

("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "scott", "tiger");

 

// 从下面开始,和SQL Server一模一样

Statement sm = ct.createStatement();

ResultSet rs = sm.executeQuery("select * from emp");

while (rs.next()) {

//用户名

System.out.println("用户名: "+rs.getString(2));

//默认是从1开始编号的

}

} catch (Exception e) {

e.printStackTrace();

}

}

}



记得要把驱动包引入,classes12.jar 
运行,。。。。 再次可惜,我还是没运行成功,错误是: 
java.sql.SQLException: Io 异常: The Network Adapter could not establish the 

connection 
at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:134) 
at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:179) 
at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:334) 
at oracle.jdbc.driver.OracleConnection.<init>(OracleConnection.java:418) 
at oracle.jdbc.driver.OracleDriver.getConnectionInstance 

(OracleDriver.java:521) 
at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:325) 
at java.sql.DriverManager.getConnection(Unknown Source) 
at java.sql.DriverManager.getConnection(Unknown Source) 
at com.sp.TestOracle2.main(TestOracle2.java:18) 
我也不知道为什么。。。 幽怨了。。 

接下来建个web project,来测试oracle的分页,挺麻烦,不记录了。。 


在oracle中操作数据 - 使用特定格式插入日期值 
 使用 to_date函数n 
请大家思考: 如何插入列带有日期的表,并按照年-月-日的格式插入? 
insert into emp values  (9998,  'xiaohong',  'MANAGER',  7782,  to_date('1988-12- 

12', 'yyyy-mm-dd'),  78.9,  55.33,  10); 

注意: 
insert into emp values  (9998,  'xiaohong',  'MANAGER',  7782,  '12-12月-1988', 

78.9,  55.33,  10); 
这句语句是可以成功运行的 



使用子查询插入数据 
 介绍n 
当使用valus子句时,一次只能插入一行数据,当使用子查询插入数据时,一条inset语句可以插 

入大量的数据。当处理行迁移或者装载外部表的数据到数据库时,可以使用子查询来插入数据。 
把emp表中10号部门的数据导入到新表中 
create table kkk(myId number(4), myName varchar2(50), myDept number(5)); 
insert into kkk (myId, myName, myDept)  select empno, ename, deptno from emp where 

deptno = 10; 

 介绍n 
使用update语句更新数据时,既可以使用表达式或者数值直接修改数据,也可以使用子查询修改 

数据。 
问题:希望员工SCOTT的岗位、工资、补助与SMITH员工一样。 
update emp set(job, sal, comm)=(select job, sal, comm from emp where ename='SMITH') where ename='SCOTT';

 

八:oracle中事务处理

什么是事务 
事务用于保证数据的一致性,它由一组相关的dml语句组成,该组的dml(数据操作语言,增删改,没有查询)语句要么全部成功,要么全部失败。 
如:网上转账就是典型的要用事务来处理,用于保证数据的一致性。 
dml 数据操作语言 
银行转账、QQ申请、车票购买 
 事务和锁n 
当执行事务操作时(dml语句),oracle会在被作用的表上加锁,防止其它用户修改表的结构。这里对我们的用户来来讲是非常重要的。 
.....其它进程排序,知道1号进程完成,锁打开,2号进程进入。依次进行,如果有进程级别较高的,可以插队。 


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


 回退事务n 
在介绍回退事务前,我们先介绍一下保存点(savepoint)的概念和作用。保存点是事务中的一点。用于取消部分事务,当结束事务时,会自动的删除该事务所定义的所有保存点。当执行rollback时,通过指定保存点可以回退到指定的点,这里我们作图说明。 

 事务的几个重要操作n 
1.设置保存点 savepoint a 
2.取消部分事务 rollback to a 
3.取消全部事务 rollback 

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

 

java程序中如何使用事务

在java操作数据库时,为了保证数据的一致性,比如账户操作(1)从一个账户中减掉10$(2)在另一个账户上加入10$,我们看看如何使用事务? 

Java代码 

1. package com.sp;   

2.   

3. import java.sql.Connection;   

4. import java.sql.DriverManager;   

5. import java.sql.ResultSet;   

6. import java.sql.Statement;   

7.   

8. public class TestTrans {   

9.   

10.     public static void main(String[] args) {   

11.         try {   

12.   

13.             // 1.加载驱动   

14.             Class.forName("oracle.jdbc.driver.OracleDriver");   

15.   

16.             // 2.得到连接   

17.             Connection ct = DriverManager.getConnection(   

18.                     "jdbc:oracle:thin:@127.0.0.1:1521:orcl", "scott", "tiger");   

19.   

20.             Statement sm = ct.createStatement();   

21.   

22.             // 从scott的sal中减去100   

23.             sm.executeUpdate("update emp set sal=sal-100 where ename='SCOTT'");   

24.   

25.             int i = 7 / 0;   

26.   

27.             // 给smith的sal加上100   

28.             sm.executeUpdate("update emp set sal=sal+100 where ename='SMITH'");   

29.   

30.             // 关闭打开的资源   

31.             sm.close();   

32.             ct.close();   

33.         } catch (Exception e) {   

34.             e.printStackTrace();   

35.         }   

36.   

37.     }   

38.   

39. }  

package com.sp;

 

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.ResultSet;

import java.sql.Statement;

 

public class TestTrans {

 

public static void main(String[] args) {

try {

 

// 1.加载驱动

Class.forName("oracle.jdbc.driver.OracleDriver");

 

// 2.得到连接

Connection ct = DriverManager.getConnection(

"

  • 0
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值