您的位置:首页 > 数据库 > Oracle

Oracle之索引/视图/游标及PL/SQL编程

2017-07-20 16:03 337 查看
1. 索引:在查询时数据库自动定位到该索引处进行查找,大大提高了查询效率
对于大型表可提高查询效率,数据量小的表不建议用
创建索引语法:create index 索引名 on 表名(列名1,列名2,...);
  create index idx on t1(id);
  select * from t1 where id = 100; //查询时自动定位到该索引idx处
创建序列语法:create sequence s1;//创建序列,常用于整形id自增长
  s1.nextval;//序列的下一个值
  s1.currval;//序列的当前值
2. 视图:封装了一条select 语句,本质上就是保存在数据字典中的一条sql语句
创建视图语法:create view 视图名 as select 语句 [with read only|with check option]
create view v1 as select ename,empno from emp;

可选项说明:
  with read only:只读,不可对该视图进行修改
create view v1 as select ename,empno from emp with read only;
  with check option:检查SQL查询条件选项,避免不合法数据出现(不加该句则不满足视图封装的sql查询语句条件也可查询到)
create view v2 as select ename,empno from emp where empno>7700;
create view v3 as select ename,empno from emp where empno>7700 with check option;
表与视图区别:
  1.表占内存和磁盘空间,而视图只是一个封装了sql语句的对象
  2.视图可以提高数据安全性,而表没有
  3.通过视图可以把一些复杂的语句简单化
  4.视图不可使用索引
3. pl/sql编程:是一种面向过程的sql语言(procedural language/sql),oracle对sql的扩展
  1.block(块):是pl/sql编程的基本单位
  该语言由三部分组成:
    1.声明部分(declare开头)--可选
    2.执行部分(以begin开头)---必须有
    3.异常处理部分(以exception开头)--可选
  2.语法
declare
  //定义变量,定义函数,定义游标
begin
 //执行sqsl语句或pl/sql语句
exception
  //处理异常错误
  3.变量
  变量名 数据类型
  给变量赋值要放在执行部分
  若要看到打印信息,要执行:set serveroutput on;
declare
name varchar2(20):='hehe';--定义并初始化
begin
dbms_output.put_line(name);
end;
  4.select 赋值
declare
  name varchar(20);
  num number(20);
begin
  select ename,empno into name,num from emp where empno=7782;
  dbms_output.put_line(name);
end;
练习:
根据输入的员工的编号(提示select ...where empno=&i;),查询出员工的姓名,工资,工作,并把这三项信息通过pls/sql输出。
declare
name varchar(20);
sal number(20);
job varchar(20);
begin
select ename,sal,job into name,sal,job from emp where empno=&i;
dbms_output.put_line(name||'--'||sal||'--'||job);
end;
  5.insert,update,delete
declare
d_no number(2);
d_name varchar2(20);
d_loc varchar2(20);
begin
insert into dept values(90,'developing','南京')
--把影响的行数据传递给变量
returning deptno,dname,loc into d_no,d_name,d_loc;
dbms_output.put_line(d_name||'--'||d_no||'--'||d_loc);
end;
  6.复合数据类型
    1.记录类型
type 记录类型名 is record(
v1 类型,
v2 类型,
...
vn 类型
);
变量名 记录类型名
示例:
declare
type dept_rc is record(
d_no number(2),
d_name varchar(20),
d_loc varchar(20)
);
v1 dept_rc;//变量名 记录类型名;
begin
delete from dept where deptno = 90
returning deptno,dname,loc into v1;
dbms_output.put_line(v1.d_name||'--'||v1.d_no||'--'||v1.d_loc);
end;
    2.数组类型
语法:
type 名字 is varrray(长度) of 元素类型;
定义数组变量
变量名 数组类型名;
初始化数组:
变量名:=数组类型名(v1,v2,v3...);
数组的属性:
变量名.first--数组下标的最小值,1
变量名.last--下标最大值
示例:
declare
type num_arr is varray(3) of number(2);
v num_arr;
begin
v:=num_arr(10,20,5);
dbms_output.put_line(v(1)||'--'||v(2)||'--'||v(3));
end;
练习:定义3个元素的数组,存放三个城市名
    3.%type类型
