Oracle數據庫

1.關係型數據庫和結構化查詢語言sql


2.Oracle,DB2,Sybase,MS SQL ,Mysql


3.實體,屬性,關係 1521


4.oracle的服務:監聽服務(遠程訪問需要)和數據庫服務(要啓動)


5.oracle的配置文件

listener.ora(監聽器服務的配置文件)和
  tnsname.ora(監聽器服務訪問的配置文件)連接數據庫的主機字符串(自定義:主機字符串包括遠程IP
  和數據庫名了)

6.測試遠程連接

net manager(配置主機字符串和監聽器)
    找安裝路徑的快捷方式:右擊net manager打開文件
     plsql工具:字體設置和顯示行號 關鍵字大寫


7.oracle的物理文件

分爲三類:數據文件(.dbf)、控制文件(.ctl)、日誌文件(.log)


8.oracle系統表(數據字典)


9.表空間(對應一個物理的磁盤存儲位置)
     

 CREATE TABLESPACE j1706
DATAFILE  'E:\oracle\product\10.2.0\oradata\orcl\j1706.dbf'  
SIZE 20M  
AUTOEXTEND ON ;  
   用戶
  授權
   表


10.sql語句
     SQL語句主要可以劃分爲以下幾類:
DDL(Data Definition Language):數據定義語言,定義對數據庫對象(庫、表、列、索引)的操作。
CREATE、DROP、ALTER、RENAME、 TRUNCATE等

DML(Data Manipulation Language): 數據操作語言,定義對數據庫記錄的操作。
INSERT、DELETE、UPDATE

DCL(Data Control Language): 數據控制語言,定義對數據庫、表、字段、用戶的訪問權限和安全級別。
GRANT、REVOKE等

Transaction Control:事務控制
COMMIT、ROLLBACK、SAVEPOINT等

     (1)常用的數據類型   數值型(int、number)、字符型(char(固定長度)、varchar(可變長度)
           varchar2(可變長度))、日期型date

     (2)DDL(數據定義語言:表結構) 定義對數據庫對象(庫、表、列、索引)的操作
          

 建表:
         create table tb_person(
         id int,
         name varchar2(15),
         sex char(3),
         age int
         );
            查詢表:
          select * from tb_person;
        刪除表:
           drop table tb_person;
        修改表; 
           增加列:
          alter table tb_person add(phone varchar2(18),address varchar2(30));
            改變列長度:
          alter table tb_person modify(phone varchar2(20));
        刪除列:
           alter table tb_person drop(phone,address);
        修改列名:
           alter table tb_person rename column phone to iphone7s;
        修改表名:
           rename tb_person to tb_people;
         截斷表
       當表結構必須保留, 而表數據不再需要的時候
          TRUNCATE TABLE  tb_person


     (3)DML(數據操作語言) 定義對數據庫記錄的操作
        

插入:
         insert into tb_person(id,name,sex,age)
         values(1,'tom','男',20);
     刪除數據:
          delete from tb_personn;或者DDL中的截斷: truncate table tb_person;
     修改數據:
          update tb_person set age=21;
          update tb_person set age=21,id=2 where sex='男' and name='tom';

     sql語句刪除數據有幾種方式?分別是什麼?

答:
    1. delete
          -- DML語句,delete語句最小單位是行,可以通過where選擇刪除,刪除數據可以回滾,
      保留表結構。最慢
    2. truncate
          -- DDL語句,TRUNCATE是截斷表的所有數據,刪除數據不可以回滾,保留表結構。較快
    3. drop
          -- DDL語句,刪除表結構和表所有數據,並且不能回滾,慎用。最快


      (4)事務控制
           transaction control:事務控制   commit(提交)、rollbck(回滾)
    (4)約束
        

 check 檢查約束
        -- not null 非空約束(特殊的檢查約束)
      unique 唯一約束
          primary key 主鍵約束(非空且唯一)
      foreign key   外鍵約束(解決數據冗餘問題)
           列級約束:
         create table tb_person(
       id int primary key,
       name varchar2(18) not null,
       sex char(3) check(sex='男' or sex='女'),
       age int check(age>=18 and age<60),
       phone varchar2(20) unique,
       address varchar2(30),
       clazz_id int  references tb_clazz(id) on delete cascade 
     );
      create table tb_clazz(
       id int primary key,
       code varchar2(15),
       name varchar2(15),
       bzr varchar2(20)
      );
