程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> SqlServer數據庫 >> 關於SqlServer >> 《高性能的數據庫》 第四講 編程細節(2)

《高性能的數據庫》 第四講 編程細節(2)

編輯:關於SqlServer
第四講 編程細節(下部分)

 1、觸發器
 2、游標
 3、函數
 4、存儲過程
 5、事務

---------------------
作者:懶蟲 # SapphireStudio .
歡迎訪問我們的站點www.chair3.com
歡迎轉載。
--------------------

  上次得到不少朋友的捧場,信心大增了:),決定趁著五一期間把它寫完,反正外面非典厲害,也不好出去玩。這裡講到3、4、5了。

  這裡決定把4與3調換一下,先講解4(存儲過程,以下用sp來簡稱;函數,以下用fn來簡稱)

4、存儲過程。

  存儲過程是數據庫編程裡面最重要的表現方式了。

  呵呵,這裡我要提到上次說道的:我拒絕使用觸發器。這裡我要開始猛批一頓觸發器了。

  在SQL 2000裡,說實話,我實在找不出觸發器可以存在的理由。回憶一下:觸發器是一種特殊的存儲過程。它在一定的事件(Insert,Update,Delete 等)裡自動執行。我建議使用sp和級聯來代替觸發器。

  在SQL 7 裡面,觸發器通常用於更新、或刪除相關表的數據,以維護數據的完整。SQL 7裡面,沒有級聯刪除和級聯修改的功能。 只能建立起關系。既然SQL 2000裡面提供了級聯,那麼觸發器就沒有很好的存在理由。更多的情況下是作為一個向下兼容的技術而存在。

  當然,也有人喜歡把觸發器作為處理數據邏輯,甚至是業務邏輯的自動存儲過程。 這種方法並不足取。這裡列舉以下使用觸發器的一些壞處:

 a、“地下”運行 。
   觸發器沒有很好的調試、管理環境。調試一段觸發器,要比調試一段sp更耗費時間與精力。

 b、類似於goto語句。(過分自由的另外一個說法是:無政府主義!)
   一個表,可以寫入多個觸發器,包括同樣for Update的10個觸發器!同樣for Delete的10個觸發器。也就是說,你每次要對這個表進行寫操作的時候,你要一個一個檢查你的觸發器,看看他們是做什麼的,有沒有沖突。
   或許,你會很牛B的對我說:我不會做那麼傻B的事情,我記得住我做了些什麼!3個月以後呢?10個月以後呢?你還會對我說你記得住麼?
 c、嵌套觸發器、遞歸觸發器
   你敢說你這麼多的觸發器中不會存在Table1更新了Table2表,從而觸發Table2表更新TAble3,TAble3的觸發器再次觸發Table1更新Table2…… ??
   或許還會發生這種情況:你的程序更新了Table1.Fd1,觸發器立馬更新Table1.fd1,再次觸發事件,觸發器再次更新Table1.fd1……

   當然,SQL Server可以設置和避免應用程序進入死循環,可是,得到的結果,或許就不是你想要的。
 
 …… 
  我想不出觸發器更多的壞處了,因為我早就拋棄了它。算了,不批它了,酸是各人愛好把!我建議使用完全存儲過程來實現數據邏輯和事務邏輯!

  先講講sp的編寫格式(我個人的編程習慣)。良好的習慣有助於日後的維護。


  Create Proc spBuyBook(           --@@存儲過程頭,包括名字、參數、說明文檔
   @iBookID int,   --書的ID       --@@參數
   @iOperatorID int  --操作員ID
  )
  -------------------------------------------------------  @@說明文檔
  --Name : spBuyBook                    @@名字   
  --func : 購買一本書的業務邏輯              @@存儲過程的功能           
  --Return: 0,正確;-1,沒找到該書;-2,更新Book表出錯;-3..... @@返回值解釋
  --Use  : spDoSomething,spDOSomething2....        @@引用了那些外部程序,比如sp,fn,vw等
  --User : 懶蟲                      @@該存儲過程的使用者
  --Author: 懶蟲 # SapphireStudio (www.chair3.com)     @@作者
  --Date : 2003-5-4                    @@最後更新日期
  --Memo : 臨時寫寫的,給大家作個Sample。沒有調試阿。   @@備注
  ------------------------------------------------

-------
  As                            --@@程序開始
  begin
   
   Begin Tran                       --@@激活事務
    Exec spDOSomething                  --@@調用其他sp
    if @@Error<>0                    --@@判斷是否錯誤
    begin
     Rollback Tran                   --@@回滾事務
     RaisError ('SQL Server,spBuyBook: 調用spDOSomeThing發生錯誤。', 16, 1) with Log --@@記錄日志
     Return -1                     --@@返回錯誤號
    end 
  
   .... --更多其他代碼

   Commit Tran                      --@@提交事務
  end
        
  媽 的我怎麼這麼背啊我??什麼時候不死機,偏偏在這時!!丟了不少……:(:(
  下面默哀3分鐘……

   1……
   2……
   3……
  
  好了,繼續!回憶剛才寫的內容ing ……

  AA、存儲過程的幾個要素: a. 參數 b.變量 c.語句 d.返回值 e.管理存儲過程
  BB、更高級的編程要素:  a.系統存儲過程 b.系統表 c.異常處理 d.臨時表 e.動態SQL f.擴展存儲過程 g.DBCC命令

  AA.a 參數: 知識要點包括:輸入參數,輸出參數,參數默認值

   Sample:

    Create Proc spTest(
     @i int =0 ,    --輸入參數
     @o int output   --輸出參數
    )
    As
     Set @o=@i*2    --對輸出參數付值
     
   Use the Sample:

    Declare @o int
    Exec spTest 33,@o output
    Select @o          --此時@o應該等於33*2=66。

   ----------------------------------------------------------------------
   以上代碼沒有測試,順手寫寫的。希望不會出錯:) 
                          --懶蟲 # SapphireStudio

         精彩世界,盡在3腿軟件網(www.chair3.com)!!
   -----------------------------------------------------------------------                       
  AA.b 變量:AA.a中已經有聲明變量的例子了,就是Declare @o int
  AA.c 語句:在SQL Server 中,如果僅僅使用標准SQL語句將是不可想象的,通常認為,標准的SQL 語句就那麼幾條,如:   
        Select, Update, Delete
       因此,我們需要引入更多更強大的功能,那


您正在看的SQLserver教程是:《高性能的數據庫》 第四講 編程細節(2)。就是T-SQL語句:
  
       賦值語句:Set     
       循環語句:While 
       分支語句:if , Case ( Case語句不能單獨使用,與一般高級語言的不同)
       
       一起舉個例子吧:
       Sample :
       
       Declare @i int
       Set @i=0

       While @i<100
       begin

        if @i<=20
        begin

         Select Case Cast(@i As Float)/2 When (@i/2) then Cast(@i As varchar(3)) + '是雙數'
                         else       Cast(@i As varchar(3)) + '是單數'

/>             end

        end

        Set @i=@i+1
       end 
     
       ----------------------------------------------------------------------
       以上代碼判斷20之內的單數與雙數。
                             --懶蟲 # SapphireStudio
             精彩世界,盡在3腿軟件網(www.chair3.com)!!
       -----------------------------------------------------------------------
  AA.d 返回值
    Sample:

     Create Proc spTest2
     As
      Return 22

    Use the Sample
     Declare @i int
     Exec @i=spTest2
     Select @i 

  AA.e 管理存儲過程: 創建,修改,刪除。
    分別為:
    Create Proc ... , Alter Proc ... , Drop Proc ...



 BB、更高級的編程要素:  a.系統存儲過程 b.系統表 c.異常處理 d.臨時表 e.動態SQL f.擴展存儲過程 g.DBCC命令

   哈哈,以下課程收費!!(玩笑,實際上打算放到後面去講了。)


3、函數。

  函數是SQL 2000的新功能。一般的編程語言都有函數,我就不用解釋函數是什麼東東了。:)
  或許不少朋友會問:我用存儲過程不就可以了麼,我為什麼要使用函數?

  這裡特別指出的一點:fn可以嵌套在Select語句中使用,而sp不可以。

  這裡不打算大批特批一番游標了,當然,在我的程序裡面,基本拋棄了游標(這裡特別說明,是“基本”!因為還是有很多地方費用導游表不可的。),轉而采用了fn。游標太消耗資源了。受不了……我快要感動得要流淚了…
 
  fn其實要比sp要簡單得多。因為它的不確定性,從而也使他受到了不少的限制。
  舉個函數的小粒子:

    Create Function fnTest ( @i int )
     Returns bit
    As
    begin
     Declare @b bit
     if (Cast(@i As Float)/2)=(@i/2)
      Set @b= 1
     else
      Set @b= 0

     Return @b 
     
    end

       ----------------------------------------------------------------------
       以上代碼判斷@i是單數還是雙數。
                             --懶蟲 # SapphireStudio
             精彩世界,盡在3腿軟件網(www.chair3.com)!!
       -----------------------------------------------------------------------


   Use the Sample:


     Create Table #TT( fd1 int)
     Declare @i int
     Set @i=0
     While @i<=20
     begin
      Insert Into #tt Values(@i)
      Set @i=@i+1
     end

     Select fd1,
         '是否雙數'=dbo.fnTest(fd1)  --在這裡調用了函數,注意哈:函數之前一定要加上他的owner.
     From #tt

     Drop Table #tt


       ----------------------------------------------------------------------
       以上代碼虛擬一段數據,然後判斷數據表中是單數還是雙數。


                             --懶蟲 # SapphireStudio
             精彩世界,盡在3腿軟件網(www.chair3.com)!!
       -----------------------------------------------------------------------

    有了sp的編程基礎,寫fn也就不是什麼很難的事情了。剛才我提到了,fn受到限制頗多,這裡稍稍列舉:

     chair1. 只能調用確定性函數,不可以調用不確定函數。 比如,不可以調用GetDate(),以及自己定義的不確定性函數。
     chair2. 不可以使用動態SQL 。如:Execute, sp_ExecuteSQL (這是我最痛苦的事情了,痛哭中……)
     chair3. 不可以調用擴展存儲過程
     chair4. 不可以調用Update語句對表進行更新
     chair5. 不可以在函數內部創建表(Create TAble ),修改表(Alter TAble)

     等等……頭腦發昏中……反正稍微一些不可預測後果,無法返回後果的都不能用。


  5.事務

   什麼叫事務? 這些就是數據庫特有的術語了。懶蟲在這裡口頭解釋:就是把多件事情當做一件事情來處理。也就是大家同在一條船上,要活一起活,要over一起over !

   我為什麼要使用事務? 俺這裡再舉個很俗很俗的例子:

     俺到銀行存錢,於是有這麼幾個步驟:
       1、把錢交給工作人員;2、工作人員填單;3、將單子給我簽字;4、工作人員確認並輸入電腦。

   要是,要是我把錢交給工作人員之後,進行到3我簽字了。那哥們突然心髒病發作,over掉了,那,我的錢還沒有輸入電腦,但我卻交了錢又簽字確認了,而並沒有其他任何記錄。我豈不是要虧死了???我的血汗錢啊!趕緊退給我!!

   於是,在數據庫裡產生了這麼一個術語:事務(Transaction),也就是要麼成功,要麼失敗,並恢復原狀。
  
   還是寫程序把:

   Create Proc sp我去存款(@M Money , @iOperator Int)
   As
   Begin

您正在看的SQLserver教程是:《高性能的數據庫》 第四講 編程細節(2)。>    Declare @i int

    Begin Tran           --激活事務
     Exec @i=sp交錢 @m,@iOperator
     if @i<>0           --這裡一般用系統錯誤號 @@Error。 我這裡為了舉例子沒有用到。需要根據實際情況。
     begin
      Rollback Tran                   --回滾事務
      RaisError ('銀行的窗口太少了,我懶得排隊,不交了!:( ', 16, 1) with Log --記錄日志
      Return -1                     --返回錯誤號
     end

     Exec @i=sp填單 @m,@iOperator
     if @i<>0
     begin
      Rollback Tran                   --回滾事務
      RaisError ('銀行的哥們打印機出了點毛病,打印不出單子來,把錢退回來給我吧??', 16, 1) with Log
      Return -2                     
     end

     Exec @i=sp簽字 @m
     if @i<>0
     begin
      Rollback Tran                   --回滾事務
      RaisError ('我 靠?什麼爛銀行,換了3支筆都寫不出水來!!老子不存了!!不簽!', 16, 1) with Log 
      Return -3                     
     end

     Exec @i=sp輸入電腦 @m,@iOperator
     if @i<>0
     begin
      Rollback Tran                   --回滾事務
      RaisError ('什麼意思?磁盤空間已滿?好了好了,把錢給我,我到旁邊的這家銀行!', 16, 1) with Log 
      Return -4                     
     end
 
    Commit Tran        --提交事務
    Return 0
  End
 

       ----------------------------------------------------------------------
       以上是偽代碼,模擬我去存款的過程。
                             --懶蟲 # SapphireStudio
             精彩世界,盡在3腿軟件網(www.chair3.com)!!
       -----------------------------------------------------------------------

  事務的幾個要點 Begin Tran , @@Error(我這裡沒有用到,見上面的注釋) , Rollback Tran , Commit Tran。
  另:事務可以嵌套使用。這個時候需要命名。請參見SQL Server online help 。

  
  算是完成第四講了,寫這麼一篇也要幾個小時呢,挺累的。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved