熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Oracle >> 正文

關於約束、CASE語句和游標的一些介紹

2013-11-13 16:16:33  來源: Oracle 

  關於約束CASE語句和游標
  我們的技術專家談完整性時間和歸屬問題
  
  我仔細閱讀了《Oraclei 數據庫概念手冊(Oraclei Database Concepts Manual)》和你們的站點但對下述概念仍不明白
  
  定義為可延遲(deferrable)的約束可以指定為
  
   initially immediate(初始化立即執行)或
   initially deferred(初始化延遲執行)
  
  我知道什麼是延遲約束但不明白什麼叫初始化立即執行的可延遲約束初始化延遲執行的可延遲約束請解釋二者的區別還有這些約束有什麼用途?這是通常容易混淆的問題我希望下面的例子能解釋清楚初始化立即執行/延遲執行規定了在默認情況下應該如何執行約束
  
  初始化立即執行在每條語句執行結束時檢驗約束
  
  初始化延遲執行一直等到事務完成後(或者調用set constraint immediate語句時)才檢驗約束
  
  來看下面的代碼
  SQL> create table t
   ( x int constraint
  check_x check ( x > )
  deferrable
  initially immediate
    y int constraint
  check_y check ( y > )
  deferrable
  initially deferred
   )
   /
  Table created
  
  SQL> insert into t values ( );
   row created
  
  SQL> commit;
  Commit complete
  
  所以當兩個約束同時滿足時才能正確無誤地插入行但是如果我試圖插入違反CHECK_X約束(初始化立即執行的約束)的行則系統會立即檢驗約束並得到下面的結果
  
  SQL> insert into t values ( );
  insert into t values ( )
  *
  ERROR at line :
  ORA: check constraint
  (OPS$TKYTECHECK_X) violated
  
  由於CHECK_X是可延遲但初始化為立即執行的約束所以這一行立刻被拒絕了而CHECK_Y則不同它不僅是可延遲的而且初始化為延遲執行這就意味著直到我用COMMIT命令提交事務或將約束狀態設置為立即執行時才檢驗約束
  
  SQL> insert into t values ( );
   row created
  
  現在它是成功的(總之到目前為止是成功的)我將約束檢驗延遲到了執行COMMIT的時候
  
  SQL> commit;
  commit
  *
  ERROR at line :
  ORA: transaction rolled back
  ORA: check constraint
  (OPS$TKYTECHECK_Y) violated
  
  此時數據庫將事務回滾因為違反約束導致了COMMIT語句的失敗這些語句說明了初始化立即執行與初始化延遲執行約束之間的區別initially(初始化)部分指定Oracle什麼時候會進行默認的約束檢驗是在語句結束時[immediate(立即執行)]還是在事務結束時[deferred(延遲執行)]我還要說明deferred(可延遲)子句有什麼用我可以發出命令讓所有可延遲的約束變為延遲執行的注意你也可以對一個約束使用該命令你不必讓所有可延遲的約束都變為延遲執行的
  
  SQL> set constraints all deferred;
  Constraint set
  
  SQL> insert into t values ( );
   row created
  
  由於將初始化立即執行的約束設置為延遲執行的模式這個語句似乎執行成功但是當我用COMMIT語句提交事務時看一下會發生什麼
  
  SQL> commit;
  commit
  *
  ERROR at line :
  ORA: transaction rolled back
  ORA: check constraint
  (OPS$TKYTECHECK_X) violated
  
  事務提交失敗並回滾因為在COMMIT語句之後對約束進行了檢驗相反我可以將初始化為延遲執行的約束變為立即執行的約束
  
  SQL> set constraints all immediate;
  Constraint set
  
  SQL> insert into t values ( );
  insert into t values ( )
  *
  ERROR at line :
  ORA: check constraint
  (OPS$TKYTECHECK_Y) violated
  
  前面在我提交前能執行的語句現在立即出了問題因為我手動修改了默認的約
  束模式
  
  延遲約束有哪些實際用處呢? 有很多它主要用於物化視圖(快照)這些視圖會使用延遲約束來進行視圖刷新在刷新物化視圖的過程中可能會破壞完整性而且將不能逐句檢驗約束但到執行COMMIT時數據完整性就沒問題了而且能滿足約束沒有延遲約束物化視圖的約束可能會使刷新過程不能成功進行
  
  使用延遲約束的另一個普遍原因是當預測是否需要更新父/子關系中的主鍵時它有助於級聯更新如果你將外鍵設為可延遲但初始化為立即執行那麼你就可以
  
  將所有約束設置為可延遲
  
  將父鍵更新為一個新值至此子關系的完整性約束不會被驗證
  
  將子外鍵更新為這個新值
  
  COMMIT只要所有受更新影響的子記錄都指向現有的父記錄這條命令就能成功執行
  
  如果沒有延遲約束這一更新過程將極為艱難參見/~tkyte/update_cascade/l中給出的沒有這一特性時進行級聯更新所必需的示例代碼!
  
  此外你可以在各種多語句事務中使用延遲約束這些事務在處理的過程中需要暫時破壞完整性但最後它們都會物歸原樣
  
  如何計算時間
  你是如何計算第一頁中AGE列顯示的時間的?我之所以問這個問題是因為我看到它有多種格式個月小時個小時等等我是Oracle新手想知道你們在使用哪種日期計算法
  
  我就是使用Oraclei第版(版)中介紹的使用已久但很好用的CASE語句
  
  Select
  case
  when sysdatetimestamp < /
  then round(**(sysdatetimestamp))
  || minutes old
  when sysdatetimestamp <
  then round(*(sysdatetimestamp))
  || hours old
  when sysdatetimestamp <
  then trunc(sysdatetimestamp)
  || days old
  when sysdatetimestamp <
  then trunc((sysdatetimestamp)/)
  || weeks old
  when sysdatetimestamp <
  then round(months_between
  (sysdatetimestamp))
  || months old
  else round(months_between
  (sysdatetimestamp)/)
  || years old
  end age
  
  如果你想在Oraclei的PL/SQL中使用CASE語句則會出現一個錯誤消息因為PL/SQL語法分析程序不識別CASE語句(請注意在Oraclei不存在這樣的問題)為了避開Oraclei的限制你可以
  
  將CASE語句隱藏在視圖當中並用PL/SQL來查詢視圖
  
  使用嵌套的DECODE語句來代替CASE語句
  
  我本人願意使用視圖但讀者Martin Burbridge在 網站上公布了下面這段DECODE代碼
  
  decode(sign(sysdatetimestamp/)
  round(**(sysdatetimestamp))
  || minutes old
  decode(sign(sysdatetimestamp )
  round(*(sysdatetimestamp))
  || hours old
  decode(sign(sysdatetimestamp)
  trunc(sysdatetimestamp)
  || days old
  decode(sign(sysdatetimestamp)
  trunc((sysdatetimestamp)/)
  || weeks old
  decode(sign(sysdatetimestamp)
  round(months_between
  (sysdatetimestamp))
  || months old
  round(months_between
  (sysdatetimestamp)/
  )
  || years old
  ))))) age
  
  它與CASE語句的功能完全相同只是不太明顯
  
  文件放在哪?
  我正在考慮為一個應用程序設計些選項利用它用戶可以上傳和存儲可供他人下載的文檔文檔可以是平均大小為K的Microsoft Word文檔最初需要(從CD)移植個文檔當使用該應用程序時存儲數量會增加到大約個文檔浏覽器前端是用於上傳和下載的PL/SQL插件(PL/SQL cartridge)頁面一開始會有人幾乎同時訪問該應用程序兩周內每天將有人訪問(分散訪問) 文檔本身在數據庫中作為BLOB存儲
  
  從使用方面考慮你覺得這樣的選項好嗎?它會過多占用系統全局區(SGA)嗎?考慮到應用程序的需求以及前端(基於浏覽器)除了保存為BLOB還有沒有其他選擇如文件系統?
  
  我什麼都存在數據庫裡就是這樣如果數據就是你的一切無論它們有什麼樣的值事實上都要放到數據庫中在那裡數據可以得到專業化的管理備份恢復而且安全除了這些實實在在的好處你還可以索引及搜索文檔(誠然用文件系統也可以做這些但在索引和文檔之間不存在完整性)在數據庫中你可以轉換文檔格式(例如上傳一個DOC文件而顯示為HTML格式)你的數據是完全集成的安全的有備份的而且隨時供你使用
  
  在Oracle公司內部我們將一個幾千吉字節的數據庫作為整個公司的一個單一的文件服務器公司所有文檔都存在那裡存在這樣一個單一的地方可以對這些文檔進行備份搜索建立索引和訪問在常規的文件系統中管理成千上萬的文檔是不可能的
From:http://tw.wingwit.com/Article/program/Oracle/201311/18071.html
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.