存儲過程補充——定義條件、處理程序及游標使用

文章目錄

  • 1. 定義條件與處理程序
    • 1.1 定義條件
    • 1.2 處理程序
    • 1.3 案例演示
  • 2. 游標
    • 2.1 使用游標
      • 第一步,聲明游標
      • 第二步,打開游標
      • 第三步,使用游標(從游標中取得數據)
      • 第四步,關閉游標
    • 2.2 舉例
    • 2.3 小結


在 MySQL 數據庫的開發過程中,為了提升程序的健壯性、可靠性以及數據處理的靈活性,常常需要面對錯誤處理和結果集逐行操作的問題。定義條件與處理程序、游標就是 MySQL 提供的強大工具,它們分別用于更精細地控制和處理錯誤異常情況,以及對查詢結果集中的每一行數據進行訪問和操作。本文將深入介紹這些重要特性,通過詳細的語法說明和豐富的案例演示,幫助大家更好地掌握和運用它們。


1. 定義條件與處理程序

在 MySQL 中,定義條件處理程序 主要用于存儲過程、函數、觸發器等復雜的程序單元里,幫助開發者對錯誤和異常情況進行更精細的控制和處理,從而提升程序的健壯性和可靠性。

  • 定義條件 是事先定義程序執行過程中可能遇到的問題;
  • 處理程序 定義了在遇到問題時應當采取的處理方式,保證存儲過程或函數在遇到警告或錯誤時能繼續執行。

1.1 定義條件

定義條件是一種命名異常的方式,將一個錯誤碼或錯誤條件與一個自定義的名稱關聯起來,讓代碼更具可讀性和可維護性。

當程序執行過程中出現錯誤時,使用自定義的名稱來指代特定的錯誤,避免在代碼里直接使用錯誤碼,使代碼更易理解和管理。

  • 定義條件使用DECLARE語句,語法格式如下:
DECLARE 錯誤名稱 CONDITION FOR 錯誤碼(或錯誤條件)
  • 錯誤碼的說明:
  • MySQL_error_codesqlstate_value 都可以表示MySQL的錯誤。
    • MySQL_error_code數值類型 錯誤代碼。
    • sqlstate_value 是長度為5的 字符串類型 錯誤代碼。
  • 例如,在 ERROR 1418 (HY000) 中,1418是MySQL_error_code,'HY000’是sqlstate_value。
  • 例如,在 ERROR 1142 (42000) 中,1142是MySQL_error_code,'42000’是sqlstate_value。
  • 例如,定義“Field_Not_Be_NULL”錯誤名與MySQL中違反非空約束的錯誤類型是“ERROR 1048 (23000)”對應。
#使用MySQL_error_code
DECLARE Field_Not_Be_NULL CONDITION FOR 1048;#使用sqlstate_value
DECLARE Field_Not_Be_NULL CONDITION FOR SQLSTATE '23000';
  • 例如,定義"ERROR 1148(42000)"錯誤,名稱為command_not_allowed
#使用MySQL_error_code
DECLARE command_not_allowed CONDITION FOR 1148;#使用sqlstate_value
DECLARE command_not_allowed CONDITION FOR SQLSTATE '42000';

1.2 處理程序

處理程序用于指定當特定錯誤或異常發生時要執行的操作。在程序運行過程中,一旦出現預定義的錯誤或異常,就會執行相應的處理程序,從而避免程序崩潰,同時可以根據具體情況進行錯誤日志記錄、回滾事務等操作。

  • 定義處理程序時,使用 DECLARE語句 的語法如下:
DECLARE 處理方式 HANDLER FOR 錯誤類型 處理語句;

處理方式:處理方式有3個取值:CONTINUEEXITUNDO

  • CONTINUE :表示遇到錯誤不處理,繼續執行。
  • EXIT :表示遇到錯誤馬上退出。
  • UNDO :表示遇到錯誤后撤回之前的操作。MySQL中暫時不支持這樣的操作。

