Oracle视图和PL SQL编程.

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(数据控制)语言,诸如:insertupdateselect intodeletecommitrollbacksavepoint。不允许使用DDL(数据定义)语言 createdropalter......

PL/SQL块的组成结构

DECLARE --声明单元(可选)

变量1 类型[(长度)];

变量2 类型[(长度)];

BEGIN --执行单元(必须)

数据处理语句;

exception --异常处理单元(可选)

异常处理语句;

END;

声明单元

PLSQL使用DDECLARE关键字声明变量定义,此单元必须在PLSQL的最前面。

通常变量名称可以包括字母、下划线、数字、#$

变量名称不能超过30个字符

l 第一个字符必须是字母

l 不区分大小写

l 不能使用任何关键字

 

declare

name varchar(24);--声明变量

age int:=25;--声明变量并赋默认值

address String(64);--声明编程类型变量

 

PL SQL编程变量类型

char定长字符类型,包括子类characterstringrowidNchar最长限制在2000个字符

varchar2可变字符类型,包括子类varcharstringnvarchar2最长限制在4000个字符

number(p,s) 值类型,包括子类intintegersmallintdecdouble

date 日期型

boolean 布尔类型

%type 复合类型变量

%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 等价于javaelse if语句

Case when 类似于JavaSwitch 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;

 

原文地址:https://www.cnblogs.com/zengyu1234/p/15345068.html