外鍵中,當主表的記錄被子表參照時,主表記錄不允許被刪除。
        解決方案:
           先刪除字表數據,在刪除父表數據。
           先將字表關聯數據設爲null,在刪除父表數據
           先將子表數據修改,在刪除父表數據。
        on delete cascade 當刪除父表數據時,級聯刪除子表數據。
        on set null 當刪除父表數據時,將關聯的數據設置爲null
 表級約束:
            create table tb_student(
          id int,
          name varchar2(18),
          sex char(3),
          age int,
          phone varchar2(18),
          email varchar2(18),
          address varchar2(18),
          clazz_id int,
          constraints tb_students_pk primary key(id),
          check(name is not null),
          check(sex='男' or sex='女'),
          check(age>18 and age<50),
          unique(phone),
          unique(email),
         constraints tb_students_fk foregin key(clazz_id) reference tb_clazz(id)
        );
        自定義約束名:(約束 約束名 約束類型)
        constraints tb_students_pk
        數據庫建議建表:
          外鍵以表級約束,其他用列級約束。
           
         約束的維護(添加、刪除):
         alter table tb_student add primary key(id);
         刪除約束根據約束名刪除:
         alter table tb_student drop constraints tb_students_pk;
         複合約束(只能在表級中定義):
         primary key(year,month)
     (5)nvl函數 nvl(第一個參數,第二個參數),
       如果第一個參數爲null,則取第二個參數
       定義字段的別名as
       select empno as eID,ename,sal,sal*12 as yearsal from scott.emp;
       distinct關鍵字去除重複數據:
           select distinct deptno from scott.emp;
       比較運算符:
           select *from scott.emp where sal>=800 and sal<=1600;
           select * from scott.emp where sal between 800 and 1600;
           select * from scott.emp where deptno=20 or deptno=30;
           select * from scott.emp where deptno in(20,30);
      模糊查詢like:
        %匹配所有  _匹配一個字符
        select * from scott.emp where ename like 's%';
        select * from scott.emp where ename like '%s';
        select * from scott.emp where ename like '%s%'; 
        select * from scott.emp where ename like '_s%';
     優先級規則:先and後or
         對結果排序 order by asc(升序 默認) desc(降序) 
     select * from scott.emp order by sal asc;
     select * from scott.emp order by sal desc;
      (6)多表連接
           內連接(等值連接)
           兩個表(或連接)中某一數據項相等的連接稱爲內連接。
       SELECT FROM dept d INNER JOIN emp e ON d.deptno = e.deptno';
      外連接(非等值連接)
用於查詢一張表在另一張表中沒有關聯數據的信息
外連接分爲三種:
左外連接(LEFT OUTER JOIN)
右外連接(RIGHT OUTER JOIN)
全外連接(FULL OUTER JOIN)
-- 左外連接:+號在右邊,左邊的表的所有數據都要顯示,如果右邊表沒有對應的數據,則補Null
-- 右外連接:+號在左邊,右邊的表的所有數據都要顯示,如果左邊表沒有對應的數據,則補Null
-- 全外連接:兩張表的所有數據都要全部顯示
           備份一張表(只備份數據,不備份約束):
         create table tb_emp as select * from scott.emp;
         select e.empno,e.ename,e.mgr,t.ename
           from scott.emp e,tb_emp t
           where e.mgr=t.empno and  e.empno='7369';
             自連接:
            select e.empno,e.ename,e.mgr,t.ename
          from scott.emp e,scott.emp t
          where e.mgr=t.empno and e.empno='7369';
    (7)組函數:(組函數都會忽略NULL值)
        對一組值進行運算,並返回單個值,也叫聚合函數。
    count(*|列名) 統計行數:
      select count(*) from scott.emp;
      select count(comm) from scott.emp;
    sum(數值類型列名) 求和:
       select sum(sal) from scott.emp;
        avg(數值類型列名)  平均值:
       select avg(sal) from scott.emp;
    max(列名)  最大值:
       select max(sal) from scott.emp;
    min(列名) 最小值:
        select min(sal) from scott.emp;
   (8)分組 group by
      把該列具有相同值得多條記錄當成一條記錄處理,最後只輸出一條記錄。
       分組函數忽略空值。結果集隱式按升序排列,
       如果需要改變排序方式可以使用order by子句。
         按部門分組:
      select deptno from scott.emp group by deptnot;
      按工作崗位分組:
      select job from scott.emp group by job;
    group by子句的真正作用在於與各種組函數配合使用:
          select deptno,count(*),sum(sal),avg(sal),max(sal),min(sal)
        from scott.emp group by deptno;



       面試題:數據條件篩選時有幾種方式?有什麼區別?
        

 限定組的結果:having子句
      having子句用來對分組後的結果進行條件過濾。
      having和where的區別;
        where和having都是用於條件過濾。
        where在分組前進行條件過濾,having子句是在分組後進行條件過濾,
        where子句中不能使用聚合函數,having子句可以使用聚合函數。
            select deptno,count(*),sum(sal),avg(sal),max(sal),min(sal)
          from scott.emp group by deptno having sum(sal)>9000
          order by sum(sal) desc;
  (9)子查詢
        子查詢就是把多條語句寫成一條,子查詢執行的時候先執行子查詢
    再執行主查詢:
     select * from scott.emp where sal>(
      select sal from scott.emp where ename='allen'
     );
     子查詢需要注意的問題:單行子查詢返回多行
      多行比較運算符:
       In:與列表中的一個值相等(包含)
       any:與子查詢返回的每一個值比較
       all:與子查詢返回的所有值比較
         in:
          select * from scott.emp where sal in(
           select min(sal) from scott.emp group by deptno
          );
           any與子查詢返回的每一個值比較 >any 大於最小的 <any 小於最大的
       select * from scott.emp where sal>any(
         select min(sal) from scott.emp group by deptno
       );
           all與子查詢返回的所有值進行比較 >all 大於最大的 <all 小於最小的
       select * from scott.emp where sal>all(
        select min(sal) from scott.emp group by deptno
       );
    
     (10)集合運算:從多個結果集中提取數據
         union 把兩個結果集的數據合起來,然後幹掉重複的
       select deptno from scott.dept union 
       select deptno from scott.emp;
     union all:把兩個結果集的數據合起來
       select deptno from scott.dept union all
       select deptno from scott.emp;
     intersect:把兩個結果集的數據合起來,然後幹掉重複的,
      再找兩個查詢中都出現的記錄
        select deptno from scott.dept intersert
         slect deptno from scott.emp;
     minus:判斷數據存在第一查詢的結果集,而·不存在第二查詢的數據集
        select deptno from scott.dept minus
         slect deptno from scott.emp;
        面試題:
         select r.id,r.R1,nvl(b.R2,'null') from r,b where r.id=b.id(+)
          union
          selet b.id,nvl(r.R1,'null'),b.R2 from r,b where r.id(+)=b.id;
       標準外連接:
         select r.id,r.R1,b.R2 from r left outer join b on r.id=b.id
         union
         select b.id,r.R1,b.R2 from r right outer join b on b.id=r.id;
       全外連接:
        select nvl(r.id,b.id) as id,r.R1,b.R2 from r full outer join b on 
        r.id=b.id;
     
    (11)rownum 僞列 ‘結果集’中產生的序列
       select rownum,deptno,dname,loc from scott.dept;
        只有存在rownum=1的記錄,纔可能存在rownum=2的記錄
          利用rownum分頁:
            select * from(
         select rownum as tempid,empno,ename from scott.emp
        )t1
        where t1.tempid between 6 and 10;
        
          rowid:一般來說每一行數據對應一個rowid,而且固定且唯一。
      在這一行存入數據庫時就確定了。可以理解爲java對象中的內存地址。
      可以利用rowid來查詢記錄,而且通過rowid查詢速度最快的查詢方法。
      rowid只有在表發生移動(比如表空間變化,數據導入/導出後)纔會發生變化。
       面試題:
         刪除重複數據(刪除所有重複數據
     /刪除重複數據但保留一條(保留最大rowid或者最小)):
      刪除所有數據;
     delete from tb_test where name in(
      select name from tb_test group by name,age having count(*)>1
     );
       刪除數據,保留一條數據(第一種方法);
        create table tb_tmp as select distinct name,age from tb_test;
       truncate table tb_test;
       insert into tb_test(name,age) select name,age from tb_tmp;
      刪除數據,保留一條數據(方法二):
       delete from tb_test where rowid not in(
        select max(rowid) from tb_test group by name,age
       );
     (12)常用函數
        dual是oracle提供的一個虛表
    select length('hello') from dual;
     常用函數:
       lower把大寫轉成小寫 upper把小寫轉大寫:
        select upper('helloworld') from dual;
    select lower('HELLOWORLD') from dual;
    select * from scott.emp where ename='smith';
    select * from scott.emp where lower(ename)='smith';
   initcap使串中的所有單詞首字母變成大寫:
     select initcap('sql course') from dual;
   concat 連接兩個字符串:
      select concat('Hello','World') from dual;
   substr 取字符串,從start開始,取count個:
      select substr('HelloWorld',1,5) from dual;
         從4開始取到末尾:
     select substr('Helloworld',4) from dual;
   length 返回字符串的長度:
         select length('HelloWorld') from dual;
   instr  在一個字符串中搜索指定的字符,返回發現指定的字符的位置,從1開始:
       select instr('HelloWorld','l') from dual;
   trim  刪除首尾的空字符串
       select trim(' HelloWorld ') from dual;
   replace 替換:
     select replace('HelloWorld','ll','ff') from dual;
   round  四捨五入;
     select round(45.926,2) from dual;
   trunc  截斷:
   select trunc(45.926,2) from dual;
   mod  取模:
     select mod(1600,300) from dual;
   decode函數:
     select ename,job,sal 基本工資,decode(job,
      'salesman', sal*0.9,
      'manager',sal*0.85,
      'clerk',sal+100,
      'pre
      sident',sal
     )as 實發工資 
     from scott.emp;
  面試題:
      select name,
        sum(decode(t.course,'JDBC',t.grade,0)) JDBC,
    sum(decode(t.course,'Hibernate',t.grade,0)) Hibernate,
    sum(decode(t.course,'Spring',t.grade,0)) Spring
     from tb_course t 
      group by t.name;
11.數據庫對象
    (1)數據庫對象包括: 表、序列、同義字、數據庫鏈接、視圖等。
       對象的特點:可以給其他對象使用,名字不能重複。
    (2)序列:自動生成的唯一序列號,常用在主鍵自動生成。
          創建序列:
         create seqeuence s_tb_student;
      刪除序列:
          drop seqeuence s_tb_student;
      序列的兩個屬性currval,nextval:
         select s_tb_student.currval from dual;
         select s_tb_student.nextval from dual;
      使用序列:
          insert into tb_student(id)values(s_tb_student.nextval);
      序列不會隨着rollback回滾,下面這些情況時sequence值可能產生間隙:
         回滾發生; 
         序列用於多個表(不建議),建議一張表使用一個序列;
          系統宕機。
    (3)索引
         面試:如何優化你的數據庫查詢?
        1.數據庫的查詢方式?
          --全表掃描  select * from tb_student 慢
          --利用索引掃描   快
          --共享語句   最快(oracle有個回滾段,臨時表空間)
      
    索引 index
      作用:在數據庫中用來加速對錶的查詢
      原理:通過使用快速路徑訪問方法快速定位數據,減少了磁盤的I/O
      特點:與表獨立存放,但不能獨立存在,必須屬於某個表
             由數據庫自動維護,表被刪除時,該表上的索引自動被刪除。
        
          索引的創建:
           自動:當在表上定義一個primary key或者unique約束1條件時,數據庫會
             自動創建一個對應的索引。
           手動:用戶可以創建索引以加速查詢。
           create index i_tb_student_name on tb_student(name);
           查詢的時候使用索引:
             select * from tb_student where name='Alice';
           刪除索引:
              drop index i_tb_student_name;
      當創建索引的時候,oracle會默認創建一個和當前表相關的索引頁,
      而索引頁中保存了索引字段和真實的磁盤地址,當用戶發送sql語句帶了索引時,
      oracle會到索引頁中查詢索引字段,直接定位磁盤IO,提取數據。
      所以索引數據快於全表掃描。
    索引的維護
       1.建立索引後,查詢的時候需要在where條件中帶索引字段纔可以使用索引。
       2.在經常查詢的字段上面建立索引。不要在所有字段上建立索引。
       3.因爲索引是用來加速查詢速度的,如果一張表經常做insert,delete,
        update ,而很少做select,不建議建立索引
     如果一張表字段很少,不建議建立索引。
       4.索引是由oracle自動維護的。索引使用久了會產生索引碎片
        (磁盤碎片),影響查詢效果,所以使用久了需要手動進行維護(刪除在重建)
   sql語句的優化:
     多使用共享語句,儘量使你的sql語句能夠使用索引。
     怎樣使sql語句能夠使用到索引呢?
      當sql語句中包含not in,<>,is null,is not null,like'%%'的時候
      不會使用索引。
      in:可以使用索引。
      優化方案: a<>0  改爲a>0 or a<0
                 a is not null改爲 a>0 或a>''
         is null 用一個缺省值代替空值
         like'%%'不能使用索引
         like'001%'可以使用索引
   (4)同義字 :通過創建同義字(對象的另外的一個名字)簡化訪問對象的操作。
      create synonym tb_emp for scott.emp;
      select * from tb_emp;
      刪除:drop synonym tb_emp;
     數據庫鏈接--database link
   (5)視圖
     創建用戶時通過dba角色賦予權限,而不是手動賦予權限,則會創建
     視圖會報:沒有權限
      解決方案:使用system用戶登錄,在給j1703賦予權限
      grant create any table to j1703 with admin option;
      grant create any view to j1703 with admin option;
      grant select any table to j1703 with admin option;
      所有數據字典都是視圖:
       select * from User_Tables;
       視圖可以使複雜的查詢變得簡單
       創建簡單視圖(一個表):
         create view v_deptinfo as
     select deptno as 部門,count(*) 人數,sum(sal) 總工資,avg(sal)
     平均工資,max(sal) 最高工資,min(sal) 最低工資
     from scott.emp group by deptno;
使用視圖:select *from v_deptinfo;
     複雜視圖(多個表)
      刪除視圖:drop view v_deptinfo;
   (6)數據建模(試規範題)
   軟件開發過程:
1. 需求調研,與客戶進行溝通
2. 需求分析,將現實工作中的動作模擬到計算機
   數據建模
3. 開發
4. 測試
5. 上線部署
從關係數據庫的表中刪除冗餘信息的過程稱爲規範化,
是得到高效的關係型數據庫表的邏輯結構最好和最容易的方法。
規範化數據時:應執行以下操作:
將數據庫的結構精簡爲最簡單的形式
從表中刪除冗餘值
標識所有依賴與其他數據的數據
     獲得數據化的三種方法:三範式
       步驟1:
         第一範式:必須要有主鍵,並且每個屬性值都是不可分的最小數據單元
     ,則稱爲是第一範式。
     第二範式:所有非主關鍵字都完全依賴於主關鍵字(通常用於聯合主鍵)
     第三範式:非主關鍵字不能依賴於其他非主關鍵字(通常用於一個主鍵)
     數據建模
      1.根據三個範式
      2.分析實體之間的關係
        1對1:一個人只有一個身份證 唯一外鍵關聯或者主鍵關聯
    一對多:一個班級可以有多個學生  一個學生只屬於一個班級
            關聯:一對多使用主外鍵關聯,通常在多方建立外鍵
        多對多:一個學生可以選擇多門課程 一門課程可以被多個學生選修
           關聯:多對多通常使用中間表(再多建一張表存儲)關聯數據
               通常中間表會有兩張表的id作爲聯合主鍵,並且
           作爲外鍵指向關聯表
        訂單和用戶之間的關係是多對一:
       create table tb_order(
        id int primary key,
        code varchar2(50),
        user_id int,
        foregin key(user_id) references tb_user(id)
       );
     訂單和書籍是多對多關係:
       create table tb_item(
        order_id int,
        book_id int,
        count int,
        primary key(order_id,book_id),
        foregin key(order_id) references tb_order(id),
        foregin key(book_id) references tb_book(id)
       );
       select * from tb_user u,tb_book b,tb_order o,tb_item i
        where u.id=o.user_id 
        and o.id=i.order_id,
        and b.id=i.book_id
 and u.name='jack';
12.plsql(數據庫編程語言)
    PL/SQL=傳統SQL+結構化流程控制
      好處:1.有結構化的流程控制,可以完成複雜的操作
            2.性能高於sql
   sql:頁面輸入信息 -- servlet接收數據,調用持久層生成sql - sql語句發送到數據庫(DBMS),數據庫編譯 -- 執行sql。
   plsql:頁面輸入信息 -- servlet接收數據,調用持久層傳入參數(調用存儲過程) -  執行sql。
        3.可以對程序中的異常進行處理
        PL/SQL程序由三個塊組成。
(1) 聲明部分: 在此聲明PL/SQL用到的變量,類型及遊標,以及局部的存儲過程和函數 
 (2)執行部分: 過程及SQL 語句  , 即程序的主要部分 
 (3)  異常處理部分: 錯誤處理  
    語法:declare --聲明部分,用來定義變量等
           begin--可以理解成java的花括號,編寫代碼的地方
           exception--處理程序拋出異常
           end;
      
       第一個plsql,在控制檯輸出HelloWorld
        BEGIN
       --包名.過程('參數')
       dbms_output.put_line('HelloWorld!');
     END;
       定義變量,變量初始值都是null
       常量constant
       declare
          v_id int;
      v_name varchar2(18):='jack';
      v_clazz constant varchar2(5):='j1703';
    begin
       v_id:=100;
       dbms_output.put_line('v_id='||v_id);
       dbms_output.put_line('v_name='||v_name);
    end;
    複合變量(數據類型) record
    1.包含多個內部組件,用於存放多個值
    2.需要先定義類型,然後用該類型可重複定義多個變量
     注意:複合變量屬於數據類型,定義時前面要加TYPE
           TYPE是不能直接使用的,使用前需要定義變量引用
      declare 
          type r_tb_clazz is record
          (
            id int,
        code varchar2(18)
           );
            v_clazz r_tb_clazz;
         begin
           v_clazz.id:=1;
           v_clazz.code:='j1703';
      end;
    plsql分兩大類:匿名塊,帶名塊 
    begin 
      insert into tb_clazz(id,code) values(3,'j1703');
      commit;
    end;
     select
         1.缺少into子句,plsql目的是操作數據,需要定義變量
     2.實際返回行數超過請求行數(只能查詢一條數據,如果需要查詢
        多條數據,使用遊標)
     3.未找到數據
    declare  
        v_id int;
    v_code varchar2(18);
    begin
        select id,code into v_id,v_code from tb_clazz where id=1;
    dbms_output.put_link(v_id || '' || v_code);
    end;
      %type屬性:
       定義某個變量的數據類型與已經存在的變量數據類型,
        某個列的數據類型相同。
       declare
          v_id tb_clazzz.id%type;
      v_code tb_clazz.code%type;
    begin
       select id,code into v_id,v_code from tb_clazz where id=1;
         dems_output.put_line(v_id || '' || v_code);
    end;
     %rowtype屬性:
        用於定義不確定的類型的變量
    當數據庫中表字段的個數和數據類型會在運行中改變,
     程序中的變量也會自動隨之改變。
      rt_tb_clazz tb_clazz%rowtype
      rt_tb_clazz 變量和tb_clazz表結構一致,相當於表結構的副本。
     declare
        v_tb_clazz tb_clazz%rowtype;
      begin
         select id,code into v_tb_clazz.id,v_tb_clazz.code from 
           tb_clazz where id=1;
           dbms_output.put_line(v_tb_clazz.id || '' || v_tb_clazz.code);
      end; 
      declare
        v_tb_clazz tb_clazz%rowtype;
      begin
         select * into v_tb_clazz from tb_clalzz where id=1;
         dbms output.put_line(v_tb_clazz.id || '' || v_tb_clazz.code);
         end;
     使用recode
     declare
         type r_tb_clazzz is recode
         (
           id tb_clazz.id%type,
           code tb_clazz.code%type;
          );
          v_tb_clazz r_tb_clazz;
       begin
         select * into v_tb_clazz from tb_clazz where id=1;
         dbms_output.putline(v_tb_clazz.id || '' || v_tb_clazz.code);
       end;
     循環和判斷
          if分支
         declare
            v_i number:=10;
              begin 
             if(v_i=10)then
           dbms_output.putline('進入if塊');
               end if;
          end;
       
      if else分支
         if ()then...else ...end if
      if elsif else分支
           if() then...elsif()then ...else ...end if
    plsql的循環有三種:loop for while
       loop循環:
           loop
          v_i:=v_i+1;--自增
          exit when v_i=5;
        end loop;
         第二種結束方法:
         loop 
           v_i:=v_i+1;
           if(v_i=5) then
              exit;
          end if;
          end loop;
       for循環
           for v_i in 1..5
       loop
        end loop;
     --重點 項目當中最常用的異常處理
     --實際開發中異常的處理  重點
      create table tb_error(
        id int primary key,
    errorObj varchar2(18),--拋出異常的對象
    sqlcode varchar(50),--異常編碼
    sqlerrm varchar(200),--異常信息
    currdate date    --發生時間
      );
       create sequence s_tb_error;
     --重點掌握
     --orale當拋出異常時會將異常編碼存儲到sqlcode函數,異常信息
     -- 存儲到sqlerrm 
       declare
          v_id tb_clazz.id%type;
      v_code tb_clazz.code%type;
       begin
          select id,code into v_id,v_code from tb_clazz;
      dbms_output.put_line(v_id || '' || v_code );
    exception
        when others then
      v_sqlcode :=sqlcode;
      v_sqlerrm:=sqlerrm;
      insert into tb_error(id,errorobj,sqlcode,sqlerrm,currdate)
      values(s_tb_error.nextval,'default',v_sqlcode,v_sqlerrm,sysdate);
      commit;
     end;
     --遊標:用來提取多行數據
     --oracle打開一個工作區(緩存)來保存多行查詢的結果集,
     -- 遊標就是給這個工作區命的名稱,並能用於處理由多行查詢而返回的
記錄行
    --隱式遊標:默認的DML語句和select語句都有隱式遊標
    --顯示遊標:開發中給工作區命名,並且可以進行操作
    --%isopen  boolean 遊標打開,則返回true
    --%nofound  boolean  如果最近抓取沒有獲得記錄,返回true
    --%found  boolean  如果最近抓取獲得記錄,返回true
    --%rowcount  number 返回到目前爲止獲取的記錄數
    --使用遊標的步驟
    --1.定義遊標  cursor c_tb_clazz is select * from tb_clazz;
    --2.打開遊標  open c_tb_clazz;
    --3.fetch遊標  fetch c_tb_clazz into r_tb_clazz;
    -- 遊標有個指針,默認指向第一行之上,fetch將指針向下移動,指向第n
      行數據,如果有數據,notfound 返回false,found返回true
       如果到末尾,抓取不到數據,一直顯示最後一條數據
    --4.關閉遊標 close c_tb_clazz;
    --第一個例子  ;使用遊標提取tb_clazz的所有數據
      declare 
           cursor c_tb_clazz is select * from tb_clazz;
       r_tb_clazz tb_clazz%rowtype;
      begin
         open c_tb_clazz;
        loop
           fetch c_tb_clazz into r_tb_clazz;
            dbms_output.put_line(r_tb_clazz.id || '' || r_ tb_clazz.code);
         end loop;
        close c_tb_clazz;
     end;
    --帶參數的遊標
      第二個例子:使用遊標提取tb_clazz的所有數據,同時提取每個班級的學生數據
    --注意:傳遞是形參,形參是不用長度的
     declare 
        --班級遊標
    cursor c_tb_clazz is select * from tb_clazz;
     r_tb_clazz tb_clazz%rowtype;
     --學生遊標
     cursor c_tb_student(v_clazz_id tb_clazz.id%type)
      is select * from tb_student where clazz_id=v_clazz_id;
         r_tb_student tb_student%rowtype;
      begin
         open c_tb_clazz;
         loop
            fetch c_tb_clazz into r_tb_clazz;
        exit when c_tb_clazz%notfound;
        dbms_output.put_.line('班級' || r_tb_clazz.id || '' || r_tb_clazz.code);
              --當前班級的學生數據
          --打開學生遊標,參數是班級id
               open c_tb_student(r_tb_clazz.id);
                loop
              fetch c_tb_student into r_tb_student;
              exit when c_tb_student%nofound;
              dbms_output.putline(r_tb_student.id || '' || r_tb_student.name);
           end loop;
               close c_tb_student;
       end loop;
     close c_tb_clazz;
      end;
    --遊標for循環
      1.不需要顯式打開遊標
      2.for循環自動隱式地定義recode變量
      3.不需要使用fetch抓取數據
      4.循環結束後,不需要使用close來關閉遊標
       declare
           cursor c_dept is select * from scott.dept;
       begin
            for re_dept in c_dept
          loop
             dbms_output.put_line();
          end loop;
      end;
      --帶名塊(declare  begin end; 就是匿名塊)
      是數據庫中命名的PL/SQL塊,作爲數據庫對象保存在數據庫裏。
        主要四類:
      存儲過程:執行特定操作,無返回值
       函數:進行復雜計算,有返回值
        包:邏輯上相關的過程和函數組織在一起
        觸發器:事件觸發,執行相應操作
         
     過程和函數統稱爲PL/SQL子程序,過程和函數的唯一區別是函數總向調用者返回數據,
     而過程則不返回數據。 
    --存儲過程
    語法:(直接創建)
       procedure name
        [(parameters)形參]
          is
           局部變量聲明
         begin
           語句;
          [exception]
         end;
       --建立存儲過程,可以被多個程序調用(java或者c++),可以向
       --存儲過程傳遞參數,也可以讓存儲過程傳出參數
       --參數:
       --in:默認,值被傳遞給子程序。子程序不能改變參數值。
       --out:值被返回調用環境(java或者c++),子程序會改變參數值。
       --調用存儲過程
          begin 
            insertclazz();--存儲過程名
          end;
       --調用存儲過程通過帶參數傳給存儲過程
     --函數與過程語法差異:
         (1)在函數的聲明中,必須包含一個帶有數據類型的return字句,
       返回值表示的類型,在函數體中必須有一個有效的return語句。
      (2)只能使用in模式參數傳入參數值
      --語法:
           function name
       [(parameters)形參]
        return datatype
        is 
          局部變量聲明
            begin
          語句;
          return value;
          [exception]
          end;
        
        包類似於C++和Java語言中的類,其中變量相當於類中的成員變量,過程和函數相當於類方法。把相關的程序單元歸納到包裏
通過使用包,可使開發人員利用面向對象的方法進行存儲過程的開發,從而提高系統性能。
      --觸發器
      --觸發器是當某個事件發生時自動隱式運行。而且,觸發器不能
      接收參數。
      --觸發器最主要作用:提供更靈活的完整性校驗規則。
      --語法:
        trigger name
        after|berfore
        is 
          局部變量聲明;
        begin
           語句;
           [exception]
            end;
    --觸發器的組成成分:
       觸發事件:在任何情況下觸發trigger(insert,undate,delete等)
       觸發時間:before或者after
       觸發器本身:該trigger被觸發後的執行體
       觸發頻率:動作被執行的次數(主要行級觸發器)
       
          當行級觸發器被觸發時,如果要訪問插入,更新或刪除的記錄的值,
      可以使用:
         :new  訪問操作完成後的值
         :old 訪問操作前的數據
         --特性  insert   update   delete
            :old    Null      有效    有效
          :new    有效      有效     null
      當刪除tb_tran的數據時,將數據備份到tb_back:
  
         create  or  replace trigger t_del_tran
           before delete
           on tb_tran
           for  each row
         declare
             begin
             insert into tb_back(id,accout,amount,currdate)
         values(:old.id,:old.Accout,:old.Amount,:old:Currdate);
             end t_del_tran;
            觸發器還可以用來維護數據完整性:
          create or replace trigger t_del_clazz
            before delete
        on  tb_clazz
                for each row
      declarer
          begin
              delete from tb_student_course
          where student_id in
          (
             select id from tb_student where clazz_id=:old.id
          );
                  delete from tb_student where clazz_id=:old.id;
    end  t_del_clazz;


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章