錯誤類型(即條件)可以有如下取值:

  • SQLSTATE '字符串錯誤碼' :表示長度為5的sqlstate_value類型的錯誤代碼;
  • MySQL_error_code :匹配數值類型錯誤代碼;
  • 錯誤名稱 :表示DECLARE … CONDITION定義的錯誤條件名稱。
  • SQLWARNING :匹配所有以01開頭的SQLSTATE錯誤代碼;
  • NOT FOUND :匹配所有以02開頭的SQLSTATE錯誤代碼;
  • SQLEXCEPTION :匹配所有沒有被SQLWARNING或NOT FOUND捕獲的SQLSTATE錯誤代碼;

處理語句:如果出現上述條件之一,則采用對應的處理方式,并執行指定的處理語句。語句可以是 像“ SET 變量 = 值 ”這樣的簡單語句,也可以是使用 BEGIN … END 編寫的復合語句。

  • 定義處理程序的幾種方式,代碼如下:
#方法1:捕獲sqlstate_value
DECLARE CONTINUE HANDLER FOR SQLSTATE '42S02' SET @info = 'NO_SUCH_TABLE';#方法2:捕獲mysql_error_value
DECLARE CONTINUE HANDLER FOR 1146 SET @info = 'NO_SUCH_TABLE';#方法3:先定義條件,再調用
DECLARE no_such_table CONDITION FOR 1146;
DECLARE CONTINUE HANDLER FOR NO_SUCH_TABLE SET @info = 'NO_SUCH_TABLE';#方法4:使用SQLWARNING
DECLARE EXIT HANDLER FOR SQLWARNING SET @info = 'ERROR';#方法5:使用NOT FOUND
DECLARE EXIT HANDLER FOR NOT FOUND SET @info = 'NO_SUCH_TABLE';#方法6:使用SQLEXCEPTION
DECLARE EXIT HANDLER FOR SQLEXCEPTION SET @info = 'ERROR';

1.3 案例演示

在存儲過程中,定義處理程序,捕獲 sqlstate_value 值,當遇到 MySQL_error_code值 為1048 時,執行 CONTINUE 操作,并且將 @proc_value 的值設置為-1。

DELIMITER //CREATE PROCEDURE UpdateDataNoCondition()BEGIN#定義處理程序DECLARE CONTINUE HANDLER FOR 1048 SET @proc_value = -1;SET @x = 1;UPDATE employees SET email = NULL WHERE last_name = 'Abel';SET @x = 2;UPDATE employees SET email = 'aabbel' WHERE last_name = 'Abel';SET @x = 3;END //
DELIMITER ;

調用過程:

mysql> CALL UpdateDataWithCondition();
Query OK, 0 rows affected (0.01 sec)
mysql> SELECT @x,@proc_value;
+------+-------------+
|   @x | @proc_value |
+------+-------------+
|    3 |          -1 |
+------+-------------+
1 row in set (0.00 sec)

在存儲過程中,定義處理程序,當執行 SELECT * FROM non_existent_table; 語句時,如果表不存在(錯誤碼 1146),就會觸發處理程序,記錄錯誤日志,然后繼續執行后續語句。

-- 創建錯誤日志表
CREATE TABLE error_log (id INT AUTO_INCREMENT PRIMARY KEY,error_message VARCHAR(255),error_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);DELIMITER //CREATE PROCEDURE test_procedure()
BEGIN-- 定義條件DECLARE table_not_found CONDITION FOR 1146;-- 定義處理程序DECLARE CONTINUE HANDLER FOR table_not_foundBEGIN-- 記錄錯誤日志INSERT INTO error_log (error_message) VALUES ('Table not found');-- 可以在這里添加其他處理邏輯END;-- 嘗試查詢一個可能不存在的表SELECT * FROM non_existent_table;-- 繼續執行后續語句SELECT 'Procedure continues...';
END //DELIMITER ;    

2. 游標

游標是指向查詢結果集中某一行的指針,通過游標可以在結果集中進行移動,從而對每一行數據進行訪問和處理。在 SQL 語句中,查詢操作通常會返回一個結果集,而游標提供了一種機制,允許按順序逐個處理結果集中的行,這在需要對每一行數據進行復雜操作時非常有用。

在這里插入圖片描述

2.1 使用游標

游標必須在聲明處理程序之前被聲明,并且變量和條件還必須在聲明游標或處理程序之前被聲明。

第一步,聲明游標

在MySQL中,使用 DECLARE 關鍵字來聲明游標,其語法的基本形式如下:

