1. 程式人生 > >四、Oracle loop循環、while循環、for循環、if選擇和case選擇、更改讀取數據、遊標、觸發器、存儲過程

四、Oracle loop循環、while循環、for循環、if選擇和case選擇、更改讀取數據、遊標、觸發器、存儲過程

bsp 邏輯或 pda 傳遞依賴 函數 名稱 執行 count 記錄

數據庫的設計(DataBase Design):
針對於用戶特定的需求,然後我們創建出來一個最使用而且性能高的數據庫!

數據庫設計的步驟:
01.需求分析
02.概念結構設計
03.邏輯結構設計
04.物理結構設計
05.數據庫的實施
06.數據庫的運行和維護

數據庫的3大範式:
1.確保每列的原子性!每一列都是一個不可再分的數據!
2.確保每列都和主鍵相關!
3.確保每列都和主鍵有直接的管理,而不是間接依賴(傳遞依賴)!


PL/SQL: (Procedural Language) 過程化sql語言!
在我們之前的sql語句中增加了選擇或者是邏輯判斷!

數據庫在執行PL/SQL語句的時候,PL和SQL是分別執行的!

|| 拼接字符串
:= 賦值運算符
= 比較運算符 類似與java中的==
.. 範圍運算符
!= <> ~= ^= 不等於
and 邏輯與
or 邏輯或
not 取反


PL/SQL語法:


1.declare 可選部分 ==》聲明

2.begin 必須有 ==》書寫sql 和 pl/sql

3.exception 可選部分 ==》異常

4.end 必須有 ==》pl/sql代碼塊結束

案例1: loop循環語法:

loop
執行的語句;
exit when 條件;
end loop;

declare
  --聲明部分
  i number;
begin
  --代碼開始

  i := 1;
  loop
    --循環開始
    dbms_output.put_line(i); --輸出語句
    i := i + 1;
    exit when i = 10;
  end loop; --循環結束

end; --結束部分

案例2:while循環語法:

while 條件 loop
執行的語句;
end loop;

declare
  --聲明部分
  i number;

begin
  --代碼開始

  i := 1;
  while
i < 20 loop --循環開始 dbms_output.put_line(i); --輸出語句 i := i + 1; end loop; --循環結束 end; --結束部分

案例3:for循環語法:

for 變量 in 範圍 loop
執行的語句;
end loop;

declare
  --聲明部分
  i number;

begin
  --代碼開始

  for i in 1 .. 30 loop
    --循環開始
    dbms_output.put_line(i); --輸出語句
  end loop; --循環結束

end; --結束部分

案例4:根據老師的薪水輸出不同的語句!

  if選擇結構 和 case選擇結構

-- 根據teacher表中的sal 來輸出不同的語句
declare
  t_name   teacher.tname%type; --說t_name的類型根據teacher表中tname的類型來決定
  t_sal    teacher.sal%type;
  t_result varchar2(50);
begin
  --開始
  select tname, sal into t_name, t_sal from teacher where tno = 1002; --查詢指定老師的薪水

  if t_sal > 5000 and t_sal < 10000 then
    -- 多重if
    t_result := 一級;
  elsif t_sal >= 10000 and t_sal < 20000 then
    t_result := 二級;
  else
    t_result := 高級;
  end if;
  --根據t_result的值來判斷輸入語句    switch
  case t_result
    when 一級 then
      dbms_output.put_line(哈哈....);
    when 二級 then
      dbms_output.put_line(一般般....);
    when 高級 then
      dbms_output.put_line(可以啊....);
  end case;
end; --結束

案例5: 函數 ==》把身份證號中的出生年月日隱藏!

create or replace function fn_teacher_tid(f_tid varchar2)
  return varchar2 --創建一個函數  傳遞一個varchar2類型的值 返回一個varchar2類型的值
is f_result varchar2(50); --聲明變量
begin
  --開始書寫函數內容
  if length(f_tid) != 18 then
    dbms_output.put_line(身份證格式不正確);
  else
    dbms_output.put_line(身份證格式正確);
  end if;
  f_result := substr(f_tid, 1, 6) || ******** || substr(f_tid, 15);
  return f_result;

end fn_teacher_tid; --函數結束

--調用函數
select fn_teacher_tid(110101198705256045) from dual;

案例6: 遊標 :

01.是oracle系統給我們用戶開設的一個數據緩沖區!
02.存放的是sql語句執行的結果集!
03.每個遊標區都有一個名稱,用戶通過遊標逐行獲取需要的數據!


分類:
01.隱式遊標: 非查詢語句
只要我們使用pl/sql,程序在執行sql語句的時候 自動創建! 遊標區===》sql
02.顯示遊標: 返回多行記錄
03.REF遊標(動態遊標): 處理運行時才能確定的動態sql查詢結果

遊標的常用屬性:
01.sql%found 影響了一行或者多行數據 返回true
02.sql%notfound 沒有影響行 返回true
03.sql%rowcount 返回true影響行數
04.sql%isopen 遊標是否打開!始終是false


使用遊標的步驟:
01.聲明遊標
02.打開遊標
03.使用遊標獲取記錄
04.關閉遊標

01.隱式遊標

begin
  --  隱式遊標    自動創建
  update teacher set tname = 大家辛苦了 where tno = 1002; --修改
  if sql%found then
    dbms_output.put_line(教師的信息已經更改 || sql%rowcount);
  else
    dbms_output.put_line(更改失敗);
  end if;
end;

02.顯示遊標

declare
  --聲明 顯示遊標
  c_tname teacher.tname%type;
  c_sal   teacher.sal%type;
  cursor teacher_cursor is
    select tname, sal from teacher where tno < 1005; --遊標數據來源
begin
  open teacher_cursor; --打開遊標
  fetch teacher_cursor
    into c_tname, c_sal; --使用遊標
  while teacher_cursor%found loop
    dbms_output.put_line(教師的姓名是==》 || c_tname);
    dbms_output.put_line(教師的薪水是==》 || c_sal);
    fetch teacher_cursor
      into c_tname, c_sal; --逐行讀取  
  end loop;
  close teacher_cursor; --關閉遊標
end;

案例7:觸發器

  觸發器是針對於增刪改!

update :old :new
insert :new
delete :old


:old 代表修改之前的值
:new 代表修改之後的值

select * from teacher t  for update

-- 創建一個用於保存teacher操作記錄的表
create table teacher_log(logid number not null, old_value varchar2(150), create_date date, log_type number, t_no number);

--創建主鍵
alter table teacher_log add constraint pk_teacher_logid primary key(logid);

-- 創建序列
create sequence sq_teacherLog_logid minvalue 1 maxvalue 99999999999 start
  with 1 increment by 1;

--  創建觸發器
create or replace trigger tr_teacher after insert or update or delete --會在增刪改之後 觸發
on teacher for each row --作用在teacher表中的每一行
declare --聲明變量
old_value teacher_log.old_value%type;
log_type teacher_log.log_type%type;
t_no teacher_log.t_no%type;
begin
  if inserting then
    log_type  := 1; --新增
    t_no      := :new.tno;
    old_value := :new.tname || ***** || :new.sal;
  elsif deleting then
    log_type  := 2; --刪除
    t_no      := :old.tno;
    old_value := :old.tname || ***** || :old.sal;
  else
    log_type  := 3; --修改
    t_no      := :old.tno;
    old_value := :old.tname || ***** || :old.sal || 現在的薪水: || :new.sal;
  end if;

  --把用戶修改的數據 放入 teacher_log
  insert into teacher_log
  values
    (sq_teacherLog_logid.nextval, old_value, sysdate, log_type, t_no);
end tr_teacher; --結束

案例8:存儲過程
為了完成一個特定的功能而實現編寫一組sql語句的集合!

新增教室時,如果身份證號碼不足18位,報錯!

create or replace procedure pro_addTeacher --存儲過程
(p_no teacher.tno%type, p_name teacher.tname%type, p_tid teacher.tid%type) is ex_tidException exception; --異常類型

begin
  if length(p_tid) != 18 then
    raise ex_tidException; --拋出異常
  end if;

  --新增
  insert into teacher (tno, tname, tid) values (p_no, p_name, p_tid);
  commit; --- 自動提交

exception
  -- 異常處理部分
  when ex_tidException then
    dbms_output.put_line(身份證號不正確);
  when others then
    dbms_output.put_line(其他異常);
  
end pro_addTeacher; --結束

--調用存儲過程
call pro_addTeacher(1111, 小白白, 1122222222222222222);

name teacher.tname%type :會根據表中字段的類型,自動改變!

teacherRow teacher%rowtype: 一整行的記錄,包括很多字段!

teacherRow.name

四、Oracle loop循環、while循環、for循環、if選擇和case選擇、更改讀取數據、遊標、觸發器、存儲過程