MySQL存儲過程和自定義函數、Navicat for mysql、創建存儲過程和函數、調用存儲過程和函數的區別


1 MySQL存儲過程和函數

過程和函數,它們被編譯后保存在數據庫中,稱為持久性存儲模塊(Persistent Stored Module,PSM),可以反復調用,運行速度快。

1.1 存儲過程

存儲過程是由過程化 SQL 語句書寫的過程,這個過程經編譯和優化后存儲在數據庫服務器中,因此稱它為存儲過程,使用時只要調用即可。

1.2 函數

這里指自定義函數,因為是用戶自己使用過程化 SQL 設計定義的。函數和存儲過程類似,都是持久性存儲模塊。函數的定義和存儲過程也類似,不同之處是函數必須指定返回類型。

MySQL 命令的執行過程: 
這里寫圖片描述

存儲過程和函數可以簡化語法分析和編譯的過程,提高運行速度。

2 我的 MySQL 數據表

數據庫名:peng 
表名: imooc_goddess

這里寫圖片描述

我的創建數據庫、建表和插入數據 SQL 語句:

  1.  
    /*
  2.  
    Navicat MySQL Data Transfer
  3.  
     
  4.  
    Source Server : localhost_3306
  5.  
    Source Server Version : 50712
  6.  
    Source Host : localhost:3306
  7.  
    Source Database : peng
  8.  
     
  9.  
    Target Server Type : MYSQL
  10.  
    Target Server Version : 50712
  11.  
    File Encoding : 65001
  12.  
     
  13.  
    Date: 2016-10-04 20:53:44
  14.  
    */
  15.  
     
  16.  
    SET FOREIGN_KEY_CHECKS=0;
  17.  
     
  18.  
    -- ----------------------------
  19.  
    -- Table structure for imooc_goddess
  20.  
    -- ----------------------------
  21.  
    DROP TABLE IF EXISTS `imooc_goddess`;
  22.  
    CREATE TABLE `imooc_goddess` (
  23.  
    `id` int(11) NOT NULL AUTO_INCREMENT,
  24.  
    `user_name` varchar(30) NOT NULL,
  25.  
    `sex` int(11) DEFAULT NULL,
  26.  
    `age` int(11) DEFAULT NULL,
  27.  
    `birthday` date DEFAULT NULL,
  28.  
    `email` varchar(30) DEFAULT NULL,
  29.  
    `mobile` varchar(11) DEFAULT NULL,
  30.  
    `create_user` varchar(30) DEFAULT NULL,
  31.  
    `create_date` date DEFAULT NULL,
  32.  
    `update_user` varchar(30) DEFAULT NULL,
  33.  
    `update_date` date DEFAULT NULL,
  34.  
    `isdel` int(11) DEFAULT NULL,
  35.  
    PRIMARY KEY (`id`)
  36.  
    ) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8;
  37.  
     
  38.  
    -- ----------------------------
  39.  
    -- Records of imooc_goddess
  40.  
    -- ----------------------------
  41.  
    INSERT INTO `imooc_goddess` VALUES ('2', '小彭', null, '23', null, null, null, null, null, null, null, null);
  42.  
    INSERT INTO `imooc_goddess` VALUES ('6', '胖子', '0', '78', '2016-10-03', 'hongming@qq.com', '1211555599', 'admin', '2016-10-03', 'admin', '2016-10-03', '1');
  43.  
    INSERT INTO `imooc_goddess` VALUES ('7', '小溪', '0', '34', '2016-10-03', 'hongming@qq.com', '1211555599', 'admin', '2016-10-03', 'admin', '2016-10-03', '1');
  44.  
    INSERT INTO `imooc_goddess` VALUES ('9', '小霞', null, '23', '1990-09-09', 'xiaoxia@qq.com', '232445455', null, '2016-10-03', null, '2016-10-03', null);
  45.  
    INSERT INTO `imooc_goddess` VALUES ('10', 'hh', '1', '23', '1990-09-09', 'jkjfskf', '12323', 'Admin', '2016-10-03', 'admin', '2016-10-03', '1');
  46.  
    INSERT INTO `imooc_goddess` VALUES ('11', '平', '1', '23', '2998-04-09', 'jjjj@ww.com', '1323', 'admin', '2016-10-03', 'admin', '2016-10-03', '1');
  47.  
    INSERT INTO `imooc_goddess` VALUES ('12', '航母', '1', '23', '2333-09-09', 'jkksjkjf', '1232', 'admin', '2016-10-03', 'admin', '2016-10-03', '1');
  48.  
    INSERT INTO `imooc_goddess` VALUES ('13', '胖紙', '1', '23', '1991-09-09', 'jjijijij', '1323244', 'admin', '2016-10-03', 'admin', '2016-10-03', '1');
  49.  
    INSERT INTO `imooc_goddess` VALUES ('14', '校長', '1', '18', '1998-09-09', 'jkjijij@qq.com', '112323424', 'admin', '2016-10-03', 'admin', '2016-10-03', '1');

 

3 存儲過程的創建模板和調用模板

3.1 創建存儲過程模板

這里寫圖片描述

[ ] 表示可以省略 
DEFINER 創建者,省略為默認用戶 
sp_name 為過程名 
sp_name 的參數(proc_paramenter) 可以無或多個 
routine_body 過程體 
proc_paramenter 類型 :

IN 必須在調用存儲過程時指定 
OUT 可以被存儲過程改變,並且可以返回 
INOUT 調用時指定,並且可以被改變和返回

過程體如果是復合結構,則使用 BEGIN …END 語句。

  1.  
    CREATE PROCEDURE sp_name(proc_paramenter)
  2.  
    BEGIN
  3.  
    routine_body
  4.  
    END

 

3.2 調用存儲過程

  1.  
    1. CAll sp_name([parameter[,.....]])
  2.  
     
  3.  
    2. CALL sp_name[()]
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

4 創建的存儲過程

存儲過程的創建的方式有很多,但是存儲過程的創建所需的代碼都大同小異。

  • 在 電腦的 CMD 命令行創建
  • 在 Navicat 表中函數模塊新建函數
  • 在 Navicat 新建查詢(類似命令行方式)

其實 Navicat for mysql 只是一個圖形化界面而已,其中的原理都是一樣的,CMD 方式還是最經典的,最基礎的。

示例

當我們登錄到 MySQL 數據庫中時,可以通過SELECT VERSION();,查詢到當前 MySQL 版本信息,如下

這里寫圖片描述

下面是把 SELECT VERSION(); 作為一個過程體,寫入到新建的一個存儲過程中的三種方式。

方式一 CMD命令行方式

因為數據庫本來就有自己的函數,創建存儲過程名,盡量避免使用數據庫相關的名詞,可以使用比較獨特的名詞。

創建名為 v1 的存儲過程,存儲在數據庫中,創建其他存儲過程時,就不能使用 v1這個名字創建了,否則會發生重名錯誤。

這里寫圖片描述

方式二 Navicat 新建查詢

創建名為 v3 的存儲過程

這里寫圖片描述

方式三 Navicat 新建函數

創建名為 v2 的存儲過程

1.在函數上右擊新建函數。

這里寫圖片描述

2.選擇過程。 
這里寫圖片描述

3.這個存儲過程沒有參數,不填寫,點完成。 
這里寫圖片描述

4.在過程體中輸入SELECT VERSION();,點擊保存,輸入過程名 v2 ,確認。 
這里寫圖片描述

還是GIF圖來的快 
這里寫圖片描述

當然,調用這 3 種存儲過程,都可以在 Navicat 新建查詢或 CMD 中通過

  1.  
    CALL v1();
  2.  
    CALL v2();
  3.  
    CALL v3();
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

來調用

4.1 創建不帶參數的存儲過程

在 CMD 中執行下面的語句。 
這里寫圖片描述

4.2 創建帶有IN類型參數的存儲過程

DELIMITER 是MySQL的一個定界符,是告訴mysql解釋器,該段命令是否已經結束了,mysql可以執行了 
但是,在復合結構中,sql 語句用“;”結尾,但是我們並沒有結束輸入命令,所以通過 
DELIMITER // 
修改 默認為 “;”的定界符為”//”, 以后輸入 “//”代表命令輸入結束,mysql 可以執行了。 
DELIMITER ; 改回默認的定界符。

這里寫圖片描述

參數名不能和數據表名相同,上面例子的 p_id不能寫成 id。 
不能更改已經保存的存儲過程的函數體,必須先刪除該存儲過程,再創建新的存儲過程。

4.3 創建帶有 IN和OUT類型參數的存儲過程

這是一個有輸入值和返回值的存儲過程。輸入要刪除的行號 p_id ,之后數據庫計算剩余行數 返回到 userNums 中。

1.要輸入的值為 p_id,返回的值為 userNums。 
這里寫圖片描述

2.在過程體中輸入

  1.  
    DELETE FROM imooc_goddess WHERE id = p_id;
  2.  
    SELECT COUNT(id) FROM imooc_goddess INTO userNums;
  • 1
  • 2
  • 1
  • 2
  • 1
  • 2

這里寫圖片描述

3.點擊進入函數,點擊運行 
這里寫圖片描述

結果:

  1.  
    時間: 00:00.08
  2.  
     
  3.  
    Procedure executed successfully
  4.  
    受影響的行: 1
  5.  
     
  6.  
    Parameters: IN `p_id` int,OUT `userNums` int
  7.  
    14,@nums
  8.  
    Return values: 14, 4
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

1.在 CMD 命令行的寫法

  1.  
    DELIMITER //
  2.  
    CREATE PROCEDURE removeUserAndReturnUserNums(IN p_id INT UNSIGNED,OUT userNums INT UNSIGNED)
  3.  
    BEGIN
  4.  
    DELETE FROM imooc_goddess WHERE id = p_id;
  5.  
    SELECT COUNT(id) FROM imooc_goddess INTO userNums;
  6.  
    END
  7.  
    DELIMITER ;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

注意如果數據中含有 removeUserAndReturnUserNums 存儲過程,更改名稱,再創建新的存儲過程。

  1. 在 CMD 命令行調用

這里寫圖片描述

4.4 創建帶有多個OUT類型的存儲過程

輸入年齡,返回刪除的行數,和剩余行數。

這里寫圖片描述

SQL 語句

  1.  
    CREATE PROCEDURE removeUserByAgeAndReturnInfos(IN p_age SMALLINT UNSIGNED,OUT
  2.  
    deleteUsers SMALLINT UNSIGNED,OUT userCounts SMALLINT UNSIGNED)
  3.  
    BEGIN
  4.  
    DELETE FROM imooc_goddess WHERE age = p_age;
  5.  
    SELECT ROW_COUNT() INTO deleteUsers;
  6.  
    SELECT COUNT(id) FROM imooc_goddess INTO userCounts;
  7.  
    END
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

5 自定義函數

用戶自定義函數(user-defined function,UDP)是一種對MySQL 擴展的途徑,其用法與內置函數相同。

5.1 創建自定義函數模板

  1.  
    CREATE FUNCTION function_name
  2.  
    RETURNS
  3.  
    {STRING|INTEGER|REAL|DECIMAL}
  4.  
    routine_body
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

關於函數體

函數體由合法的SQL語句構成 
函數體可以是簡單的SELECT或INSERT語句 
函數體如果為復合結構則使用 BEGIN….END 語句 
復合結構可以包含聲明,循環,控制結構

5.2 自定義函數的創建和調用

1 自定義不帶參數的函數

這里寫圖片描述

  1.  
    CREATE FUNCTION f1() RETURNS VARCHAR(30)
  2.  
    RETURN DATE_FORMAT(NOW(),'%Y年%m月%d日:%H時:%i分:%s秒');
  • 1
  • 2
  • 1
  • 2
  • 1
  • 2
SELECT f1();
  • 1
  • 1
  • 1

在 Java 項目上調用函數(函數有返回值)時

CallableStatement cs = conn.prepareCall("{?= call f1()}");
  • 1
  • 1
  • 1

2 自定義兩個參數的函數

輸入兩個值,計算其平均值。

  1.  
    CREATE FUNCTION f2(num1 SMALLINT UNSIGNED,num2 SMALLINT UNSIGNED)
  2.  
    RETURNS FLOAT(10,2) UNSIGNED
  3.  
    RETURN (num1+num2)/2;
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

3 創建具有復合機構函數體的函數

插入一條新數據,user_name,返回該行的id。

  1.  
    CREATE FUNCTION adduser(username VARCHAR(20))
  2.  
    RETURNS INT UNSIGNED
  3.  
    BEGIN
  4.  
    INSERT imooc_goddess(user_name) VALUES (username);
  5.  
    return LAST_INSERT_ID();
  6.  
    END
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

這里寫圖片描述

6 通過 Navicat 查看存儲過程和函數的創建語句

在 Navicat 中點開函數欄,選擇你要查看的函數,右擊選擇對象信息。 
這里寫圖片描述

選擇DDL欄(數據定義語言)

這里寫圖片描述

  1.  
    CREATE DEFINER=`root`@`localhost` PROCEDURE `selectAll`()
  2.  
    BEGIN
  3.  
    SELECT * FROM imooc_goddess;
  4.  
    END
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

語句中的

DEFINER=`root`@`localhost`
  • 1
  • 1
  • 1

是數據庫自己默認添加的。

復制數據定義語言創建過程時-發生錯誤

當我想直接復制數據定義語言,更改一個名稱創建另一個存儲過程時,總是創建不成功。 
1、更改名稱(Error)

  1.  
    CREATE DEFINER=`root`@`localhost` PROCEDURE `myselectAll`()
  2.  
    BEGIN
  3.  
    SELECT * FROM imooc_goddess;
  4.  
    END
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

2、修改DEFINER(下面的語句都是不能成功創建)

  1.  
    CREATE DEFINER={'root`@`localhost`} PROCEDURE `myselectAll`()
  2.  
    BEGIN
  3.  
    SELECT * FROM imooc_goddess;
  4.  
    END
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
  1.  
    CREATE DEFINER={'root`@`%`} PROCEDURE `myselectAll`()
  2.  
    BEGIN
  3.  
    SELECT * FROM imooc_goddess;
  4.  
    END
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
  1.  
    CREATE DEFINER={root|localhost} PROCEDURE `myselectAll`()
  2.  
    BEGIN
  3.  
    SELECT * FROM imooc_goddess;
  4.  
    END
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
  1.  
    CREATE DEFINER={root} PROCEDURE `myselectAll`()
  2.  
    BEGIN
  3.  
    SELECT * FROM imooc_goddess;
  4.  
    END
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
  1.  
    CREATE DEFINER=root PROCEDURE `myselectAll`()
  2.  
    BEGIN
  3.  
    SELECT * FROM imooc_goddess;
  4.  
    END
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
  1.  
    CREATE DEFINER=`CURRENT_USER`() PROCEDURE `myselectAll`()
  2.  
    BEGIN
  3.  
    SELECT * FROM imooc_goddess;
  4.  
    END
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
  1.  
    CREATE DEFINER=CURRENT_USER PROCEDURE `myselectAll`()
  2.  
    BEGIN
  3.  
    SELECT * FROM imooc_goddess;
  4.  
    END
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

3、刪除DEFINER 
刪除DEFINER,可以創建成功

  1.  
    CREATE PROCEDURE `myselectAll`()
  2.  
    BEGIN
  3.  
    SELECT * FROM imooc_goddess;
  4.  
    END
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

然而創建函數時卻可以帶 DEFINER 
下面的語句可以創建成功

  1.  
    CREATE DEFINER=`root`@`localhost` FUNCTION `f2`(num1 SMALLINT UNSIGNED,num2 SMALLINT UNSIGNED) RETURNS float(10,2) unsigned
  2.  
    RETURN (num1+num2)/2
  • 1
  • 2
  • 1
  • 2
  • 1
  • 2

復制數據定義語言,創建存儲過程要刪除DEFINER。

7 存儲過程與自定義函數的區別

    • 存儲過程實現的功能要復雜一些,而函數的的針對性更強

    • 存儲的過程可以返回多個值,函數只能有一個返回值

    • 存儲過程一般獨立的執行,而函數可以作為其他 SQL語句的組成部分來實現。

    • 過程 通俗易懂的說法:它只是將其中的程序執行一遍

    • 函數 通俗易懂的說法:它不但將其中的程序執行一遍,還返回一個值


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM