2011-04-18 162 views
3

「存儲過程通常用於數據驗證或 封裝組合若干SQL查詢大型,複雜的處理指令。」sql:如何通過存儲過程完成數據驗證?

說這個Oracle reference。那麼有人可以幫助我理解存儲過程如何用於數據驗證?因爲將數據傳遞到存儲過程中,它的經由其被明確設置爲Oracle數據類型(或用戶定義的類型,其也基於Oracle數據類型)參數進行發生

+0

好吧,我當然不是專家,這就是爲什麼我寧願留下評論。是不是真的,你可以在存儲過程中編寫你的業務邏輯作爲你的表的主要訪問點,通過這個你可以在實際持久化之前驗證數據? – 2011-04-18 05:47:34

回答

3

數據驗證。只發生數據類型驗證 - 必要時可以構建更深入的驗證(IE:檢查NUMBER數據類型中的小數)。參數化查詢通常對於SQL注入來說更安全,但它確實取決於參數是什麼以及查詢的內容。

CREATE OR REPLACE PROCEDURE example (IN_VALUE NUMBER) IS 

BEGIN 

    SELECT t.* 
    FROM TABLE t 
    WHERE t.column = IN_VALUE; 

END; 

在這個例子中,提交VARCHAR /字符串將導致錯誤 - 比將導致一個錯誤編號支持其他任何東西。如果IN_VALUE數據類型不能隱式轉換爲TABLE.column的數據類型,你會得到一個錯誤。

存儲過程封裝了一個交易,這是允許複雜的處理指令(意思是,一個以上的SQL查詢)。事務處理(IE:必須明確指定「COMMIT」或「ROLLBACK」)取決於設置。

+0

我在等你的答案;) – SuperMan 2011-04-18 06:04:13

+0

這意味着除了客戶端驗證之外,數據驗證是通過存儲過程在數據庫級完成的。我們是否需要在兩個層次都進行驗證? – SuperMan 2011-04-18 06:08:20

+4

@SuperMan:是的,在兩個層次都有效。始終在數據庫上進行驗證,就好像沒有客戶端驗證一樣。 – 2011-04-18 06:10:20

4

驗證可能意味着一些東西,可以以各種方式的數據庫中進行:

  • 列數據類型本身驗證的一種形式:NUMBER列只接受有效號碼等
  • 主鍵,唯一性和外鍵約束執行驗證
  • CHECK約束執行其他簡單的一排驗證,如:
    • END_DATE> START_DATE
    • SALARY> 0
    • JOB =售貨員或佣金IS NULL

然而,存在不能由任何上述的強制執行更復雜的驗證規則,例如: - SALARY < = (SELECT max_sal FROM config_table) - emp.start_date BETWEEN start_date和它們被分配到

部門END_DATE

有各種各樣的方式執行這些規則,包括數據庫觸發器,但經常優選的方法是創建一個存儲PR流程,通常稱爲「API」以執行驗證和動作,例如

PROCEDURE insert_emp (...) IS 
    ... 
BEGIN 
    -- Validate 
    -- 1) Salary less than max 
    SELECT max_sal 
    INTO l_max_sal 
    FROM config; 
    IF p_sal > l_max_sal THEN 
     error_pkg.raise_error ('Salary is too high'); 
    END IF; 
    ... 
    -- Insert 
    INSERT INTO emp (...) VALUES (...); 
END; 

然後,應用程序可以調用此過程,而不是直接執行更新,並且將執行所有必要的驗證。事實上,應用程序可能會調用此過程 - 直接插入到表中可能會被禁用。

3

在一個理想的世界中,您選擇的DBMS將是關係完整的,允許您編寫任意複雜度的約束並支持多個賦值,以便您的數據庫隨時更新(即不需要推遲或禁用約束)聲明。在現實世界中,我們擁有SQL。

理想的SQL的產品將是完整的SQL-92標準兼容:支持CREATE ASSERTION(架構級約束),允許在CHECK約束子查詢,並支持事務中的約束的管理延遲,使您的數據庫沒有禁用的約束進行更新。可悲的是,甲骨文還沒有達到這個水平的功能。因此,在現實世界中,我們必須訴諸程序代碼來「管理」更新,同時保持數據的完整性。

例如,考慮一個真實的一對一的關係,是普通不過,隨着業務規則如下:

數據庫包含三個 relvars的 員工和項目的詳細信息:EMP,PROJ和EMP_PROJ。每個 項目必須至少有一個 僱員,每個項目附件 必須參考現有項目。 當創建一個項目時,至少有一個員工必須同時連接 。

在Oracle中,你不能寫一個ASSERTIONCHECK執行臺間的限制,所以推遲約束的能力是無關緊要的在這種情況下。

一種方法可以編寫具有適當參數的PROCEDURE以創建項目並將一個員工分配給項目。這樣的程序將按照以下順序(僞代碼):

1)開始交易;

2)插入PROJ;

3)插入EMP_PROJ;

4)測試不符合名義約束條件的數據

EXISTS (
     SELECT * 
      FROM PROJ 
     WHERE NOT EXISTS (
          SELECT * 
          FROM EMP_PROJ 
          WHERE EMP_PROJ.project_code = PROJ.project_code 
         ) 
     ); 

5)如果測試發現非法數據,則回滾否則提交事務。

如果約束咬那麼事務回滾和數據的完整性一直維持(儘管你也許會想處理更優雅此類驗證失敗:)

類似的程序將需要刪除的員工從項目中防止將最後剩餘分配的員工從項目中移除時的情形(應該防止員工搬遷還是應該刪除項目?請問您的設計師:)

由於數據完整性只能由執行這樣的程序代碼,每個人都可以方便地將它封裝在數據庫中的一個PROCEDURE對象中n向用戶授予對PROCEDURE的'執行'權限(而不是授予對基礎表的增強權限)。強制一組用戶(例如,最終用戶應用程序)只能使用PROCEDURE來更新數據,因此應撤銷其在基礎表上的更新權限。這可能需要進一步的「輔助」功能,例如,將員工分配到項目並刪除項目。如果你購買了「通過存儲特效庫訪問所有數據庫」學派,那麼無論如何你都會這樣做。

+1

+1,即使步驟1和5不屬於存儲過程,但在呼叫環境中,在我看來。 – 2011-04-19 10:44:30