DECLARE cursor_name CURSOR FOR select_statement;

這個語法適用于 MySQL,SQL Server,DB2 和 MariaDB。如果是用 Oracle 或者 PostgreSQL,需要寫成:

DECLARE cursor_name CURSOR IS select_statement;

要使用 SELECT 語句來獲取數據結果集,而此時還沒有開始遍歷數據,這里 select_statement 代表的是 SELECT 語句,返回一個用于創建游標的結果集。比如:

DECLARE cur_emp CURSOR FOR
SELECT employee_id,salary FROM employees;DECLARE cursor_fruit CURSOR FOR
SELECT f_name, f_price FROM fruits ;

第二步,打開游標

打開游標的語法如下:

OPEN cursor_name;

當我們定義好游標之后,如果想要使用游標,必須先打開游標。打開游標的時候 SELECT 語句的查詢結果集就會送到游標工作區,為后面游標的逐條讀取結果集中的記錄做準備。

OPEN cur_emp ;

第三步,使用游標(從游標中取得數據)

從游標中取得數據語法如下:

FETCH cursor_name INTO var_name [, var_name] ...

這句的作用是使用 cursor_name 這個游標來讀取當前行,并且將數據保存到 var_name 這個變量中,游標指針指到下一行。如果游標讀取的數據行有多個列名,則在 INTO 關鍵字后面賦值給多個變量名即可。

注意:var_name必須在聲明游標之前就定義好。

FETCH cur_emp INTO emp_id, emp_sal ;

注意:游標的查詢結果集中的字段數,必須跟 INTO 后面的變量數一致,否則,在存儲過程執行的時候,MySQL 會提示錯誤。

第四步,關閉游標

關閉游標語法如下:

CLOSE cursor_name;

當使用完游標后需要關閉掉該游標。因為游標會占用系統資源 ,如果不及時關閉,游標會一直保持到存儲過程結束,影響系統運行的效率。而關閉游標的操作,會釋放游標占用的系統資源。

關閉游標之后,我們就不能再檢索查詢結果中的數據行,如果需要檢索只能再次打開游標。

CLOSE cur_emp;

2.2 舉例

創建存儲過程“get_count_by_limit_total_salary()”,聲明IN參數 limit_total_salary,DOUBLE類型;聲明 OUT參數total_count,INT類型。函數的功能可以實現累加薪資最高的幾個員工的薪資值,直到薪資總和 達到limit_total_salary參數的值,返回累加的人數給total_count。

DELIMITER //CREATE PROCEDURE get_count_by_limit_total_salary(IN limit_total_salary DOUBLE,OUT total_count INT)
BEGINDECLARE sum_salary DOUBLE DEFAULT 0; #記錄累加的總工資DECLARE cursor_salary DOUBLE DEFAULT 0; #記錄某一個工資值DECLARE emp_count INT DEFAULT 0; #記錄循環個數#定義游標DECLARE emp_cursor CURSOR FOR SELECT salary FROM employees ORDER BY salary DESC;#打開游標OPEN emp_cursor;REPEAT#使用游標(從游標中獲取數據)FETCH emp_cursor INTO cursor_salary;SET sum_salary = sum_salary + cursor_salary;SET emp_count = emp_count + 1;UNTIL sum_salary >= limit_total_salaryEND REPEAT;SET total_count = emp_count;#關閉游標CLOSE emp_cursor;
END //
DELIMITER ;

2.3 小結

游標為逐條讀取結果集中的數據,提供了完美的解決方案。跟在應用層面實現相同的功能相比,游標可以在存儲程序中使用,效率高,程序也更加簡潔。

但同時也會帶來一些性能問題,比如在使用游標的過程中,會對數據行進行加鎖 ,這樣在業務并發量大的時候,不僅會影響業務之間的效率,還會消耗系統資源 ,造成內存不足,這是因為游標是在內存中進行的處理。

建議養成用完之后就關閉的習慣,這樣才能提高系統的整體效率。


總之,定義條件與處理程序、游標在 MySQL 開發中各有其獨特價值。前者讓錯誤處理更精細,增強程序健壯性;后者為結果集逐行處理提供高效簡潔方案。但使用游標時要警惕性能問題,及時關閉以提升系統效率。希望大家能借此提升 MySQL 開發能力。


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/79800.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/79800.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/79800.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