定义变量语法:
变量名 表名.字段名%type;
示例:
declare
v emp.ename%type;
begin
select ename into v from emp where empno=7788;
dbms_output.put_line(v);
end;
    4.%rowtype类型(行变量)
语法
变量名 表名%rowtype;
示例:
declare
v dept%rowtype;
begin
insert into dept values(99,'研发','北京')
returning deptno,dname,loc into v;
dbms_output.put_line(v.deptno||'--'||v.dname||'--'||v.loc);
end;
  条件语句:
    1.if语句
语法:
if 条件 then 语句1;
....
elsif 条件 then 语句二2;
...
else 语句3;
...
end if;
练习1:输入员工工号,查询出员工的工资,如果工资小于1500打印出:太少了,如果工资小于5000,大于1500打印:一般,其他显示:工资很高。
declare
v emp.sal%type;
msg varchar2(20);
begin
select sal into v from emp where empno=&no;
if v<1500 then 
msg:='工资太少,加点儿吧';
elsif v between 1500 and 5000 then
msg:='一般';
else
msg:='很高';
end if;
dbms_output.put_line(v||'--'||msg);
end;
练习2:输入工员,查询员工的姓名,入职日期,如果晚于1988-1-1,输出其奖金为:1600,晚于1990-1-1,输出奖金800,其他情况输出奖金:2400,最后输出员工的姓名,入职日期,奖金。
declare
v emp%rowtype;
bonus number(7,2);
begin
select * into v from emp where empno=&no;
if v.hiredate > to_date('1990-01-01','yyyy/mm/dd') then
bonus:=800;
elsif v.hiredate  > to_date('1988-01-01','yyyy/mm/dd') then 
bonus:=1600;
else
bonus:=2400;
end if;
dbms_output.put_line(v.ename||'--'||v.hiredate||'--'||bonus);
end;
    2.case语句
switch(表达式)
case 1:
..
语法一:
case 表达式;
when 结果1 then 语句1; 
...
when 结果2 then 语句2;
...
[else ....]
end case;
语法二:
case when 条件1 then 语句1;
...
when 条件2 then 语句2;
...
[else ....]
end case;
示例:
1.输入成绩(字符),是A则输出excellen,B则输出:verygood,C输出:good,其他输出:不合格 。
declare
v char(1):='&c';
msg varchar2(30);
begin
case v when 'A' then
msg:='excellen';
when 'B' then
msg:='verygood';
when 'C' then
msg:='good';
else
msg:='不合格';
end case;
dbms_output.put_line(msg);
end;
2.输入一个数字,大于90输出优秀,大于80输出良,大于70输出中,其他及格或差。
declare
v number:=&score;
msg varchar2(30);
begin
case when v>=90 then
msg:='优秀';
when v>=80 then
msg:='良';
when v>=70 then
msg:='中';
else
msg:='不合格';
end case;
dbms_output.put_line(msg);
end;
  循环语句:
    1.loop循环,相当于java do while
语法:
loop
 ....
 [exit;]--相当于break;
 [exit when 条件;]
end loop;
示例:
declare
begin
loop
dbms_output.put_line('哈哈');
end loop;
end;
练习:打印出1到10的值。
declare
v number(2):=1;
begin
loop
dbms_output.put_line(v);
v:=v+1;
exit when v>10;
end loop;
end;
    2.while循环
语法:
while 条件 loop
.....
end loop;
1...10的实现?
    3.for循环
语法:
for 变量名 in[reverse] 最小值..最大值
loop
....
end loop;
说明:
  1.变量名:就是一个名称,无需定义
  2.每次循环自动加1或减1
  3.reverse表示是从小到大取值还是从大到小取值
begin
for v in 1..10
loop
dbms_output.put_line(v);
end loop;
end;

begin
for v in reverse 1..10
loop
dbms_output.put_line(v);
end loop;
end;
练习:
1.创建一张表,先向表中插入一条数据10,然后用for循环插入20..30数据,该循环要执行两次。
declare 
v number(2):=10;
begin
insert into nums values(v);
for v in 1..2 loop
for v1 in 20..30 loop
insert into nums values(v1);
end loop;
end loop;
end;
2.定义一个数组,内容为'SALESMAN','CLERK',MANAGER','PRESIDENT''ANALYST'用循环针对数组中的每个工作岗位,求出 
 每个岗位的员工人数,最后输出工作及人数。
declare
type job_arr is varray(5) of varchar2(30);
arr job_arr;
v number(2);
begin
arr:=job_arr('SALESMAN','CLERK','MANAGER','PRESIDENT','ANALYST');
for v_i in arr.first..arr.last loop
select count(*) into v from emp where job=arr(v_i);
dbms_output.put_line(arr(v_i)||'--'||v);
end loop;
end;
4.游标:游标是个指标,指向一个查询结果集
  1.显式游标
    1.使用步骤:
1.声明一个游标:cursor 游标名 is select 语句;
2.打开游标:open 游标名;  //只能打开一次
3.提取游标中数据:fetch 游标名 into 变量(记录类型);
4.关闭游标:close 游标名;
2.游标的属性:
1.found:select into游标位置是否有数据,如果有返回true对于DML语句判断是否改变了行
2. notfound:!found,如果有数据,返回false,没有返回true
3. isopen:判断是否打开了游标
4.rowcount:对于select语句表示访问到了游标中的第几行dml语句表示影响的行数
如何使用属性:游标名%属性;
练习:用loop循环实现查询emp中部门为10的员工工号,姓名,工资,
1.loop循环的使用
declare
cursor c1 is select * from emp where deptno=10;
v emp%rowtype;
begin
open c1;
loop
fetch c1 into v;
exit when c1%notfound;
dbms_output.put_line(c1%rowcount||'--'||v.empno||'--'||v.ename||'--'||v.sal);
end loop;
close c1;
end;
2.用while循环实现上面功能
declare
cursor c1 is select * from emp where deptno=10;
v emp%rowtype;
begin
open c1;
fetch c1 into v;
while c1%found loop
dbms_output.put_line(c1%rowcount||'--'||v.empno||'--'||v.ename||'--'||v.sal);
fetch c1 into v;
end loop;
close c1;
end;
    3.游标的for循环
语法:for 变量名 in 游标名 loop
....
end loop;
特点:隐藏了打开游标、fetch操作、检测游标属性、关闭
示例:
declare
cursor c1 is select * from dept;
begin
for v in c1 loop
dbms_output.put_line(v.deptno||'--'||v.dname||'--'||v.loc);
end loop;
end;
练习:查询emp表前10条记录的姓名
declare
curson c is select * from emp where rownum<=10;
begin
for v in c loop
dbms_output.put_line(v.ename);
end loop;
end;

declare
cursor c is select * from emp;
begin
for v in c loop
if c%rowcount<=10 then
dbms_output.put_line(v.ename);
else
exit;
end if;
end loop;
end;
4.带参数的游标
语法:cursor 游标名 (形参名 参数类型,...) is select 语句---参数类型不能跟范围
declare
cursor c(spno number,spjob varchar2) 
is select * from emp where deptno=spno and job=spjob;
v emp%rowtype;
begin
open c(30,'SALESMAN');
loop
fetch c into v;
exit when c%notfound;
dbms_output.put_line(v.ename);
end loop;
close c;
end;
for的实现:
declare
cursor c(spno number,spjob varchar2) 
is select * from emp where deptno=spno and job=spjob;
begin
for v in c(30,'SALESMAN')
loop
dbms_output.put_line(v.ename);
end loop;
end;
2.隐式游标:系统自动定义,适用于insert,update,delete操作,使用时只能通过其属性完成相应操作,名字叫sql,
属性:
found
notfound
isopen
rowcount
示例:
begin
--insert into emp(empno,ename) values(6000,'abc123');
dbms_output.put_line(sql%rowcount);
delete from emp where ename='abc123';
dbms_output.put_line(sql%rowcount);
if sql%notfound then
dbms_output.put_line('aaa');
end if;
end;
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: