1. 程式人生 > >程式設計師常見面試之 資料庫 知識點小結(二)

程式設計師常見面試之 資料庫 知識點小結(二)

前言

聚簇索引與非聚簇索引的區別

  • 聚簇索引的順序就是資料的物理儲存順序
    每個表中只能有一個聚集索引
    聚集索引要求:“既不能絕大多數都相同,又不能只有極少數相同”的規則。
  • 非聚簇索引的解釋是:索引順序與資料物理排列順序無關
  • 一個表最多隻能有一個聚簇索引。

建立索引程式碼

-----------------------------------------------------------
---- Create T_Pet table in tempdb. 
-----------------------------------------------------------
USE tempdb CREATE TABLE T_Pet ( animal VARCHAR(20), [name] VARCHAR(20), sex CHAR(1), age INT ) ----------------------------------------------------------- ---- Create Unique Clustered Index ----------------------------------------------------------- CREATE UNIQUE CLUSTERED INDEX T_PetonAnimal1_
ClterIdx ON T_Pet (animal)

非聚集索引程式碼

-----------------------------------------------------------
---- Create T_Pet table in tempdb with NONCLUSTERED INDEX. 
-----------------------------------------------------------
USE tempdb

CREATE TABLE T_Pet
(
    animal    VARCHAR(20),
    [name]    VARCHAR(20),
    sex        CHAR(1),
    age        INT
)

----------------------------------------------------------- ---- Create Unique NonClustered Index ----------------------------------------------------------- CREATE UNIQUE NONCLUSTERED INDEX T_PetonAnimal1_NonClterIdx ON T_Pet (animal)

NonClustered 和 Clustered 就是聚集和非聚集的區別

稠密和非稠密的區別

稠密就是一條搜尋碼值都有一個索引,
非稠密索引中,只為搜尋碼的某些值建立索引項。非稠密是一個索引對應一些記錄的範圍

Note
輔助索引必須是稠密索引

遊標

比如 select * from table_a 可以得到結果集,遊標用來定位結果集的行,可以對結果集修改等等。
@@FETCH_STATUS 全域性變數可以判斷遊標是不是到了最後,該變數為非0表示到了最後或者出錯

程式碼

Set serveroutput on;

declare 
    ---define Cursor
    Cursor cur_policy is
     select cm.policy_code, cm.applicant_id, cm.period_prem,cm.bank_code,cm.bank_account
     from t_contract_master cm
     where cm.liability_state = 2
     and cm.policy_type = 1
     and cm.policy_cate in ('2','3','4')
     and rownum < 5
     order by cm.policy_code desc;
    curPolicyInfo cur_policy%rowtype;---定義遊標變數
Begin
   open cur_policy; ---open cursor
   Loop 
     --deal with extraction data from DB
     Fetch cur_policy into curPolicyInfo;
     Exit when cur_policy%notfound;

     Dbms_Output.put_line(curPolicyInfo.policy_code);
   end loop;
   Exception 
     when others then
         close cur_policy;
         Dbms_Output.put_line(Sqlerrm);

   if cur_policy%isopen then  
    --close cursor 
      close cur_policy;
   end if;
end;

觸發器

觸發器是一個特殊的儲存過程。 ORACLE事件指的是對資料庫的表進行的INSERT、UPDATE及DELETE操作或對檢視進行類似的操作。ORACLE將觸發器的功能擴充套件到了觸發ORACLE,如資料庫的啟動與關閉等

  • 觸發時機:指定觸發器的觸發時間。如果指定為BEFORE,則表示在執行DML操作之前觸發,以便防止某些錯誤操作發生或實現某些業務規則;如果指定為AFTER,則表示在執行DML操作之後觸發,以便記錄該操作或做某些事後處理。
  • 語句觸發器是對每一個語句觸發一次
  • 行觸發器是對語句受影響的每一行觸發一次
  • 行觸發器和語句觸發器的區別表現在:行觸發器要求當一個DML語句操走影響資料庫中的多行資料時,對於其中的每個資料行,只要它們符合觸發約束條件,均啟用一次觸發器;而語句觸發器將整個語句操作作為觸發事件,當它符合約束條件時,啟用一次觸發器。當省略FOR EACH ROW 選項時,BEFORE 和AFTER 觸發器為語句觸發器,而INSTEAD OF 觸發器則為行觸發器。

  • 比如 插入500行的 insert 命令,語句觸發器只觸發一次,而行觸發器出發了500次

  • 行觸發器有 for each row子句。語句觸發器沒有for each row 子句

程式碼

BEFORE DELETE 這兒的 before 可以換成 after
for each row 可以有或者省略
例1: 建立一個觸發器, 當職工表 emp 表被刪除一條記錄時,把被刪除記錄寫到職工表刪除日誌表中去。

CREATE TABLE emp_his AS SELECT * FROM EMP WHERE 1=2;
CREATE OR REPLACE TRIGGER tr_del_emp
   BEFORE DELETE --指定觸發時機為刪除操作前觸發
   ON scott.emp
   FOR EACH ROW   --說明建立的是行級觸發器