藍橋杯單片機國賽模板——基于柳離風模板

藍橋杯單片機國賽模板——基于柳離風模板 文章目錄 藍橋杯單片機國賽模板——基于柳離風模板一、工程結構二、USER文件夾main.c 三、BSP文件夾1、sys2、display3、key4、timer5、iic6、ds13027、onewire8、uart9、ultrasound 四、源碼五、內存不夠 一、工程結構 與省賽模板相比…

C與指針——常見庫函數

字符串 #include<stdlibs.h> int abs(int); long labs(long); int rand(void);//0-RAND_MAX //字符串轉值 int atoi(const char*); long atol(const char*); float atof(const char*);數學\排序 #include<math.h> \\常見三角&#xff0c;sqrt(); exp(); double p…

數學復習筆記 2

前言 朋友和我討論了一個二重積分題&#xff0c;非常有意思。內容非常細致。整理如下&#xff1a; 二重積分 題目來源是 1000 上面的 16 題&#xff0c;積分區域是一個偏心圓&#xff0c;偏心圓的圓心在 y 軸上面&#xff0c;偏心圓是關于 y 軸對稱的&#xff0c;可以看關于…

Javaweb項目--Mybatis,導入com.mysql.cj.jdbc.Driver時報錯,Cannot resolve class ‘Driver‘

目錄 問題解決方法結果 問題 在項目java文件下&#xff0c;包文件下的application.properties文件中&#xff0c;項目目錄如下&#xff1a; 報錯信息如下&#xff1a; 解決方法 在pom.xml文件中增加此依賴 結果 報錯信息消失

分布式-redisson

分布式鎖redisson 加鎖流程緩存相關問題 加鎖流程 redisson底層通過lua腳本實現加鎖的原子性lock動作包含&#xff1a;加鎖、設置超時時間、鎖續命未獲取到鎖的線程通過獲取信號量許可等待&#xff0c;所釋放后釋放信號量通知等待線程 緩存相關問題 緩存失效&#xff08;擊穿…

Java基礎學完,繼續深耕(0505)Linux 常用命令

昨天休息了一天&#xff0c;沒有寫csdn 昨天和今天把Linux大概學了一下。總結一下常用命令&#xff0c;總結的不全。 Linux目錄結構 / 是所有目錄的頂點 目錄結構像一顆倒掛的樹 注意&#xff1a;/itheima 是絕對路徑&#xff0c;是指根目錄 / 下的itheima目錄 itheima…

【AI論文】Sadeed:通過小型語言模型推進阿拉伯語變音

摘要&#xff1a;由于語言的形態豐富&#xff0c;阿拉伯語文本的變音符號仍然是自然語言處理中一個持續的挑戰。 在本文中&#xff0c;我們介紹了一種基于微調解碼器語言模型的新方法Sadeed&#xff0c;該方法改編自Kuwain 1.5B Hennara等人[2025]的模型&#xff0c;該模型最初…

學習海康VisionMaster之亮度測量

一&#xff1a;進一步學習了 今天學習下VisionMaster中的亮度測量&#xff1a;這個和前面學習的都不一樣了&#xff0c;這個是測量ROI區域內的平均亮度等 1&#xff1a;什么是亮度測量&#xff1f; 我們工業上用的相機里面有一個感光芯片&#xff08;CCD/CMOS&#xff09;&…

學習路線(python)

Python從初級到專家的學習路線# 初級階段 (1-3個月)基礎語法數據結構文件操作推薦資源 中級階段 (3-6個月)面向對象編程常用模塊錯誤處理進階特性推薦資源 高級階段 (6-12個月)并發編程性能優化元編程設計模式推薦資源 專業方向 (選擇1-2個方向深入)Web開發數據分析/科學計算機…

svn文件提交失敗

這里寫自定義目錄標題 1報錯項目2.解決辦法1.安裝sqlite3.exe 數據庫2.sqlite3.exe放到svn 項目的主目錄下&#xff0c;和.svn目錄同級下, 可以直接在數據庫目錄下執行cmd命令。3.在當前目錄下 cmd 運行命令 4.最后再項目的文件夾下&#xff0c;看是否可以 clean up了。--成功&…

