Oracle遊標和觸發器

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
  • u331/123456:用戶名和密碼
  • schemas=u331:模式,默認狀況下模式=用戶;
  • dumpfile=u331.dmp:導出的文件名
  • logfile=u331.log:日誌文件
  • directory=dir331:虛擬目錄: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;

觸發器中的內置的對象:

邏輯表:

  • :old 舊錶:用來存放刪除的數據;delete和update時會用到
  • :new 新表:用來存放新的數據;insert和update時會用到

一、不容許降薪

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個條件謂詞:

  • updating: 判斷是不是修改操做
  • deleting: 判斷是不是刪除操做
  • 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();
                }
            }
        }
    }
}

總結

相關文章
相關標籤/搜索