1. 程式人生 > 其它 >Oracle檢視和PL SQL程式設計.

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的最前面。

l通常變數名稱可以包括字母、下劃線、數字、#$

l變數名稱不能超過30個字元

l第一個字元必須是字母

l不區分大小寫

l不能使用任何關鍵字

declare

name varchar(24);--宣告變數

age int:=25;--宣告變數並賦預設值

address String(64);--宣告程式設計型別變數

PL SQL程式設計變數型別

lchar定長字元型別,包括子類characterstringrowidNchar最長限制在2000個字元

lvarchar2可變字元型別,包括子類varcharstringnvarchar2最長限制在4000個字元

lnumber(p,s) 值型別,包括子類intintegersmallintdecdouble

ldate 日期型

lboolean 布林型別

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 等價於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;