BEGIN
   --將修改前資料插入到日誌記錄表 del_emp ,以供監督使用。
   INSERT INTO emp_his(deptno , empno, ename , job ,mgr , sal , comm , hiredate )
       VALUES( :old.deptno, :old.empno, :old.ename , :old.job,:old.mgr, :old.sal, :old.comm, :old.hiredate );
END;
DELETE emp WHERE empno=7788;
DROP TABLE emp_his;
DROP TRIGGER del_emp;
    Oracle 中預設的相關名稱分別為OLD和NEW。觸發器的PL/SQL塊中應用相關名稱時,必須在它們之前加冒號(:),但在WHEN子句中則不能加冒號。

例2:限制對Departments表修改(包括INSERT,DELETE,UPDATE)的時間範圍,即不允許在非工作時間修改departments表。

CREATE OR REPLACE TRIGGER tr_dept_time
BEFORE INSERT OR DELETE OR UPDATE
ON departments
BEGIN
 IF (TO_CHAR(sysdate,'DAY') IN ('星期六', '星期日')) OR (TO_CHAR(sysdate, 'HH24:MI') NOT BETWEEN '08:30' AND '18:00') THEN
     RAISE_APPLICATION_ERROR(-20001, '不是上班時間,不能修改departments表');
 END IF;
END;

其他示例

我為什麼要使用觸發器?比如,這麼兩個表:

      Create Table Student(              --學生表 
        StudentID int primary key,       --學號 
        .... 
       ) 

      Create Table BorrowRecord(               --學生借書記錄表 
        BorrowRecord   int identity(1,1),       --流水號   
        StudentID      int ,                    --學號 
        BorrowDate     datetime,                --借出時間 
        ReturnDAte     Datetime,                --歸還時間 
        ... 
      ) 
 用到的功能有: 
    1.如果我更改了學生的學號,我希望他的借書記錄仍然與這個學生相關(也就是同時更改借書記錄表的學號); 
    2.如果該學生已經畢業,我希望刪除他的學號的同時,也刪除它的借書記錄。 
 等等。 

 這時候可以用到觸發器。對於1,建立一個Update觸發器: 
     Create Trigger truStudent 
       On Student                         --在Student表中建立觸發器 
       for Update                          --為什麼事件觸發 
     As                                        --事件觸發後所要做的事情 
       if Update(StudentID)            
       begin 

         Update BorrowRecord 
           Set StudentID=i.StudentID 
           From BorrowRecord br , Deleted   d ,Inserted i      --Deleted和Inserted臨時表 
           Where br.StudentID=d.StudentID 

       end        

SQLServer 理解觸發器裡面的兩個臨時的表:Deleted , Inserted 。注意Deleted 與Inserted分別表示觸發事件的表“舊的一條記錄”和“新的一條記錄”。
一個數據庫系統中有兩個虛擬表用於儲存在表中記錄改動的資訊,分別是:

Tables 虛擬表Inserted 虛擬表Deleted
在表記錄新增時 存放新增的記錄 存放新增的記錄
修改時 存放用來更新的新記錄 存放更新前的記錄
刪除時 不儲存記錄 存放被刪除的記錄

PL SQL

PL: Procedural LanguagePL/SQL也是一種程式語言,叫做過程化SQL語言(Procedural Language/SQL)。

PL/SQL是Oracle資料庫對SQL語句的擴充套件。在普通SQL語句的使用上增加了程式語言的特點,所以PL/SQL就是把資料操作和查詢語句組織在PL/SQL程式碼的過程性單元中,通過邏輯判斷、迴圈等操作實現複雜的功能或者計算的程式語言。
參見 這兒
plsql 常用函式

事務日誌

事務日誌檔案Transaction Log File,副檔名為ldf。它是用來記錄資料庫更新情況的檔案,它可以記錄針對資料庫的任何操作,並將記錄的結果儲存到獨立的檔案中。對於每一次資料庫更新的過程,事務日誌檔案都有非常全面的記錄。根據這些記錄可以恢復資料庫更新前的狀態。

在 SQL Server 2000中,資料庫至少包括一個數據檔案和事務日誌檔案,資料和事務日誌從不混在一個檔案裡。

在事務日誌已滿的情況下,使用者不能更新資料。backup log語句有雙重的目的,不僅可以備份事務日誌,並且在事務日誌滿的時候,使用者還可以利用他清理事務日誌,移去事務日誌中不活動的部分。

截斷並不減少物理日誌檔案大小,而是減少邏輯日誌檔案的大小並釋放磁碟空間以供重新使用。

通常情況下,事務日誌備份經常與完整備份和差異備份結合使用,比如,每週進行一次完整備份,每天進行一次差異備份,每小時進行一次日誌備份。這樣,最多隻會丟失一個小時的資料。

如何檢視最早開始的活動事務的開始時間及伺服器程序 ID

連線到某個資料庫,執行 DBCC OPENTRAN命令,檢視 SPID 和 Start time 行。

如果文章對您有所幫助,不妨支援一注2塊彩票錢

支付寶

參考文章