調試——GDB、日志

調試——GDB、日志 1. gdb常用指令2. 如何生成core文件并調試&#xff1f;3. 如何調試正在運行的程序4. 調試多進程程序5. 調試多線程程序6. log日志 gcc編譯器可以幫我們發現語法錯誤&#xff0c;但是對業務邏輯錯誤卻無能為力。當我們想找出邏輯錯誤時&#xff0c;就需要調試…

redis----通用命令

文章目錄 前言一、運行redis二、help [command]三、通用命令 前言 提示&#xff1a;這里可以添加本文要記錄的大概內容&#xff1a; 學習一些通用命令 以下操作在windows中演示 提示&#xff1a;以下是本篇文章正文內容&#xff0c;下面案例可供參考 一、運行redis 我們先c…

CatBoost算法原理及Python實現

一、概述 CatBoost 是在傳統GBDT基礎上改進和優化的一種算法&#xff0c;由俄羅斯 Yandex 公司開發&#xff0c;于2017 年開源&#xff0c;在處理類別型特征和防止過擬合方面有獨特優勢。 在實際數據中&#xff0c;存在大量的類別型特征&#xff0c;如性別、顏色、類別等&#…

五一假期作業

sub_process.c #include <stdio.h> // 標準輸入輸出庫 #include <pthread.h> // POSIX線程庫 #include <sys/ipc.h> // IPC基礎定義&#xff08;如消息隊列/共享內存&#xff09; #include <sys/msg.h> // 消息隊列操作相關…

Liunx安裝Apache Tomcat

目錄 一、了解tomcat 二、下載 三、啟動tomcat 四、網頁訪問tomcat 五、Tomcat修改默認8080端口 六、Tomcat創建項目步驟-實現項目對外訪問 一、了解tomcat Apache Tomcat 是一個開源的 Java Servlet 容器 和 Web 服務器&#xff0c;主要用于運行基于 Java 的 Web 應用…

破局者手冊 Ⅰ:測試開發核心基礎,解鎖未來測試密鑰!

目錄 一、引入背景 二、軟件測試基礎概念 2.1 軟件測試的定義 2.2 軟件測試的重要性 2.3 軟件測試的原則 三、測試類型 3.1 功能測試 3.2 接口測試 3.2.1 接口測試的概念 3.2.2 接口測試的重要性 3.2.3 接口測試的要點 3.2.4 接口測試代碼示例&#xff08;Python r…

C++ 適配器模式詳解

適配器模式&#xff08;Adapter Pattern&#xff09;是一種結構型設計模式&#xff0c;它允許不兼容的接口之間能夠協同工作。 概念解析 適配器模式的核心思想是&#xff1a; 接口轉換&#xff1a;將一個類的接口轉換成客戶希望的另一個接口 兼容性&#xff1a;使原本由于接…

【NLP】 28. 語言模型的評估方式:MRR, PERPLEXITY, BLEU, WER從困惑度到實際效果

語言模型的評估方式&#xff1a;從困惑度到實際效果 評估語言模型&#xff08;LLM&#xff09;是否有效&#xff0c;并不僅僅是看它生成句子是否“聽起來通順”&#xff0c;我們需要定量的指標對模型性能做出系統性評價。評估方法主要分為兩大類&#xff1a; 內在評價&#x…

Java 企業級開發設計模式全解析

Java 企業級開發設計模式全解析 在 Java 企業級開發的復雜領域中&#xff0c;設計模式如同精湛的工匠工具&#xff0c;能夠幫助開發者構建高效、可維護、靈活且健壯的軟件系統。它們是無數開發者在長期實踐中總結出的解決常見問題的最佳方案&#xff0c;掌握這些模式對于提升開…

小剛說C語言刷題—1038編程求解數學中的分段函數

1.題目描述 編程求解數學中的分段函數。 …………x1 (當 x>0 )。 yf(x)…0 (當 x0 )。 ………x?1 (當 x<0 )。 上面描述的意思是&#xff1a; 當x>0 時 yx1 ; 當 x0 時 y0 ; 當 x<0 時 yx?1 。 輸入 輸入一行&#xff0c;只有一個整數x(?30000≤x≤30…