《MySQL必知必會》第24章 使用遊標 中的bug:最後一行被重複INSERT
在看《MySQL必知必會》第24章 使用遊標的時候,手打儲存過程processorders()的時候,發現ordertotals總是有重複的一行:
經仔細校對原書的程式碼,沒有發現問題;上網看別人的部落格,讀書筆記,暫時沒有發現有人提到這個問題,還有的人程式碼跟書裡一樣,執行結果也跟書裡一樣(不過搞笑的是,我把他的程式碼複製下來,發現他程式碼中第一個DECLARE還打錯了),居然這麼玄學?
對書中程式碼一番仔細端詳後,感覺FETCH跟java中的Iterator的next()很像,next()沒有元素可以訪問的時候直接拋NoSuchElementException異常,當FETCH沒有元素可以訪問時會發生什麼呢?於是我把每獲取完一行資料後把done的狀態也INSERT到ordertotals表中,修改後程式碼如下:
CREATE TABLE IF NOT EXISTS ordertotals(order_num INT,
total DECIMAL(8, 2),
done BOOLEAN);
#清空資料
DELETE FROM ordertotals;
OPEN ordernumbers;
#具有bug的程式碼, 最後一行被INSERT兩次
REPEAT
FETCH ordernumbers INTO o; #從遊標中fetch資料到區域性變數
CALL ordertotal(o, 1, t);
INSERT INTO ordertotals(order_num, total, done )
VALUES(o, t, done);
UNTIL done END REPEAT;
結果如下:
可以說明FETCH不到資料時,MySQL不會報錯,也不會改變要填充的變數o的值,因此在使用變數o之前必須檢驗done的狀態,改進程式碼如下:
#正確的repeat程式碼, 需要兩次判斷, 略繁瑣 REPEAT FETCH ordernumbers INTO o; #從遊標中fetch資料到區域性變數 IF NOT done THEN CALL ordertotal(o, 1, t); INSERT INTO ordertotals(order_num, total, done) VALUES(o, t, done); END IF; UNTIL done END REPEAT;
輸出結果:
在這種情況下,其實使用WHILE或LOOP更加簡潔,完整程式碼如下:
#先刪除原來的儲存過程
DROP PROCEDURE IF EXISTS processorders;
DELIMITER $
CREATE PROCEDURE processorders()
BEGIN
#在定義遊標,控制代碼之前先定義區域性變數
DECLARE done BOOLEAN DEFAULT 0;
DECLARE o INT;
DECLARE t DECIMAL(8, 2);
DECLARE ordernumbers CURSOR
FOR
SELECT order_num FROM orders;
#在定義遊標之後定義控制代碼(handler)alter
#注意: 可以使用NOT FOUND來代替SQLSTATE '02000', 有助記憶
DECLARE CONTINUE HANDLER
FOR NOT FOUND
SET done = 1;
#刪除表
DROP TABLE IF EXISTS ordertotals;
#建立表
CREATE TABLE IF NOT EXISTS ordertotals(order_num INT,
total DECIMAL(8, 2),
done BOOLEAN);
#清空資料
DELETE FROM ordertotals;
OPEN ordernumbers; #開啟遊標
/*
#具有bug的程式碼, 最後一行被INSERT兩次
REPEAT
FETCH ordernumbers INTO o; #從遊標中fetch資料到區域性變數
CALL ordertotal(o, 1, t);
INSERT INTO ordertotals(order_num, total, done)
VALUES(o, t, done);
UNTIL done END REPEAT;
*/
/*
#正確的repeat程式碼, 需要兩次判斷, 略繁瑣
REPEAT
FETCH ordernumbers INTO o; #從遊標中fetch資料到區域性變數
IF NOT done THEN
CALL ordertotal(o, 1, t);
INSERT INTO ordertotals(order_num, total, done)
VALUES(o, t, done);
END IF;
UNTIL done END REPEAT;
*/
FETCH ordernumbers INTO o;
WHILE NOT done DO #注意有個DO
CALL ordertotal(o, 1, t);
INSERT INTO ordertotals(order_num, total, done)
VALUES(o, t, done);
FETCH ordernumbers INTO o; #嘗試獲取值
END WHILE;
/*
fetch_loop : LOOP
FETCH ordernumbers INTO o;
IF done THEN
LEAVE fetch_loop;
END IF;
CALL ordertotal(o, 1, t);
INSERT INTO ordertotals(order_num, total, done)
VALUES(o, t, done);
END LOOP;
*/
CLOSE ordernumbers;
END;
程式碼複製到編輯區時格式錯亂,調整好後正常瀏覽時又錯亂,所以沒辦法,將就著看吧,見諒。
相關推薦
《MySQL必知必會》第24章 使用遊標 中的bug:最後一行被重複INSERT
在看《MySQL必知必會》第24章 使用遊標的時候,手打儲存過程processorders()的時候,發現ordertotals總是有重複的一行: 經仔細校對原書的程式碼,沒有發現問題;上網看別人的部落格,讀書筆記,暫時沒有發現有人提到這個問題,還有的人程式碼跟書裡一
微軟必應-英雄會第三屆線上程式設計大賽:幾個Bing?【英雄會】
但現實生活中,我們也經常能看到一些毫無規則的字串,導致詞典無法正常收錄,不過,我們是否可以從無規則的字串中提取出正規的單詞呢? 例如有一個字串"iinbinbing",擷取不同位置的字元‘b’、‘i’、‘n’、‘g’組合成單詞"bing"。 若從1開始計數的話,
【MySQL必知必會】第6章 過濾數據
sea 錯誤 arch order by ice where 大量數據 子句 否則 1、使用WHERE子句 數據庫一般包含大量數據,所以一般不會檢索所有行。只檢索所需數據需要指定搜索條件(search criteria),搜索條件也稱為過濾條件(filter condi
【MySQL比知必會】第八章 用通配符進行過濾
通配符 操作符 範圍 name 使用 技巧 商品 -- rom 1、LIKE操作符 之前使用的操作符都是針對已知的數據,而使用通配符可以對未知數據也進行搜索。 通配符(wildcard):用來匹配值得一部分的特殊字符。 搜索模式(search pattern):
【MySQL必知必會】第十章 創建計算字段
客戶機 cat 第十章 去掉 quantity 字段 cme 引用 field 1、字段(field):一般與列(同義),經常互換使用,不過數據庫列一般稱之為列,字段通常用在計算字段的連接上。 2、拼接:將值連接到一起構成單個值。 註:多數DBMS使用+或||來實現拼接
【MySQL必知必會】第十三章 分組數據
num mysql 統計 where子句 rom 過濾 group by 大於 映射 1、創建分組 輸入: SELECT vend_id , COUNT(*) AS num_prods FROM products GROUP BY vend_id; 輸出
【MySQL必知必會】第十六章 創建高級聯結
類型 where子句 contact items order by 其他 mysq custom 必知必會 1、使用表別名 好處: a、縮短SQL語句。 b、允許在單條SELECT語句中多次使用相同的表。 輸入: SELECT cust_name,cu
讀書筆記《MySQL必知必會》之第十七章組合查詢
文章目錄 什麼是組合查詢 建立組合查詢 使用union 使用union的規則 union all的使用 組合查詢的結果的排序 總結 什麼是組合查詢 把
讀書筆記《MySQL必知必會》之第0章,書中基本資料的準備
文章目錄 指令碼下載地址 下載壓縮包 解壓檔案 建立資料庫 建表語句 填充資料語句 各個表的詳細描述 vendors表 products表
Mysql必知必會Note-第五章 排序檢索資料.md
排序資料 SQL檢索出的資料預設按照底層中出現的順序顯示,一般是資料最初的新增順序,但這種順序會受到資料更新的影響。因此,很多情景下都需要我們明確排序的順序,這裡我們可以通過ORDER BY子句實現。O
Mysql必知必會Note-第六章&第七章 過濾資料
第六章 過濾資料 WHERE子句 WHERE子句用於指定檢索條件(搜尋條件),WHERE子句在FROM子句之後給出。 【例項】 SELECT prod_name, prod_price FROM products WHERE prod_price = 2.5;
Mysql必知必會 第三章 使用Mysql
ror 特定 erro 數據 ble warning rom 創建 column 第三章 使用Mysql SQL語句和大小寫 請註意,SQL語句不區分大小寫,因此SELECT與select是相同的。同樣,寫成Select也沒有關系。許多SQL開發人員喜歡對所有SQL關鍵字使
mysql必知必會(1-12章)
這篇文章是《MySQL必知必會》自己的筆記。打算分為兩個部分,上半部分是截止到MySQL函式(第12章),下半部分到本書最後。 4 檢索資料 DISTINCT關鍵字指示MySQL只返回不同的值,需放在列名的前面。但是此關鍵字會應用於所有列而不是前置它的列 LIMIT子句可以跟檢索的開始行和行數,
mysql必知必會(13章)
目錄 分組資料 是什麼 為什麼用這個 怎麼用 基本使用 在分組中過濾 排序 分組資料 是什麼 分組資料是可以將資料分為多個邏輯組,以便對每個組進行匯聚計算的語句 為什麼用這個 前面提到的知識都
讀書筆記《MySQL必知必會》之第一章瞭解SQL
文章目錄 瞭解SQL 資料庫基礎 什麼是資料庫 什麼是表 列和資料型別 行 主鍵 關於主鍵最好的習慣 什麼是SQL
資料庫基礎整理之《MySQL必知必會》Ben Forta &&《資料庫基礎概論》(第五版)王珊
第一章 瞭解SQL 1.1資料庫基礎 1.1.1什麼是資料庫? 資料庫是一個以某種有組織的方式儲存的資料集合 資料庫(DB:DataBase)儲存有組織的資料的容器(通常是一個檔案或一組檔案) 資料庫是通過DBMS(資料庫管理系統)建立和操縱的容器 1.1.
MYSQL必知必會讀書筆記 第二十四章 使用遊標
MySQL檢索操作返回一組稱為結果集的行。這組返回的行都是與SQL語句相匹配的行。使用簡單的SELECT語句無法得到第一行、下一行和前十行。有時候需要在檢索出來的結果中前進或後退一行或多行。這就是使用遊標的原因。遊標(cursor)是一個儲存在MySQL伺服器上的資料庫查詢
《MYSQL必知必會》學習筆記(4-8章)
以下為《mysql必然知必會》第4-8章學習筆記,主要涉及查詢的select語句,where語句和like萬用字元。SELECT語句1.檢索一列Select name from products;2.檢索多列Select id,name,price fromproducts;
《MYSQL必知必會》
聚集函數 結構 則表達式 拼接 建議 支持 類型 習慣 功能 1、 同一個數據庫中不允許出現同名表;不同的數據庫中可以出現同名表2、 每一行記錄都用有一個key(一列或一組列作為key)3、 作為key的列不允許值為空(NULL)4、 多個列作為key時,多個列的組
《MYSQL必知必會2
pri upd delet rate 服務器 cal delete 生效 單獨 60、NULL是沒有值,空串是一個有效值61、主鍵只能使用不允許未NULL值的列62、每個表只允許一個auto_increment列63、不允許使用函數作為默認值,只支持常量64、InnoDB