1>-----------------------------表空间-------------------------
1.1>创建表空间example
create tablespace 表空间名称[example]
logging
datafile 数据库存储位置['/opt/oracle/oradata/orcl/EPSSITE.dbf']
size 50m [初始大小]
autoextend on
next 50m maxsize 20480m [每次增长,和最大占有]
extent management local;
1.2>查看创建好的表空间
select default_tablespace, temporary_tablespace, d.username from dba_users d;
2>------------------------------用户-------------------------------
2.1>创建用户easysite并赋权
create user [用户名称]easysite identified by [密码]easysite default tablespace [表空间]example;
grant connect,imp_full_database,resource,dba[高级权限] to [给用户赋权]easysite;
2.2>查看数据库用户
select * from dba_users;
2.3>删除用户
drop user 用户名 cascade;---cascade 级联
2.4>----------------------------权限---------------------
2.4.1>-- 用户权限
-- 分配用户 Sam 创建表,创建序列,创建存储过程和创建视图的权限
grant create table,create sequence,create view,create procedure to [用户]sam
-- 去除用户创建视图的权限
revoke create view from sam;
-- 分配用户 Sam 在表 tt 上的 select 权限
grant select on tt to sam;
-- 去除用户 Sam 在表 tt 上的 select 权限
revoke select on tt from sam;
-- 分配表的 Select 权限给所有用户
grant select on tt to public;
-- 去除表的 Select 权限给所有用户
revoke select on tt from public;
2.4.2>-- 角色权限
-- 分配角色 manager 创建表,创建序列的权限
grant create table,create sequence to manager;
-- 去除角色 manager 创建视图的权限
revoke create table from manager;
-- 分配表的 Update 权限给角色 Manager
grant update on tt to manager;
-- 去除表的 Update 权限给角色 Manager
revoke update on tt from manager;
3>还原数据
imp 用户名[easysite]/密码[easysite] file=数据库文件位置[e:/easysite.dmp] full=y
4>备份数据[d:\oracle 目录需要先创建好]
exp user/password@orcl[实例名] file=[文件路径]d:\oracle\example.tmp log=[日志路径]d:\oracle\example.log
第一课:客户端
1. Sql Plus(客户端),命令行直接输入:sqlplus,然后按提示输入用户名(scott ),密码(tiger)。
2. 从开始程序运行:sqlplus,是图形版的sqlplus.
3. http://localhost:5560/isqlplus
Toad:管理, PlSql Developer:
-------------------------------------------------------------
第二课:更改用户
1. sqlplus sys/bjsxt as sysdba
2. alter user scott account unlock;(解锁)
show user 查看当前用户
conn scott/tiger 更改用户
--------------------------------------------------------------
第三课:table structure
1. 描述某一张表:desc 表名
2. select * from 表名
----------------------------------------------------------------
第四课:select 语句:
1.计算数据可以用空表(dual):比如:select 2*3 from dual(sqlserver不成立) select sysdate from dual 查询当前日期
2.select ename,sal*12 annual_sal from emp;与select ename,sal*12 "annual sal" from emp;区别,加双引号保持原显示方式包括大小写。如果不加 写成annual sal会出错。而且会都显示为大写。(sql server 加不加双引号都是大小写不变)
3. select ename || "abcd" 如果连接字符串中含有单引号,用两个单引号代替一个单引号。(相当于sql server的+) 如果两个单引号是ename'abcd' 如果是单引号是enameabcd
------------------------------------------------------------------------------------------
第五课:distinct
select deptno from emp;
select distinct deptno from emp;
select distinct deptno from emp;
select distinct deptno ,job from emp
去掉deptno,job两者组合的重复。更多的项,就是这么多项的组合的不重复组合。
--------------------------------------------------------------------------------------
第六课:Where
select * from emp where deptno =10;
select * from emp where deptno <>10;不等于10
select * from emp where ename ='bike';
select ename,sal from emp where sal between 800 and 1500 (>=800 and <=1500)
空值处理:
select ename,sal,comm from emp where comm is (not) null;
select ename,sal,comm from emp where ename ( not)in ('smith','king','abc');
select ename from emp where ename like '_A%';_代表一个字母,%代表0个或多个字母. 如果查询%,+代表一个或者多个
可用转义字符.\%. 还可以用escape '$'比如:select ename from emp where ename like '%$a%' escape '$';select ename from emp where ename like '\%a%'
----------------------------------------------------------------------------------------
第七课: orderby
select * from dept;
select * from dept order by dept desc;(默认:asc)
select ename,sal,deptno from emp order by deptno asc,ename desc;
----------------------------------------------------------------------------------------
第八课: sql function1:
select ename,sal*12 annual_sal from emp
where ename not like '_A%' and sal>800
order by sal desc;
select lower(ename) from emp;
select ename from emp
where lower(ename) like '_a%';等同于
select ename from emp where ename like '_a%' or ename like '_A%';
select substr(ename,2,3) from emp;从第二字符截,一共截三个字符.
select chr(65) from dual 结果为:A
select ascii('a') from dual 结果为:65
select round(23.652,1) from dual; 结果为: 23.7
select round(23.652,-1) from dual; 20
select to_char(sal,'$99_999_999') from emp;
select to_char(sal,'L99_999_999') from emp;人民币符号,L:代表本地符号
这个需要掌握牢:
select birthdate from emp;
显示为:
BIRTHDATE
----------------
17-12月-80
----------------
改为:
select to_char(birthdate,'YYYY-MM-DD HH:MI:SS') from emp;
显示:
BIRTHDATE
-------------------
1980-12-17 12:00:00
-------------------
select to_char(sysdate,'YYYY-MM-DD HH24:MI:SS') from dual; //也可以改为:HH12
TO_CHAR(SYSDATE,'YY
-------------------
2007-02-25 14:46:14
to_date函数:
select ename,birthdate from emp where birthdate > to_date('1981-2-20 12:34:56','YYYY-MM-DD HH24:MI:SS');
如果直接写 birthdate>'1981-2-20 12:34:56'会出现格式不匹配,因为表中的格式为: DD-MM月-YY.
select sal from emp where sal>888.88 无错.但
select sal from emp where sal>$1,250,00;
会出现无效字符错误.
改为:
select sal from emp where sal>to_number('$1.250.00','$9,999,99');
把空值改为0
select ename,sal*12+nvl(comm,0) from emp;
这样可以防止comm为空时,sal*12相加也为空的情况.
------------------------------------------------------------------------------------------
第九课: Group function 组函数
max,min,avg ,count,sum函数
select to_char(avg(sal),'99999999,99') from emp;
select round(avg(sal),2) from emp;
结果:2073.21
select count(*) from emp where deptno=10;
select count(ename) from emp where deptno=10; count某个字段,如果这个字段不为空就算一个.
select count(distinct deptno) from emp;
select sum(sal) from emp;
------------------------------------------------------------------------------------------
第十课: Group by语句
需求:现在想求,求每个部门的平均薪水.
select avg(sal) from emp group by deptno;
select deptno,avg(sal) from emp group by deptno;
select deptno,job,max(sal) from emp group by deptno,job;
求薪水值最高的人的名字.
select ename,max(sal) from emp;出错,因为max只有一个值,但等于max值的人可能好几个,不能匹配.
应如下求:
select ename from emp where sal=(select max(sal) from emp);
Group by语句应注意,
出现在select中的字段,如果没出现在组函数中,必须出现在Group by语句中.
-----------------------------------------------------------------------------------------
第十一课: Having 对分组结果筛选
Where是对单条纪录进行筛选,Having是对分组结果进行筛选.
select avg(sal),deptno from emp
group by deptno
having avg(sal)>2000;
查询工资大于1200雇员,按部门编号进行分组,分组后平均薪水大于1500,按工薪倒充排列.
select * from emp
where sal>1200
group by deptno
having avg(sal)>1500
order by avg(sal) desc;
------------------------------------------------------------------------------------------
第十二课:子查询
谁挣的钱最多(谁:这个人的名字, 钱最多)
select 语句中嵌套select 语句,可以在where,from后.
问那些人工资,在平均工资之上.
select ename,sal from emp where sal>(select avg(sal) from emp);
查找每个部门挣钱最多的那个人的名字.
select ename ,deptno from emp where sal in(select max(sal) from ename group by deptno) 查询会多值.
应该如下:
select max(sal),deptno from emp group by deptno;当成一个表.语句如下:
select ename, sal from emp join(select max(sal) max_sal,deptno from emp group
by deptno) t on(emp.sal=t.max_sal and emp.deptno=t.deptno);
每个部门的平均薪水的等级.
分析:首先求平均薪水(当成表),把平均薪水和另外一张表连接.
-------------------------------------------------------------------------------------------
第十四课:self_table_connection
把某个人的名字以及他的经理人的名字求出来(经理人及这个人在表中同处一行)
分析:首先求出这个人的名字,取他的编号,然后从另一张表与其相对应编号,然后找到经理的名字.
select e1.ename ,e2.ename from emp e1,emp e2 where e1.mgr= e2.empno.
empno编号和MGR都是编号.
------------------------------------------------------------------------------------------
第十15课: SQL1999_table_connections
select ename,dname,grade from emp e,dept d, sqlgrade s
where e.deptno = d.deptno and e.sql between s.losal and s.hisal and
job<>'CLERK';
有没有办法把过滤条件和连接条件分开来? 出于这样考虑,Sql1999标准推出来了.有许多人用的还是
旧的语法,所以得看懂这种语句.
select ename,dname from emp,dept;(旧标准).
select ename,dname from emp cross join dept;(1999标准)
select ename,dname from emp,dept where emp.deptno=dept.deptno (旧)
select ename,dname from emp join dept on(emp.deptno = dept.deptno); 1999标准.没有Where语句.
select ename,dname from emp join dept using(deptno);等同上句,但不推荐使用.
select ename,grade from emp e join salgrade s on(e.sal between s.losal and s.hisal);
join 连接语句, on过滤条件。连接,条件一眼分开。如果用Where语句较长时,连接语句和过滤语句混在一起。
三张表连接:
slect ename,dname, grade from
emp e join dept d on(e.deptno=d.deptno)
join salgrade s on(e.sal between s.losal and s.hisal)
where ename not like '_A%';
把每张表连接 条件不混在一起,然后数据过滤条件全部区分开来。读起来更清晰,更容易懂一点。
select e1.ename,e2.ename from emp e1 join emp e2 on(e1.mgr = e2.emptno);
左外连接:会把左边这张表多余数据显示出来。
select e1.ename,e2,ename from emp e1 left join emp e2 on(e1.mgr =e2.empno);left 后可加outer
右外连接:会把右边这张表多余数据显示出来。
select ename,dname from emp e right outer join dept d on(e.deptno =d.deptno); outer可以取掉。
即把左边多余数据,也把右边多余数据拿出来,全外连接。
select ename,dname from emp e full join dept d on(e.deptno =d.deptno);
16-23 课:求部门平均薪水的等级
A.求部门平均薪水的等级。
select deptno,avg_sal,grade from
(select deptno,avg(sal) avg_sal from emp group by deptno)t
join salgrade s on(t.avg_sal between s.losal and s.hisal)
B.求部门平均的薪水等级
select deptno,avg(grade) from
(select deptno,ename, grade from emp join salgrade s on(emp.sal between s.losal and
s.hisal)) t
group by deptno
C.那些人是经理
select ename from emp where empno in(select mgr from emp);
select ename from emp where empno in(select distinct mgr from emp);
D.不准用组函数,求薪水的最高值(面试题)
select distinct sal from emp where sal not in(
select distinct e1.sal from emp e1 join emp e2 on (e1.sal<e2.sal));
E.平均薪水最高的部门编号
select deptno,avg_sal from
(select avg(sal)avg_sal,deptno from emp group by deptno)
where avg_sal=
(select max(avg_sal)from
(select avg(sal) avg_sal,deptno from emp group by deptno)
)
F.平均薪水最高的部门名称
select dname from dept where deptno=
(
select deptno from
(select avg(sal)avg_sal,deptno from emp group by deptno)
where avg_sal=
(select max(avg_sal)from
(select avg(sal) avg_sal,deptno from emp group by deptno)
)
)
G.求平均薪水的等级最低的部门的部门名称
组函数嵌套
如:平均薪水最高的部门编号,可以E.更简单的方法如下:
select deptno,avg_sal from
(select avg(sal) avg_sal,deptno from emp group by deptno)
where avg_sal =
(select max(avg(sal)) from emp group by deptno)
组函数最多嵌套两层
分析:
首先求
1.平均薪水: select avg(sal) from group by deptno;
2.平均薪水等级: 把平均薪水当做一张表,需要和另外一张表连接salgrade
select deptno,grade avg_sal from
( select deptno,avg(sal) avg_sal from emp group by deptno) t
join salgrade s on(t.avg_sal between s.losal and s.hisal)
上面结果又可当成一张表。
DEPTNO GRADE AVG_SAL
-------- ------- ----------
30 3 1566.66667
20 4 2175
10 4 2916.66667
3.求上表平均等级最低值
select min(grade) from
(
select deptno,grade,avg_sal from
(select deptno,avg(sal) avg_sal from emp group by deptno)t
join salgrade s on(t.avg_sal between s.losal and s.hisa)
)
4.把最低值对应的2结果的那张表的对应那张表的deptno, 然后把2对应的表和另外一张表做连接。
select dname ,deptno,grade,avg_sal from
(
select deptno,grade,avg_sal from
(select deptno,avg(sal) avg_sal from emp group by deptno)t
join salgrade s on(t.avg_sal between s.losal and s.hisal)
) t1
join dept on (t1.deptno = dept.deptno)
where t1.grade =
(
select deptno,grade,avg_sal from
(select deptno,avg(sal) avg_sal from emp group by deptno) t
join salgrade s on(t.avg_sal between s.losal and s.hisal)
)
)
结果如下:
DNAME DEPTNO GRADE AVG_SAL
-------- ------- -------- --------
SALES 30 3 1566.6667
H: 视图(视图就是一张表,一个子查询)
G中语句有重复,可以用视图来简化。
给scott赋视图权限
conn sys/bjsxt as sysdba;
grant create table,create view to scott;
conn scott/tiger
创建视图:
create view v$_dept_avg-sal_info as
select deptno,grade,avg_sal from
( select deptno,avg(sal) avg_sal from emp group by deptno)t
join salgrade s on 9t.avg_sal between s.losal and s.hisal)
然后
select * from v$_dept_avg-sal_info
结果如下:
DEPTNO GRADE AVG_SAL
-------- ------- ----------
30 3 1566.66667
20 4 2175
10 4 2916.66667
然后G中查询可以简化成:
select dname,t1.deptno,grade,avg_sal from
v$_dept_avg-sal_info t1
join dept on9t1.deptno =dept.deptno)
where t1.grade=
(
select min(grade) from v$_dept_avg-sal_info t1
)
---------------------------------------------------------------------------------------
第28-29课:创建表:
constraint:后面添加约束
写字段后面属于字段约束 如名字和邮箱组合不能重复做不到
create table stu
(
id number(6) primary key, 主键约束 不能为空值
name varchar2(20) constraint stu_name_nn not null, 非空约束
sex number(1),
age number(3),
sdate date,
grade number(2) default 1,
class number(4) references class(id),外键约束
email varchar2(50) unique 唯一约束 但是插入空值没问题
)
或者
email varchar2(50) unique,
constraint stu_id_pk primary key(id), 主键约束
constraint stu_class_fk foreign key(本表字段名) references 外表名(外表字段名), 外键约束
constraint stu_name_email_uni unique(email,name) 表级约束 唯一约束
------------------------------------------------------------------------------------------
第30课: 修改表结构
alter table stu add(addr varchar2(100)); 添加字段
alter table stu modify(addr varchar2(150)); 修改字段
alter table stu drop(addr); 删除字段
alter table drop constraint(stu_class_fk); 删除约束条件
rollback; 数据恢复
alter table stu add constraint stu_class_fk foreign key(本表字段名) references class(id); 添加新的外键
drop table stu; 删除表
------------------------------------------------------------------------------------------
第32课: 数据字典表
desc user_tables; 查询用户下的表的字段
select table_name from user_tables; 查询表名
select view_name from user_views; 查询视图
select constraint_name,table_name from user_constraints; 查询约束
desc user_constraints; 约束描述查询
desc dictionary; 数据字典的名字和描述
select table_name from dictionary; 查询所有数据字典表
------------------------------------------------------------------------------------------
第33课:索引 视图
--------------------------------------------------------------------------------------
索引
create index idx_stu_email on stu(email,class)/stu(email); 创建索引(通过索引字段去查询,会效率高,但是插入修改时效率不高,反而会低)
drop index idx_stu_email; 删除索引
select index_name from user_indexes; 查询索引
加主键或者唯一约束 会自动建立出索引 如果是字段组合 会自动建立出组合索引
-------------------------------------------------------------------------------------
视图
select view_name from user_views; 查询视图
给scott赋视图创建权限
conn sys/bjsxt as sysdba;
grant create table,create view to scott;
conn scott/tiger
创建视图:
create view v$_dept_avg-sal_info as
select deptno,grade,avg_sal from
( select deptno,avg(sal) avg_sal from emp group by deptno)t
join salgrade s on 9t.avg_sal between s.losal and s.hisal)
然后
select * from v$_dept_avg-sal_info
drop view v$_dept_avg-sal_info; 删除视图
缺点: 如果表结构改了 视图也要修改 增加了维护
功能: 1 简化查询 2 查询某些信息(安全性)
必须有用的时候再去创建视图 视图一般只负责查询
---------------------------------------------------------------------------------------
第34课:自增
create sequence seq; 创建序列
select sequence seq; 查询序列
select seq.nextval from dual;
insert into article values(seq.nextval,'1','2');
drop sequence seq; 删除序列
---------------------------------------------------------------------------------------
第35课:三范式(实际问题实际分析)
1. 表要有主键
列不可分,也不能重复 如姓名 不需要分成姓和名 也不要将姓名和年龄组合为一个列 还有 比如有出生年月不需要再写年龄列 如果写了 就属于重复了
2. 不能存在部分依赖 比如 主键是学号和图书编号组合(2个以上) 那么姓名依赖与学号 那么就属于部分依赖
解决方法 建立第三张表 存学号和图书编号 但是不保存姓名图书名称等信息
3. 不能存在传递依赖 也就是 除主键以外其它字段全部依赖于主键
----------------------------------------------------------------------------------------
第38--46课:PLSQL
1. begin
dbms_output.put_line('HelloWorld!'); 相当于system.out.print();
end; 不打印
创建
set serveroutput on; 想打印要先启用
begin
dbms_output.put_line('HelloWorld!'); 相当于system.out.print();
end;
2. declare 定义变量
declare
v_name varchar2(20); 变量名用v_开头
begin
v_name := 'myname';
dbms_output.put_line(v_name);
end;
-----------------------------------------
declare
v_num number := 0; 变量名用v_开头
begin
v_num := 2/v_num;
dbms_output.put_line(v_num);
exception 异常处理
when others then
dbms_output.put_line('error');
end;
3.变量声明
declare
v_temp number(1);
v_count binary_integer := 0;
v_sal number(7,2) := 4000.00;
v_date date := sysdate;
v_pi constant number(3,2) := 3.14; constant 相当于 final 常量
v_valid boolean := false;
v_name varchar2(20) not null := 'MyName'; 不能取空值
begin
dbms_output.put_line('v_temp value:' || v_temp); || 字符串连接符
end;
dbms_output.put_line 不能打印boolean值 如果想判断用if else
---变量声明的规则
1. 变量名不能够使用保留字,如from select 等
2. 第一个字符必须是字母
3. 变量名最多包含30个字符
4. 不要与数据库的表或者列同名
5. 每一行只能声明一个变量
---常用变量类型
1. binary_integer: 整数,主要用来计数而不是用来表示字段类型
2. number:数字类型
3. char:定长字符串
4. varchar2:变长字符串
5. date:日期
6. long:长字符串,最长2GB
7. boolean:布尔类型,可以取值为true flase和null值(建议给个值 不要用Null)
---假如声明变量v_empno number(7,2) 如果表中修改了 那么声明也需要修改 如果想让声明的根据表中的自动修改 用如下命令:
---变量声明,使用%type属性
declare
v_empno number(4);
v_empno2 emp.empno%type; 1. 表名.字段名%type;
v_empno3 v_empno2%type; 2. 变量名%type;
begin
dbms_output.put_line('Test');
end;
4. 复合变量(Table变量类型(表示数组) Record变量类型(类似于java的类))
---Table变量类型
declare
关键字 类型名字type_table_ 类型 由binary_integer作为索引
type type_table_emp_empno is table of emp.empno%type index by binary_integer;
v_empnos type_table_emp_empno; 声明变量
begin
v_empnos(0) := 7369;
v_empnos(2) := 7839;
v_empnos(-1) := 9999;
dbms_output.put_line(v_empnos(-1));
end;
---Record变量类型
declare
type type_record_dept is record
(
deptno dept.deptno%type,
dname dept.dname%type,
loc dept.loc%type
);
v_temp type_record_dept;
begin
v_temp.deptno := 50;
v_temp.dname := 'aaa';
v_temp.loc := 'bj';
dbms_output.put_line(v_temp.deptno || ' ' || v_temp.dname);
end;
---如果用以上 那么表添加字段 上面需要跟着添加 如何使用表的字段自动创建 如下
---使用%rowtype声明record变量
declare
v_temp dept%rowtype;
begin
v_temp.deptno := 50;
v_temp.dname := '111';
v_temp.loc := 'bj';
dbms_output.put_line(v_temp.deptno || ' ' || v_temp.dname);
end;
5.PL SQL中使用sql
--------------------select---------------------
declare
v_ename emp.ename%type;
v_sal emp.sal%type;
begin;
select ename,sal into v_ename,v_sal from emp where empno=7369;
dbms_output.put_line(v_ename || ' ' || v_sal);
end;
在plsql中 如果使用select,必须返回一条记录,并且只能返回一条记录,select里面必须有into
---plsql中使用%rowtype
declare
v_emp emp%rowtype;
begin;
select * into v_emp from emp where empno=7369;
dbms_output.put_line(v_emp.ename);
end;
-------------------insert into-----------------------
declare
v_deptno dept.deptno%type := 50;
v_dname dept.dname%type := 'aaa';
v_loc dept.loc%type := 'bj';
begin
insert into dept2 values(v_deptno,v_dname,v_loc);
commit;
end;
------------------update------------------------------
declare
v_deptno emp.deptno%type := 50;
v_count number;
begin
update emp set sal = sal/2 where deptno = v_deptno;
select deptno into v_deptno from emp where empno = 7369;有一条被影响
select count(*) into v_count from emp; 也是一条记录被影响
dbms_output.put_line(sql%rowcount || '条记录被影响');查询影响行数 sql为关键字
commit;
end;
6.ddl
begin
固定说明马上执行 这是两个单引号
execute immediate 'create table T(nnn varchar2(20) default ''aaa'')';
end;
------------------------if---------------------------
---取出7369的薪水,如果<1200,则输出'low',如果<2000则输出'middle',否则输出'high'
declare
v_sal emp.sal%type;
begin
select sal into v_sal from emp where empno=7369;
if(v_sal < 1200) then
dbms_output.put_line('low');
elsif(v_sal < 2000) then elsif 要看清。。
dbms_output.put_line('middle');
else
dbms_output.put_line('high');
end if;
end;
-----------------------循环--------------------------
1. 相当于java do while
declare
i binary_integer := 1;
begin
loop
dbms_output.put_line(i);
i := i + 1;
exit when(i >= 11);
end loop;
end;
2. 相当于java while
declare
j binary_integer := 1;
begin
while j<11 loop
dbms_output.put_line(j);
j := j + 1;
end loop;
end;
3.
begin
for k in 1..10 loop
dbms_output.put_line(k); 打印1---10
end loop;
for k int reverse 1..10 loop
dbms_output.put_line(k); 打印 10---1
end loop;
end;
--------------------------------
7.错误处理
declare
v_emp number(4);
begin
select empno into v_temp from emp where deptno = 10;
exception
when too_many_rows then
dbms_output.put_line('有太多记录');
when others then
dbms_output.put_line('error');
end;
declare
v_temp number(4);
begin
select empno into v_temp from emp where empno = 222;
exception
when no_data_found then
dbms_output.put_line('没数据');
end;
-----------利用异常表-----------
---创建异常表
create table errorlog
(
id number primary key,
errcode number,
errmsg varchar2(1024),
errdate date
);
----创建序列
create sequence seq_errorlog_id start with 1 increment by 1;
---异常使用异常表
declare
v_deptno dept.deptno%type := 10;
v_errcode number;
v_errmsg varchar2(1024);
begin
delete from dept where deptno = v_deptno;
commit;
exception
when others then
rollback; 事务回滚
v_errcode := SQLCODE;
v_errmsg := SQLERRM;
insert into errorlog values(seq_errorlog_id.nextval,v_errcode,v_errmsg,sysdate);
commit;
end;
----查询异常 异常编号都是负数
select * from errorlog;
----查询日期
select to_char(errdate,'YYYY-MM-DD HH24:M1:SS') from errorlog;
---------------------------------------游标-----------------------------------------------
----第47--48课
--游标
declare
cursor c is
select * from emp;
v_emp c%rowtype;
begin
open c;
fetch c into v_emp;
dbms_output.put_line(v_emp.ename);
close c;
end;
---loop循环
declare
cursor c is
select * from emp;
v_emp c%rowtype;
begin
open c;
loop
fetch c into v_emp;
exit when (c%notfound);
dbms_output.put_line(v_emp.ename);
end loop;
close c;
end;
---while循环
declare
cursor c is
select * from emp;
v_emp emp%rowtype;
begin
open c;
fetch c into v_emp;
while(c%fond) loop
dbms_output.put_line(v_emp.ename);
fetch c into v_emp;
end loop;
close c;
end;
--for循环
declare
cursor c is
select * from emp;
begin
for v_emp in c loop
dbms_output.put_line(v_emp.ename);
end loop;
end
--带参数的游标
declare
cursor c(v_deptno emp.deptno%type, v_job emp.job%type)
is
select ename,sal from emp where deptno = v_deptno and job = v_job;
begin
for v_temp in c(30,'CLERK') loop
dbms_output.put_line(v_temp.ename);
end loop;
end;
--可更新的游标
declare
cursor c
is
select * from emp2 for update;
begin
for v_temp in c loop
if(v_temp.sal < 2000) then
update emp2 set sal = sal*2 where current of c;
elsif(v_temp.sal = 5000) then
delete from emp2 where current of c;
end if;
end loop;
commit;
end;
PL/SQL中用游标查询多条记录
PL/SQL游标为程序提供了从数据库中选择多行数据,然后对每行数据单独进行处理的方法,它为Oracle提供了一种指示和控制SQL处理的各个阶段的方法。我将认为您已经对PL/SQL有一定的了解。通过本文,您将学会:
游标的创建
游标的处理
定义和使用游标属性
一、 什么是游标
Oracle使用两种游标:显式游标和隐式游标。不管语句返回多少条纪录,PL/SQL为使用的每一条UPDATE、DELETE和INSERT等SQL命令隐式的声明一个游标。(要管理SQL语句的处理,必须隐式的 给它定义一个游标。)用户声明并使用显示游标处理SELECT语句返回的多条记录。显示的定义游标一种结构,它使用户能够为特定的语句指定内存区域,以便以后使用。
二、 游标的作用
当PL/SQL游标查询返回多行数据时,这些记录组被称为活动集。Oracle将这种活动集存储在您创建的显示定义的已命名的游标中。Oracle游标是一种用于轻松的处理多行数据的机制,没有游标,Oracle开发人员必须单独地、显式地取回并管理游标查询选择的每一条记录。
游标的另一项功能事,它包含一个跟踪当前访问的记录的指针,这使您的程序能够一次处理多条记录。
三、 使用显示游标的基本方法
步骤如下:
声明游标
打开游标
从游标中取回数据
关闭游标
1、声明游标
声明游标的语法如下:
DECLARE cursor_name
Is
SELECT statement
其中,cursor_name是您给游标指定的名称;SELECT statement是给游标活动集返回记录的查询。
声明游标完成了下面两个目的:
给游标命名;
将一个查询与游标关联起来。
值得注意的是,必须在PL/SQL块的声明部分声明游标;给游标指定的名称是一个未声明的标识符,而不是一个PL/SQL变量,不能给游标名称赋值,也不能将它用在表达式中。PL/SQL块使用这个名称来引用游标查询。
例:DECLARE
CURSOR c1
Is
SELECT VIEW_NAME FROM ALL_VIEWS
WHERE ROWNUM<=10;
另外还可以在游标定义语句中声明游标的参数,例:
CURSOR c1(view _nbr number)
Is
SELECT VIEW_NAME FROM ALL_VIEWS
WHERE ROWNUM<= view _nbr;
游标参数只对相应的游标是可见的,不能在游标范围之外引用该游标的参数。如果试图这样做,Oracle将返回一个错误,指出该变量没有定义。
2、打开游标
打开游标的语法如下:
OPEN cursor_name;
其中cursor_name是您以前定义的游标名称。
打开游标将激活查询并识别活动集,可是在执行游标取回命令之前,并没有真正取回记录。OPEN命令还初始化了游标指针,使其指向活动集的第一条记录。游标被打开后,直到关闭之前,取回到活动集的所有数据都是静态的,换句话说,游标忽略所有在游标打开之后,对数据执行的SQL DML命令(INSERT、UPDATE、DELETE和SELECT)。因此只有在需要时才打开它,要刷新活动集,只需关闭并重新打开游标即可。
3、从游标中取回数据
FETCH命令以每次一条记录的方式取回活动集中的记录。通常将FETCH命令和某种迭代处理结合起来使用,在迭代处理中,FETCH命令每执行一次,游标前进到活动集的下一条记录。
FETCH命令的语法:
FETCH cursor_name INTO record_list;
其中,cursor_name是前面定义的游标的名称;record_list是变量列表,它接受活动集中的列。FETCH命令将活动集的结果放置到这些变量中。
执行FETCH命令后,活动集中的结果被取回到PL/SQL变量中,以便在PL/SQL块中使用。每取回一条记录,游标的指针就移向活动集的下一条记录。
例:
FETCH C1 INTO VNAME;
WHILE C1%FOUND LOOP
DBMS_OUTPUT.PUT_LINE(TO_CHAR(C1%ROWCOUNT)||' '||VNAME);
END LOOP;
其中,使用属性'%FOUND'使得当FETCH到达活动集的结尾时,不会引发异常。其它属性及含义见下表:
属性 含量
%FOUND 布尔型属性,当最近一次该记录时成功返回,则值为TRUE
%NOTFOUND 布尔型属性,它的值总与%FOUND属性的值相反
%ISOPEN 布尔型属性,当游标是打开时返回TRUE
%ROWCOUNT 数字型属性,返回已从游标中读取的记录数
属性 含量
%FOUND 布尔型属性,当最近一次该记录时成功返回,则值为TRUE
%NOTFOUND 布尔型属性,它的值总与%FOUND属性的值相反
%ISOPEN 布尔型属性,当游标是打开时返回TRUE
%ROWCOUNT 数字型属性,返回已从游标中读取的记录数
4、关闭游标
CLOSE语句关闭以前打开的游标,使得活动集不确定。当用户的程序或会话结束时,Oracle隐式关闭游标。游标被关闭后,就不能对它执行任何操作了,否则将引发异常。
CLOSE语句的语法是:
CLOSE cursor_name;
其中,cursor_name是以前打开的游标的名称。
完整的程序代码如下:
DECLARE
CURSOR C1 IS SELECT VIEW_NAME FROM ALL_VIEWS
WHERE ROWNUM<=10
ORDER BY VIEW_NAME;
VNAME VARCHAR2(40);
BEGIN
OPEN C1;
FETCH C1 INTO VNAME;
WHILE C1%FOUND LOOP
DBMS_OUTPUT.PUT_LINE(TO_CHAR(C1%ROWCOUNT)||''||VNAME);
END LOOP;
END;
……CLOSE C1;
四、 小结
游标是一种结构,能够以一次一条记录的方式处理多行查询的结果.为每条DML语句创建隐式游标,而显式游标是由用户创建的,以便处理返回多条记录的查询。而且,通过消除反复地分析代码,游标提高了代码的处理速度。
------------------------------存储过程---------------------------------
---第49--50课
--创建存储过程 执行如果有错误会提示 创建的存储过程带有编译错误 但是不提示哪有错误
如果想查看 执行show error即可
create or replace procedure p ---这里相当于declare
is
cursor c
is
select * from emp2 for update;
begin
for v_temp in c loop
if(v_temp.sal < 2000) then
update emp2 set sal = sal*2 where current of c;
elsif(v_temp.sal = 5000) then
delete from emp2 where current of c;
end if;
end loop;
commit;
end;
select * from emp2;
---执行存储过程
begin
p;
end;
exec p; ---执行存储过程
---带参数的存储过程
---创建存储过程
create or replace procedure p
(v_a in number, v_b number, v_ret out number, v_temp in out number)
---第一个为传入参数 第三个为传出参数 第四个为传入传出参数
is
begin
if(v_a>v_b) then
v_ret := v_a;
else
v_ret := v_b;
end if;
v_temp := v_temp + 1;
end;
--定义变量
declare
v_a number := 3;
v_b number := 4;
v_ret number;
v_temp number := 5;
---执行存储过程
begin
p(v_a,v_b,v_ret,v_temp);
dbms_output.put_line(v_ret);
dbms_output.put_line(v_temp);
--函数
---创建函数
create or replace function sal_tax
(v_sal number)
return number
is
begin
if(v_sal < 2000) then
return 0.10;
elsif(v_sal < 2750) then
return 0.15;
else
return 0.20;
end if;
end;
--执行函数
select sal_tax(sal) from emp;
----------------------触发器----------------
create table emp2)log
(
uname varchar2(20),
action varchar2(10),
atime date
);
---创建触发器
create or replace trigger trig
after insert or delete or update on emp2 for each row
begin
if inserting then
insert into emp2_log values(USER,'insert',sysdate);
elsif updating then
insert into emp2_log values(USER,'update',sysdate);
elsif deleting then
insert into emp2_log values(USER,'delete',sysdate);
end if;
end;
---删除触发器
drop trigger trig;
create or replace trigger trig
after update on dept
for each row
begin
update emp set deptno = :NEW.deptno where deptno = :OLD.deptno;
end;
--有了这个触发器 就可以执行 update emp set deptno=10 where deptno=99; 先出发触发器才检查约束条件
select * from emp;
rollback;
------------树状结构展示------------
---第52---53课
drop table article;
create table article
(
id number primary key,
cont varchar2(4000),
pid number,
isleaf number(1),--0代表非叶子节点,1代表叶子节点
alevel number(2)
);
insert into article values(1,'蚂蚁大战大象',0,0,0);
insert into article values(2,'大象被打趴下了',1,0,1);
insert into article values(3,'蚂蚁也不好过',2,1,2);
insert into article values(4,'瞎说',2,0,2);
insert into article values(5,'没有瞎说',4,1,3);
insert into article values(6,'怎么可能',1,0,1);
insert into article values(7,'怎么没有可能',6,1,2);
insert into article values(8,'可能性是很大的',6,1,2);
insert into article values(9,'大象进医院了',2,0,2);
insert into article values(10,'护士是蚂蚁',9,1,3);
commit;
蚂蚁大战大象
大象被打趴下了
蚂蚁也不好过
瞎说
没有瞎说
大象进医院了
护士是蚂蚁
怎么可能
怎么没有可能
可能性是很大的
----------------使用存储过程展示树状结构-------------
create or replace procedure p (v_pid article.pid%type) is
cursor c is select * from article where pid = v_pid;
begin
for v_article in c loop
dbms_output.put_line(v_article.cont);
if(v_article.isleaf = 0) then
p (v_article.id);
end if;
end loop;
end;
---以上写法 顺序会输出正确 但是没有缩进
create or replace procedure p (v_pid article.pid%type, v_level binary_integer) is
cursor c is select * from article where pid = v_pid;
v_preStr varchar2(1024) := '';
begin
for i in 1..v_level loop
v_preStr := v_preStr || '*****'; ----如果使用空格 貌似会自动消除
end loop;
for v_article in c loop
dbms_output.put_line(v_preStr || v_article.cont);
if(v_article.isleaf = 0) then
p (v_article.id, v_level + 1);
end if;
end loop;
end;
---以上写法可以实现缩进
oracle-个人学习笔记
最新推荐文章于 2023-04-20 15:17:11 发布