oracle 遊標和觸發器sql
回顧數據庫
表空間oracle
表空間:邏輯名詞:表、視圖、索引;拆分:段、區 、塊(最小的存儲單元)app
物理文件的構成:maven
一、tcl文件 二、log文件 三、dbf文件(數據文件)
一個或者多個表空間----------->一個物理文件(dbf文件)ide
一、建立表空間和用戶函數
一、建立表空間(切換成管理員)oop
二、建立用戶 關聯表空間學習
三、受權測試
示例:
--表空間: 數據表空間 create tablespace tbs_331 datafile 'd:/oracledata/tbs_331.dbf' --數據文件 size 50m; --初始大小 --臨時表空間 create temporary tablespace tbs_331_tmp tempfile 'd:/oracledata/tbs_331_tmp.dbf' size 20m; --建立用戶 create user u331 identified by 123456 default tablespace tbs_331 --默認表空間 temporary tablespace tbs_331_tmp; --默認臨時表空間 --受權 --內置的角色: --connect: 鏈接,可以登錄系統,具有最基本的權限;遊客 --resource: 資源;查看數據庫對象,增刪改查數據;正式的用戶使用 --dba:管理員 grant connect,resource to u331;
二、導出(備份)和導入(還原)
2.1 須要準備虛擬目錄:
--建立一個虛擬目錄:映射到指定的物理路徑上 create directory dir331 as 'd:/oracledata'; --授予u331用戶操做dir331的權限:read,write grant read,write on directory dir331 to u331;
2.2 導出:expdp
(數據泵程序)
注意:在cmd窗口執行
expdp u331/123456 schemas=u331 dumpfile=u331.dmp logfile=u331.log directory=dir331
導入:impdp
impdp u331/123456 schemas=u331 dumpfile=u331.dmp logfile=u331.log directory=dir331
實驗:
一、使用新建立的用戶登陸建立好的表空間,建立一個數據表並錄入一些數據供測試
二、導出
三、刪除表
四、再次導入,查看數據是否還原
三、刪除用戶和表空間:
-- 刪除用戶 drop user u331 cascade; --級聯刪除 --刪除表空間 (包括內容和數據文件) drop tablespace tbs_331 including contents and datafiles; drop tablespace tbs_331_tmp including contents and datafiles;
若是忘掉管理員密碼:
sqlplus scott/tiger SQL*Plus: Release 11.1.0.6.0 - Production on 星期一 9月 21 15:30:44 2020 Copyright (c) 1982, 2007, Oracle. All rights reserved. 鏈接到: Oracle Database 11g Enterprise Edition Release 11.1.0.6.0 - Production With the Partitioning, OLAP, Data Mining and Real Application Testing options SQL> conn / as sysdba; 已鏈接。 SQL> alter user sys identified by sys;
學習目標
一、遊標
二、觸發器
學習內容
一、遊標
遊標:cursor ;指針;
以往對數據表中數據進行的各類數據操做,本質上都是對列進行操做的。沒法對每一行數據進行處理。
遊標:將查詢到的結果暫時的存放到上下文的空間中(內存區),能夠對數據進行逐行定位操做。
遊標的分類:
一、顯式遊標
有名字,定義遊標,打開遊標...
二、隱式遊標
DML命令(insert,update,delete) 和select ... into 命令
遊標的屬性
用法:顯式遊標名%屬性名 或者:SQL%屬性名
%NOTFOUND:若是沒有讀取到數據,返回true。不然返回false %ROWCOUNT:實際讀取到的行數 %ISOPEN:遊標是否打開,true/false %FOUND:遊標是否讀取到數據 ;讀取到true;不然:false
顯式遊標
一、聲明遊標 二、打開遊標 三、提取數據 四、關閉遊標 declare --聲明遊標 cursor c1 is 查詢命令; begin --打開遊標 open c1; --提取數據 fetch c1 into 變量名; --關閉遊標 close c1; end;
普通顯式遊標
示例:
declare --聲明遊標 cursor c1 is select ename,sal from emp where deptno=10; --臨時變量 vname emp.ename%type; vsal emp.sal%type; begin --打開遊標 open c1; --逐行提取數據 loop fetch c1 into vname,vsal; -- 實際的業務... if vsal>3000 and vsal<=10000 then dbms_output.put_line('調薪:2000'); else dbms_output.put_line('調薪:1000'); end if; exit when c1%notfound; end loop; --關閉遊標 close c1; end;
帶變量的遊標
declare --聲明遊標 cursor c1(vno number) is select ename,sal from emp where deptno=vno; --臨時變量 vname emp.ename%type; vsal emp.sal%type; begin --打開遊標 open c1(10); --逐行提取數據 loop fetch c1 into vname,vsal; dbms_output.put_line(vname||':工資:'||vsal); -- 實際的業務... if vsal>3000 and vsal<=10000 then dbms_output.put_line('調薪:2000'); else dbms_output.put_line('調薪:1000'); end if; exit when c1%notfound; end loop; --關閉遊標 close c1; end;
使用for循環簡化遊標
--emp_row:行數據 begin for emp_row in (select ename,sal from emp where deptno=10) loop dbms_output.put_line(emp_row.ename||emp_row.sal); end loop; end;
遊標類型的變量
說明:將遊標看成數據類型,來聲明變量;好比:存儲過程,函數,將查詢的多條結果存入到遊標中,返回供別的過程使用; declare --遊標類型 type cur_type is ref cursor; --使用該遊標類型 聲明一個變量 cur1 cur_type; --行類型的變量用來存儲每次讀取到的數據 emp_row emp%rowtype; begin open cur1 for select * from emp; loop fetch cur1 into emp_row; dbms_output.put_line(emp_row.ename||emp_row.sal); exit when cur1%notfound; end loop; close cur1; end;
隱式遊標
begin delete from emp where empno=621; if SQL%NOTFOUND then dbms_output.put_line('數據不存在'); else dbms_output.put_line('刪除成功'); end if; end;
遊標測試
create or replace procedure test_cur5 as --聲明變量 cursor c1 is select deptno,count(*) from emp group by deptno; vno number(3); vcount number(5); begin open c1; loop fetch c1 into vno,vcount; dbms_output.put_line('部門:'||vno||'人數:'||vcount); exit when c1%notfound; end loop; close c1; end;
測試:
begin test_cur5; end;
二、觸發器
觸發器:
隱式(自動)執行的存儲過程;當執行:DDL(create,alter,drop)操做,DML(insert,update,delete)操做時,一系列的系統事件(實例加載,登陸、登出)時會激活相應類型的觸發器;
觸發器分類:
一、DDL觸發器
二、DML觸發器
三、系統觸發器
DML觸發器
建立觸發器:
create or replace trigger 名字 --trigger 觸發器 before or after or instead of --執行時間 before:以前 after:以後 instead of :替代(替換) insert or update or delete --激活觸發器的操做(動做) on 表名 或者 視圖名 --觸發器操控的數據庫對象 for each row -- 行級觸發器 :數據操做影響的每一行數據都會激活觸發器 begin --命令 若是出現錯誤: rasie_application_error(); --觸發器執行過程當中一旦發生錯誤,會致使原先的數據操做:一併回滾 end; -- 觸發器中規定,最多不超過:32k的代碼;若是代碼過多能夠封裝成過程,在觸發器中調用
例子:
一、不容許刪除員工的數據
create or replace trigger tg_test1 before delete on emp begin raise_application_error(-20001,'不容許刪除員工表的數據'); end;
測試:
delete from emp where empno=66;
觸發器中的內置的對象:
邏輯表:
一、不容許降薪
create or replace trigger tg_test2 before update on emp for each row --行級 begin -- 獲取原來的薪資 ,獲取修改後的薪資 if :old.sal>:new.sal then raise_application_error(-20002,'不容許降薪操做'); end if; end;
觸發器中的:3個條件謂詞:
inserting: 判斷是不是錄入操做
用來判斷當前是那種數據操做激活了觸發器;直接看成條件使用;
create or replace trigger tg_test3
after insert or update or delete
on emp
begin
if updating then
dbms_output.put_line('修改操做激活了觸發器');
elsif inserting then
dbms_output.put_line('錄入操做激活了觸發器');
elsif deleting then
dbms_output.put_line('刪除操做激活了觸發器');
end if;
end;
準備一個員工表相同結構的的歷史記錄表;
-- 複製表結構 create table emp_his as select * from emp where 1=2; --複製表 create table emp_his2 as select * from emp;
例子:刪除員工數據時,將刪除的數據插入到歷史表中
create or replace trigger tg_test4 before delete on emp for each row begin insert into emp_his(empno,ename,job,sal) values(:old.empno,:old.ename,:old.job,:old.sal); end;
替代觸發器只能做用於視圖上面:
什麼是視圖(view):虛擬表,本質上是一個查詢命令;
一、授予該用戶建立視圖的權限:
grant create view to scott;
二、建立視圖
將一個複雜的查詢命令存儲起來,以供重複使用; 建立視圖 create view v_selectemp as select dt.deptno,dt.dname,count(e.empno) vcount from dept dt,emp e where dt.deptno=e.deptno group by dt.deptno,dt.dname; --測試 select * from v_selectemp where vcount>6 order by vcount ;
視圖的做用:簡化查詢操做,不容許:insert,update,delete
例子:
-- 測試錄入 insert into v_selectemp(deptno,dname,vcount) values(30,'帥哥部',30); create or replace trigger tg_test5 instead of insert on v_selectemp for each row --替換錄入操做 begin delete from emp where deptno=:new.deptno; --換成了刪除操做 end;
應用場景:
一、限制數據的修改規則
二、實現自動記錄歷史記錄
三、模擬自增列
create or replace trigger tg_test6 before insert on emp for each row begin select 序列.nextval into :new.empno from dual; end;
Java中jdbc調用oracle存儲過程:
獲取驅動包:
D:\app\MrLang\product\11.1.0\db_1\jdbc\lib
maven中註冊jar包:
mvn install:install-file -DgroupId=com.oracle -DartifactId=ojdbc6 -Dversion=11.1.0.6.0 -Dpackaging=jar -Dfile=驅動包路徑
引入依賴項:
<dependencies> <dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc6</artifactId> <version>11.1.0.6.0</version> </dependency> </dependencies>
測試調用過程:
public class Test1 { static final String DRIVER = "oracle.jdbc.driver.OracleDriver"; static final String URL = "jdbc:oracle:thin:@localhost:1521:orcl"; static final String USERNAME = "scott"; static final String PWD = "tiger"; public static void main(String[] args) { Connection connection=null; //操做過程 CallableStatement statement=null; try { Class.forName(DRIVER); connection = DriverManager.getConnection(URL, USERNAME, PWD); // 與編譯命令:指定要調用的過程, statement=connection.prepareCall("{call sp_zhuanzhang3(?,?,?,?)}"); // 綁定參數 // 輸入參數:傳參 statement.setInt(1,2); statement.setInt(2,1000); // 輸出參數:只須要指定對應的數據類型;註冊輸出參數 statement.registerOutParameter(3,OracleTypes.NUMBER); statement.registerOutParameter(4,OracleTypes.NUMBER); // 執行命令 statement.execute(); // 執行後:能夠獲取到輸出參數的值 double b1= statement.getDouble(3); double b2=statement.getDouble(4); System.out.println("轉帳後的餘額:"+b1+":"+b2); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); }finally { if(statement!=null) { try { statement.close(); } catch (SQLException e) { e.printStackTrace(); } } if(connection!=null){ try { connection.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }
總結