Oracle中的视图
在Oracle数据库中视图是数据库中特有的对象。视图主要用于数据查询,它不会存储数据(物化视图除外)。这是视图和数据表的重要区别。
视图的数据来源于一个或等多个表中的数据,可以利用视图进行查询、插入、更新和删除数据,操作视图就是间接操作数据库表。
通常情况下,视图主要用于查询,不提倡通过视图而更新与视图相关的表,因为视图中的数据只是一个或多个表中的局部数据。
关系视图
关系视图是四种视图中比较简单和常用的视图。可以将关系视图看做对简单或复杂查询的定义。它的输出可以看作一个虚拟的表,该表的数据是由其它基础数据表提供的。由于关系视图并不存储真正的数据,因此占用数据库资源也较少
create or replace view view_name AS select 表or其他视图......
create or replace view view_communic_address AS select email,address,tel from students;
select * from view_communic_address --查询视图
提示:视图中的数据来源于实际的物理表,修改视图中的数据实际就是更改视图数据的来源表,在通常情况下不提倡通过视图修改数据;
只读关系视图
只读视图单一提供数据的查询
create or replace view vw_employees AS
select employee_id,employee_name,employee_position,employee_age
from employees
with read only;
Drop View 视图名称;--删除视图对象
内嵌视图
内嵌视图是非存在于Oracle数据库中的对象,它只是查询过程中生成的结果数据集;内嵌视图通常以子查询的方式出现在SQL操作中。
内嵌视图通常对于数据库的开销有更大的优势,可以适当使用。
内嵌视图的创建不使用create关键字创建,通常在查询语句中创建内嵌视图,在执行完sql操作后,内嵌视图自动销毁。
物化视图
物化视图也叫快照,物化视图和表一样生成物理文件并占用磁盘空间,对于数据库及磁盘空间都有一定的开销维护,在物化视图上可以像普通表一样创建索引。
Create materializedview 视图名称AS Select * from 表名
PL/SQL编程
PL/SQL是过程化SQL语言(Procedural Language/SQL)。
PL/SQL是对SQL语句的扩展,增加了编程语言的特点,所以PL/SQL就是把数据操作和查询语句组织在PL/SQL代码的过程性单元中,通过逻辑判断、循环等操作实现复杂的功能,在定义复杂业务的函数、过程及建立触发器时使用。
PL/SQL中通常只能使用数据DML(数据操纵)语音和DCL(数据控制)语言,诸如:insert、update、select into、delete、commit、rollback、savepoint。不允许使用DDL(数据定义)语言 create、drop、alter......
PL/SQL块的组成结构
DECLARE --声明单元(可选)
变量1 类型[(长度)];
变量2 类型[(长度)];
BEGIN --执行单元(必须)
数据处理语句;
exception --异常处理单元(可选)
异常处理语句;
END;
声明单元
PLSQL使用DDECLARE关键字声明变量定义,此单元必须在PLSQL的最前面。
l 通常变量名称可以包括字母、下划线、数字、#、$
l 变量名称不能超过30个字符
l 第一个字符必须是字母
l 不区分大小写
l 不能使用任何关键字
declare
name varchar(24);--声明变量
age int:=25;--声明变量并赋默认值
address String(64);--声明编程类型变量
PL SQL编程变量类型
l char定长字符类型,包括子类character、string、rowid、Nchar最长限制在2000个字符
l varchar2可变字符类型,包括子类varchar、string、nvarchar2最长限制在4000个字符
l number(p,s) 值类型,包括子类int、integer、smallint、dec、double
l date 日期型
l boolean 布尔类型
l %type 复合类型变量
l %rowtype 行符合类型变量
%rowtype自定义符合类型
%rowtype是%type类型的扩展,可存储查询返回数表的一个未知列数量及类型的功能,使用更加方便
declare
R_var student% rowtype;
begin
select * into R_var from students where id=’stu001’;
dbms_output.put_line(R_var.name);
end;
PL SQL逻辑控制语句
IF Else基本逻辑语句if可以单独使用,Else必须结合if使用
Elsif 等价于java的else if语句
Case when 类似于Java的Switch Case
if 布尔表达式 then 满足if执行的语句;
elsif 布尔表达式 then 满足if执行的语句;
else对应else执行的语句;
end if;
case
when布尔表达式then执行语句;
when布尔表达式then执行语句;
else 执行语句;
end case;
loop循环
loop
[业务处理语句;] [exit;]--退出循环
endloop;
while循环
while布尔表达式loop
[业务处理语句;] [循环变量更新;]
endloop;
for循环
for in1..5 loop
[业务处理语句;]
endloop;
-- 创建关系视图 create or replace view view_emp_tab_salary AS select e.NAME,s.grantdate,s.should,s.actual from emp_tab e inner join salary s on e.ID = s.emp_id; select * from view_emp_tab_salary; --查询视图 update view_emp_tab_salary SET NAME='任我行' WHERE NAME='张敏'; --不允许修改 update view_emp_tab_salary SET should=should+50 WHERE NAME='任我行'; --不允许修改 select * from salary; --创建只读关系视图 create view view_dep_emp as select d.id,d.NAME dname,e.NAME ename from dep_table d inner join emp_tab e on d.id = e.dep_id with read only select * from view_dep_emp --更改只读视图的数据(会导致系统报错) update view_dep_emp set ename = '火云邪神' where ename = '张无忌'; select * from emp_tab; -- PL SQL declare name string(64); age int:=17;--初始化默认值 BEGIN NAME:='白无瑕'; age:=age+1; dbms_output.put_line('此人的名字是 '||name); END; --使用自定义符合类型%rowtype映射数据行 select * from emp_tab; DECLARE row_emp emp_tab%ROWTYPE; id_ STRING(64):='NO003'; BEGIN select * into row_emp from emp_tab where id = id_; dbms_output.put_line(row_emp.ID); dbms_output.put_line(row_emp.NAME); dbms_output.put_line(row_emp.address); dbms_output.put_line(row_emp.age); END; -- if 逻辑判断语句 declare age int:=16; message string(64):='是成年人'; message2 string(31):='是未成年人'; begin if age >= 18 then dbms_output.put_line(message); else dbms_output.put_line(message2); end if; end; -- if elsif 语句 declare score number :=-2; begin if (score >= 0 and score <= 100) then if score>=90 then dbms_output.put_line('优秀'); elsif score >=80 then dbms_output.put_line('良好'); elsif score >=70 then dbms_output.put_line('中等'); elsif score >=60 then dbms_output.put_line('及格'); else dbms_output.put_line('不及格'); end if; else dbms_output.put_line('成绩非法必须在0-100之间'); end if; end; --case when 分支语句 declare score number :=70; begin if (score >= 0 and score <= 100) then case when score>=90 then dbms_output.put_line('优秀★★★★★'); when score>=80 then dbms_output.put_line('良好★★★★'); when score>=70 then dbms_output.put_line('中等★★★'); when score>=90 then dbms_output.put_line('及格★★'); else dbms_output.put_line('不及格★'); end case; else dbms_output.put_line('成绩非法必须在0-100之间'); end if; end; -- PL SQL 循环 --基本loop 循环 --判断及统计1到100之间有多少个能被3整除的数 declare num int:=1; counts int:=0; BEGIN LOOP if (num>100)then exit;--退出循环 end if; if(num MOD 3 = 0)THEN counts:=counts+1; dbms_output.put_line(num); END IF; num:=num+1; END LOOP; dbms_output.put_line('1到100之间能够被3整除的数一共有 '||to_char(counts)); END; --使用while循环完成1到100之间累加和的计算 declare num INT:=1; sums int:=0; BEGIN while(num <=100) LOOP sums:=sums+num;--计算累加和 num:=num+1; END LOOP; dbms_output.put_line('1到100之间整数的累加和是:'||to_char(sums)); END; --使用for循环计算1到100之间的偶数和 DECLARE num INT:=1; sums INT:=0; BEGIN FOR i IN 1..100 LOOP if(num MOD 2=0)THEN sums:=sums+num;--统计偶数的累加和 END IF; num:=num+1;--变量自增 END LOOP; dbms_output.put_line('1到100之间所有偶数的累加和是 '||to_char(sums)); END;
--1 使用SQL语句建立关系型视图,视图数据来源于department和emp表,包含部门名称,员工姓名,地址,电话和邮箱号码; create or replace view view_department_emp as select d.name 部门名称,e.name 员工姓名,e.address 地址,e.phone 电话,e.email 邮箱号码 from dept d inner join emp e on d.id = e.depid select * from view_department_emp; /*2 连接department和emp表和sales表创建关系型只读视图,要求包含,部门名称,员工姓名,产品代码, 销售数量,销售单价,销售日期并未视图创建列别名*/ create view view_dept_emp_sales as select d.name 部门名称,e.name 员工姓名,s.id 产品代码,s.salquantity 销售数量,s.price 销售单价, to_char(s.saldate,'yyyy-MM-dd') 销售日期 from (dept d inner join emp e on d.id = e.depid)inner join sales s on s.eid = e.id with read only select * from view_dept_emp_sales /*1 定义一段PL SQL 块,声明2个值类型变量,分别用来存储销售部和研发部们员工数量, 利用sql查询获取销售部和研发部们的员工数量并储存在2个变量中,对人数进行比较, 最后在输出窗口显示2个部门的人数差,必需是正数;*/ select * from emp; select * from dept; declare sales_department number; develop_department number; results number; BEGIN select count(DEPID) into sales_department from emp where depid = 'NO300'; select count(DEPID) into develop_department from emp where depid = 'NO200'; dbms_output.put_line('销售部人数 '||sales_department); dbms_output.put_line('研发部人数 '||develop_department); select abs(sales_department-develop_department) into results from dual; dbms_output.put_line('部门人数差 '||results); END; /*2 定义一段PL SQL 块,声明类型为number类型的变量用来存储emp表的某个id值; 声明定义一个自定义%type类型的变量及描述用来封装存储department表部门名称, emp表员工姓名,emp表员工地址,emp表员工生日, inner join 内连接查询emp 和 department表,限制条件时emp表id等于以上number类型的变量值,查询储department表部门名称, emp表员工姓名,emp表员工地址,emp表员工生日字段为自定义%type类型进行赋值,在输出窗口输出 4个字段的获取后信息。*/ declare zengyu varchar2(64):='671'; row_emp emp%ROWTYPE; BEGIN select * into row_emp from emp where id = zengyu; dbms_output.put_line(row_emp.id); dbms_output.put_line(row_emp.name); dbms_output.put_line(row_emp.address); dbms_output.put_line(to_char(row_emp.birth,'yyyy-mm-dd')); END; --1 利用循环语句完成在输出窗口打印九九乘法表; declare num_i number:=1; num_j number:=1; begin FOR num_i IN 1..9 LOOP FOR num_j IN 1..9 LOOP dbms_output.put_line(num_i||'x'||num_j||'='||num_i*num_j); END LOOP; END LOOP; end; --pl sql输出不换行 declare i number(8):=0; -- 定义循环所需的初始值 a varchar2(1000):=''; -- 定义一个空字符串 begin -- 开启循环 loop i:=i+1; -- 改变循环变量的值 exit when i>100; -- 退出循环条件 a:=a||i||' '; -- 拼接字符串 end loop; dbms_output.put_line(a); -- 输出结果 end; --网上参考答案 --1 利用循环语句完成在输出窗口打印九九乘法表; BEGIN FOR i IN 1..9 LOOP FOR j IN 1..9 LOOP IF (j<=i) THEN dbms_output.put(to_char(j)||'*'||to_char(i)||'='||to_char(i*j)||' '); END IF; END LOOP; dbms_output.new_line(); END LOOP; END; --2 运用pl/sql语句块打印6*4矩形 DECLARE a INT := 6; b INT := 4; BEGIN FOR i IN 1..a LOOP FOR j IN 1..b LOOP IF(i=1 OR i=a) THEN dbms_output.put('*'); ELSIF(j=1 OR j=b) THEN dbms_output.put('*'); ELSE dbms_output.put(' '); END IF; END LOOP; dbms_output.new_line(); END LOOP; END; --3 利用循环分别计算1-100之内的能被7整除和能被3整除数的累加和,并比较二者之间的差,打印输出差的正数值。 DECLARE sums7 INT := 0; sums3 INT := 0; num INT := 1; differences INT := 0; BEGIN WHILE(num<=100) LOOP IF(num MOD 3 = 0) THEN sums3 := sums3+num; ELSIF(num MOD 7 = 0) THEN sums7 := sums7+num; END IF; num := num + 1; END LOOP; dbms_output.put_line('能被3整除的数的累加和是 '||to_char(sums3)); dbms_output.put_line('能被7整除的数的累加和是 '||to_char(sums7)); differences := abs(sums3-sums7); dbms_output.put_line('两数之差是 '||to_char(differences)); END;