Mysql - 存儲過程/自定義函數

来源:http://www.cnblogs.com/elvinle/archive/2016/12/27/6225535.html
-Advertisement-
Play Games

在資料庫操作中, 尤其是碰到一些複雜一些的系統, 不可避免的, 會用到函數/自定義函數, 或者存儲過程. 實際項目中, 自定義函數和存儲過程是越少越好, 因為這個東西多了, 也是一個非常難以維護的地方. 一、自定義函數 1. 例子 mysql提供的函數, 不在這一篇講了, 這裡主要貼一下自定義函數. ...


在資料庫操作中, 尤其是碰到一些複雜一些的系統, 不可避免的, 會用到函數/自定義函數, 或者存儲過程. 

實際項目中, 自定義函數和存儲過程是越少越好, 因為這個東西多了, 也是一個非常難以維護的地方. 

一、自定義函數

1. 例子

mysql提供的函數, 不在這一篇講了, 這裡主要貼一下自定義函數.  前臺js插件裡面有一個zTree, 不知道大家知不知道, 效果是這樣的:

這種結構的數據, 在資料庫中, 我一般會設計到一個表中

create table ztree
(
    id int(11) not null PRIMARY key auto_increment,
    name varchar(20) not null comment '節點名稱',
    pid int(11) not null comment '父節點id'
) comment '樹形表';

然後插入數據:

如果你拿到一個節點A, 想要獲取A下麵的節點(不只是子節點哦), 那麼通過一個自定義函數來做, 能方便許多.

delimiter $
DROP FUNCTIONIF EXISTS GetChildNodes ;
CREATE FUNCTION `GetChildNodes` (`rootId` INT) RETURNS VARCHAR (1000) BEGIN DECLARE res VARCHAR (1000) DEFAULT '-1'; DECLARE temp VARCHAR (1000) DEFAULT CAST(rootId AS CHAR); -- SET res = '' ; -- SET DECLARE = CAST(rootId AS CHAR) ; WHILE DECLARE IS NOT NULL DO SET res = CONCAT(res, ',', temp) ; SELECT GROUP_CONCAT(id) INTO temp FROM ztree WHERE FIND_IN_SET(pid, temp) > 0 ; END WHILE ; RETURN res ; END$ delimiter ;

 這裡, 我將res的值預設為-1, 這樣的話, 就可以在查詢的時候, 將這個結果拼入sql中, 還是比較方便的. 

mysql中, 自定義函數的調用, 使用 select, 接下來, 就看一下之前的成果:

SELECT GetChildNodes (2);

 

2. 語法

自定義函數與存儲過程有一個很明顯的地方, 就是, 自定義函數是有返回值的, 並且需要通過return的方式返回. 而存儲過程沒有return返回值. 但是, 程式在執行存儲過程的時候, 其實是可以得到一個結果集的.

語法:

  create function 函數名 (參數名 參數類型) returns 參數類型

  begin

  return result;

  end

 1) 自定義函數傳參與存儲過程不同, 不需要指定 in/out. 

 2) 自定義函數可以用到別的sql語句中, 可以單獨使用, 也可以混入別的sql中使用

 

二、存儲過程

既然前面已經講了自定義函數的語法, 那這裡就先上存儲過程的語法, 以便比較

1. 語法

  CREATE PROCEDURE 存儲過程名稱 (IN 參數名 參數類型, OUT 參數名 參數類型)

  begin

  end

這裡的參數都是非必須的, 可以有 IN/OUT 都是可以沒有的

從語法格式上看, 與自定義函數的框架大致是一樣的, 只是其中的細節不同.

1) 存儲過程沒有return返回值, 但是卻可以通過OUT的方式, 來修改傳入的參數, 可以當做是一種返回值, 

2) 存儲過程在end之前, 可以加上一句 select語句, 以便程式讀取到結果集. 所以存儲過程能返回的值其實更多

3) 並不能混入別的sql中使用, 只能通過 call 的方式, 單獨使用

 

2. 例子

之前的項目中, 我碰到一個生成流水號的功能. 當時, 我是通過藉助資料庫的方式, 來生成流水號的. 

我這裡的流水號, 由首碼, 時間, 流水碼 三部分組成

先建一張流水號表

CREATE TABLE `serialno` (
  `Id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Id',
  `Pre` varchar(10) NOT NULL COMMENT '編號',
  `Description` varchar(10) DEFAULT NULL COMMENT '說明',
  `Res` varchar(20) DEFAULT NULL COMMENT '流水號(不加編號的)',
  PRIMARY KEY (`Id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='流水號表'

有了這張表, 就可以開始存儲過程了.

delimiter $
drop PROCEDURE if EXISTS p_GetSerialNo;
CREATE PROCEDURE `p_GetSerialNo`(IN preValue VARCHAR(10), IN preDate VARCHAR(10),IN des varchar(20), in length int)
BEGIN
    DECLARE  t_error INT DEFAULT 0;
    DECLARE  resValue VARCHAR(20) DEFAULT NULL;
    -- DECLARE
    --     CONTINUE HANDLER FOR SQLEXCEPTION,
    --     SQLWARNING,
    --     NOT FOUND
    -- SET t_error = 1;
    
    START TRANSACTION;

    SELECT Res INTO resValue FROM serialno WHERE Pre=preValue;
    IF resValue IS NULL  THEN
        SET resValue= CONCAT(preDate, LPAD(1, length, '0'));
        INSERT INTO serialno (Pre, Description, Res) VALUES (preValue, des, resValue);
    ELSE
        IF preDate =  (SUBSTRING(resValue,1,8) + '0') THEN
            SET resValue = CAST(resValue AS SIGNED) + 1;
            if preDate <> SUBSTRING(resValue,1,8) THEN
                set t_error = -1;
            end if;
        ELSE
            SET resValue= CONCAT(preDate, LPAD(1, length, '0'));
        END IF;
        UPDATE serialno SET Res = resValue WHERE Pre = preValue;
    END IF;
    
    #IF t_error = 1 then 
    IF @@error_count <> 0 | t_error <> 0 THEN
        ROLLBACK;
        select t_error;
    ELSE 
        COMMIT;
        SELECT CONCAT(preValue, resValue);
    END IF;
END $
delimiter ;

這裡的參數preValue為首碼, preDate為8位的日期,格式如:"20161227", 參數des為說明, 此處並不參與邏輯, 只是更新一個欄位. 最後一個length欄位, 表示流水號的位數. 流水號的位數不能設置的太過小, 得視業務來確定. 當流水號溢出時, 會返回-1.

OK, 來看一下效果:

call p_GetSerialNo( 'b', '20170101',  'b', 4);

 


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

-Advertisement-
Play Games
更多相關文章
  • 1.Android數據存儲的五種方法 (1)SharedPreferences數據存儲 詳情介紹:http://www.cnblogs.com/zhangmiao14/p/6201900.html 優點:SharedPreferences是很輕量級的應用,使用起來也很方便、簡潔。 缺點:存儲數據類型 ...
  • 在研發中總會遇到一些莫名的需求,本著存在即合理的態度跟大家分享一下"模態Model視圖跳轉和Push視圖跳轉的需求實現",本文僅僅傳授研發技術不傳授產品以及UE的思想,請大家合理對待;推薦乾貨:一鍵合成APP引導頁,包含不同狀態下的引導頁操作方式,同時支持動態圖片引導頁和靜態圖片引導頁以及視頻引導頁 ...
  • 實現攔截 的`pop`操作有兩種方式: 自定義實現返回按鈕,即設置 來實現自定義的返回操作。 創建 的`Category navigationBar: shouldPopItem:`的邏輯。 UIViewController+BackButtonHandler.h: UIViewController ...
  • 轉載地址:http://www.jb51.net/article/77206.htm 這篇文章主要介紹了Android和JavaScript相互調用的方法,實例分析了Android的WebView執行JavaScript及JavaScript訪問Android的技巧,需要的朋友可以參考下: 本文實例 ...
  • 普通分頁 數據分頁在網頁中十分多見,分頁一般都是limit start,offset,然後根據頁碼page計算start 這種分頁在幾十萬的時候分頁效率就會比較低了,MySQL需要從頭開始一直往後計算,這樣大大影響效率 我們可以用explain分析下語句,沒有用到任何索引,MySQL執行的行數是16 ...
  • Mysql提供的函數是在是太多了, 很多我都見過, 別說用了. 園子裡面, 有人弄了一個比較全的. MYSQL函數 我這裡會將他寫的完全拷貝下來, 中間會插入一些自己項目中使用過的心得 一、數學函數 數學函數, 說實話, 我暫時還真沒怎麼用過, 就是在系統中做統計的時候, 也沒用過. 能在程式中處理 ...
  • SQLServer定時作業任務:即資料庫自動按照定時執行的作業任務,具有周期性不需要人工干預的特點 創建步驟:(使用最高許可權的賬戶登錄--sa) 一、啟動SQL Server代理(SQL Server Agent) 二、新建作業 三、設置作業常規屬性 四、設置作業步驟 五、設置作業計劃 六、點擊"確 ...
  • 資料庫分為關係型資料庫(關係型資料庫強調的是 表跟表建立在誰跟誰有關係的基礎上進行設計 ;你是他的,他是她的,她是它的;基本最終都能找到一個數據 是誰的。這就是關係型資料庫了) 以前傳統的資料庫都是關係型資料庫 Oracle、SQLServer、Sybase、Informix、access、DB2、 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...