T-SQL編程中的異常處理-異常捕獲(catch)與拋出異常(throw)

来源:http://www.cnblogs.com/wy123/archive/2017/04/21/6743515.html
-Advertisement-
Play Games

本文出處: http://www.cnblogs.com/wy123/p/6743515.html T-SQL編程與應用程式一樣,都有異常處理機制,比如異常的捕獲與異常的拋出,本文簡單介紹異常捕獲與異常拋出在T-SQL編程中的實際使用 。 異常處理簡單說明 異常捕獲在應用程式編程中非常常見,提供了處 ...


 

本文出處: http://www.cnblogs.com/wy123/p/6743515.html 

 

 T-SQL編程與應用程式一樣,都有異常處理機制,比如異常的捕獲與異常的拋出,本文簡單介紹異常捕獲與異常拋出在T-SQL編程中的實際使用 。

異常處理簡單說明

異常捕獲在應用程式編程中非常常見,提供了處理程式運行時出現的任何意外或異常情況的方法
剛畢業的時候對於異常處理迷茫不解,尤其是catch中又throw,既然catch或者不catch,都會throw,為什麼要catch後再throw?catch中到底要做什麼處理?
後來接觸的多了開始慢慢理解了異常處理這個機制,在應用程式和T-SQL中應該是類似的
可以簡單地這樣理解:
對於UI層面, 異常捕獲,個人理解就是對於可能發生異常的代碼段進行捕獲處理,給予用戶友好的提示信息,
防止應用程式崩潰(或者拋給給用戶一個後臺代碼錯誤的頁面)的一種做法。
如果是底層方法(這個底層可以這麼理解A方法調用B方法,B方法又調用C方法,C方法就是底層方法),
異常處理可以是在捕獲之後繼續拋出給上層調用者,讓調用者知道它調用的方法發生了什麼問題。
對於發生了異常的代碼本身,要記錄下來異常的原因,以便於問題的排查。
比如C方法中發生了異常,要告訴調用他的B方法“我發生了異常,異常原因是***”, 這種的話C就要拋出異常,
同時C要記錄異常的信息(通過不同方式將上面的異常原因記錄下來),供後繼排查問題作參考。

  以上是理論基礎,下麵以T-SQL中的異常處理為例,簡單介紹一下異常處理方式和要做的事情,T-SQL中的異常處理。

 

catch塊中處理異常信息

  首先藉助下麵兩張表來做示例說明。一張產品信息表,有產品Id和價格信息

  

  下麵將通過一個新增產品信息的存儲過程說明如何進行異常處理
  如下是新增產品信息的存儲過程,存超過程根據參數,插入到Product表中,

  

  在插入數據的過程中,進行了異常捕獲,在catch代碼中,有兩個操作,
  第一步是將異常信息插入ExceptionLog,當然,這個異常信息的格式可以自己定義,第二步拋出異常(throw),就基於上面的理論
  首先為什麼要記錄異常,這個很容易理解,A寫的存儲過程給B去調用,B調用的時候發生了異常,將異常信息記錄下來有利於A去排查異常的具體原因
  然後拋出異常,目的是告訴B,執行存儲過程的時候產生了異常,你的操作並沒有成功執行。
  比如下麵代碼,執行的時候發生了主鍵衝突異常,throw的作用就是告訴調用者,執行存儲過程的時候發生了異常,並將詳細的錯誤信息拋出

  當然實際中常見的異常也比較多,比如死鎖,主外鍵衝突,執行超時,沒有操作許可權等等各種無法估計到的異常,包括記錄異常信息的格式,可以自由選擇。

  

  此時觀察Catch中記錄的ExceptionLog信息,也記錄了下麵
  記錄下來的異常信息目的是事後排查問題,與上面直接“拋出”的異常信息作用不同的是,
  一個是在異常的發生的時候告訴調用者,拋出異常是標明當前執行的代碼發生了異常,ExceptionLog記錄異常信息是做排查分析異常原因使用

  如果不拋出異常,比如如下的代碼,註釋掉throw語句,等於是在catch塊中單純地記錄下來異常之後“吃掉”異常,會出現什麼情況

  

  比如在Product表中已經存在Id = 1的記錄的情況下,執行如下代碼是失敗,
  但是客戶端並沒有任何提示,調用方並不知道發生了什麼,調用存儲過程的時候到底是失敗了還是成功了?沒有一個明確的答案。
  這就是catch中吃掉異常的後果。
  因此正常情況下,catch中記錄完異常之後,要“拋出”異常,當異常發生的時候,明確地告訴調用方發生了什麼問題。

  

 

使用throw顯式拋出異常

  某些情況下需要主動拋出異常的方式來中斷邏輯的執行,什麼意思?
  就是說當前的邏輯,只有在滿足一定的條件下才能執行,如果條件不滿足,就要明確告訴調用方,你的條件不滿足,當前邏輯無法正常執行。
  舉個例子,還是剛纔插入產品信息的存儲過程,如下
  當插入產品信息的時候,只有產品價格大於0才是有效的產品信息,否則無法插入,
  此時就可以通過拋出異常的方式明確地告訴調用者(當然也有其他方式),你的參數不合法,使用throw拋出自定義異常,強制中斷代碼的執行。

  

  上面的方式只是舉個示例說明,正常情況下,調用方傳遞過來的參數都是經過校驗的,不會發生太低級的錯誤。
  當然,實際應用中應該比這個複雜的多,無法保證調用者都是從用戶圖形界面(UI)發起的,也就是說無法通過直接的預先處理來確保輸入信息的合法性
  對於類似上面的存儲過程
  首先無法保證調用方永遠傳遞過來的參數是合法有效的,其次連調用者也無法確保自己的生成的參數的邏輯永遠不會發生錯誤。
  此時對於邏輯上要求非常嚴謹的程式來說,就需要做類似上面主動拋出異常了來中斷代碼的執行了。
  當然上面問題的處理方式也不止這一種,只是說異常處理的應用場景和方式。

  

throw語句的使用

  最後說一下throw語句,

  

  throw是必raiserror更加方便和直觀的異常拋出方式,也是推薦的異常處理方式,具體差異網上一大把就不多說了
  throw有兩種使用方式,拋出自定義異常和直接在catch塊中拋出異常。
  拋出自定義異常的時候有三個必須參數,下麵會細說,catch塊中可以直接用throw不需要任何參數的方式拋出捕獲到的異常
  throw語句的前一句需要一分號結尾,前一句又不能保證一定有分號,
  所以可以直接把分號寫在throw的前面,比如文中的;throw 50000,'Price can not be less than 0',1 寫法
  當拋出自定義錯誤的時候,throw語句有三個參數,參考如下
  throw語句安全級別預設為16並且不會被修改,換句話說就是throw語句執行之後將拋出錯誤,打斷當前Session的批處理語句,throw後面的語句將不會執行
  第一個參數是錯誤號,用戶自定義錯誤號要大於50000(50000 to 2147483647)
  第二個參數是自定義錯誤信息內容,可以根據需要自定義
  第三個參數是Error State,他的作用是可以標記異常發生的位置,
     比如同樣是“參數不能小於0”的錯誤提示,整個存儲過程中有可能有兩個地方進行同樣的校驗
       就可以在兩個地方使用Error State不同分別來拋出異常;
       throw 50000,'Price can not be less than 0',1
       throw 50000,'Price can not be less than 0',2,
      因為Error State不同,就可以根據具體的Error State更加方便地知道是哪個地方發生了異常,參考

  

throw語句存儲自定義異常到messages系統表
可以將自定義的異常信息加入到sys.messages 系統表中,先加英文的,再加中文的。
然後使用的時候可以使用這個預定義的message,而不是每次寫一個字元串

EXEC sp_addmessage   
    @msgnum = 50001,   
    @severity = 16,   
    @msgtext = N'%s can not be less than 0',   
    @lang = 'us_english';  
  
EXEC sp_addmessage   
    @msgnum = 50001,   
    @severity = 16,   
    @msgtext = N'%s 不能小於0',   
    @lang = '簡體中文';  

如下,存儲過程中先通過FORMATMESSAGE來格式化異常信息,然後使用throw 50001, @msg, 1;的方式拋出異常

  然後在調用存儲過程是的時候,如下是異常被觸發時候的拋出自定義異常的場景。

  

  

總結:本文簡單介紹了T-SQL編程中的異常處理方式,異常處理的時候可以通過捕獲異常信息並記錄下來,確保代碼的維護性,也為問題排查提供參考依據。
     也可以在確保滿足業務邏輯的條件下,主動拋出自定義異常的方式終止代碼的執行,來確保業務邏輯的正確性。

    

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 圖片載入框架: Glide https://github.com/bumptech/glide Android-Universal-Image-Loader https://github.com/nostra13/Android-Universal-Image-Loader Picasso http ...
  • 運行報錯的原因是sdk沒有下載完整 解決辦法: 1,打開sdk manage。分別下載android support repository、Google play services、google repository這三個sdk的包,當然最新的包也要下載。 下載Extras中選中的三個即可 2,打開 ...
  • < SELECT names Language: English • 中文 namecontinent Afghanistan Asia Albania Europe Algeria Africa Andorra Europe Angola Africa .... name:國家名稱continen ...
  • 對於剛入門的同學來說 可能很少單獨安裝Mysql (大多都使用集成包 例如:wampserver、PHPstudy。因本人寫php 這裡就不多說了)。 由於是第一次安裝百度了大量的信息 此條信息經驗證 可順利安裝 Mysql 地址:http://www.jb51.net/article/92158. ...
  • 資料庫表常用術語 關係 關係即二維表,每一個關係都有一個關係名,就是表名記錄 表中的行欄位 表中的列 也稱屬性域 取值範圍關聯 不同資料庫表之間的數據聯繫關鍵字 屬性或屬性的組合,可以用於唯一標識一條記錄外部關鍵字 表中的一個欄位,不是本表中的關鍵字,而是其他表的關鍵字 數據冗餘 資料庫表中的重覆數 ...
  • sql 使用系統存儲過程 sp_send_dbmail 發送電子郵件語法: 參數參考地址:https://docs.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-send-dbmail-transac ...
  • https://dev.mysql.com/downloads/mysql/ ...
  • 索引 1.主鍵索引 作用:唯一約束和提高查詢速度 2.普通索引 作用:提高查詢速度 3.唯一索引 作用:唯一約束和提高查詢速度 4.主鍵和唯一索引的區別 主鍵是一種約束,唯一索引是一種索引,兩者在本質上是不同的。主鍵創建後一定包含一個唯一性索引,唯一性索引並不一定就是主鍵。唯一性索引列允許空值,而主 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...