最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java調(diào)用MySQL數(shù)據(jù)庫的存儲(chǔ)過程和自定義函數(shù)及區(qū)別解析

 更新時(shí)間:2025年12月31日 10:15:55   作者:w_zero_one  
本文介紹了存儲(chǔ)過程和自定義函數(shù)的概念、特性和構(gòu)建方法,并通過Java代碼展示了如何調(diào)用存儲(chǔ)過程和自定義函數(shù),最后,對(duì)比了存儲(chǔ)過程和自定義函數(shù)的區(qū)別,感興趣的朋友跟隨小編一起看看吧

一、什么是存儲(chǔ)過程?

1、存儲(chǔ)過程的定義

        存儲(chǔ)過程(Stored Procedure)是一組預(yù)編譯并存儲(chǔ)在 MySQL 服務(wù)器中的 SQL 語句集合,可通過名稱調(diào)用執(zhí)行,支持參數(shù)傳遞、流程控制(條件、循環(huán))、異常處理等特性,是數(shù)據(jù)庫層面封裝業(yè)務(wù)邏輯的核心工具。

2、存儲(chǔ)過程的特性

特性

說明

預(yù)編譯

創(chuàng)建時(shí)編譯,調(diào)用時(shí)無需重復(fù)解析 / 優(yōu)化,執(zhí)行效率更高

封裝性

將復(fù)雜 SQL 邏輯封裝為單個(gè)單元,降低應(yīng)用層代碼復(fù)雜度

可復(fù)用性

一次創(chuàng)建,多處調(diào)用,減少重復(fù)開發(fā)

安全性

可通過權(quán)限控制僅允許調(diào)用存儲(chǔ)過程,不直接操作底層表

支持參數(shù)

輸入(IN)、輸出(OUT)、輸入輸出(INOUT)參數(shù)

流程控制

支持 IF、CASE、LOOP、WHILE、REPEAT 等編程邏輯

事務(wù)支持

可在存儲(chǔ)過程中管理事務(wù)(COMMIT/ROLLBACK)

3、如何構(gòu)建存儲(chǔ)過程?

-- 創(chuàng)建存儲(chǔ)過程
delimiter $$
CREATE PROCEDURE 存儲(chǔ)過程名([參數(shù)列表])
BEGIN
-- 存儲(chǔ)過程體(SQL語句/流程控制邏輯)
END $$
delimiter;
-- 調(diào)用存儲(chǔ)過程
CALL 存儲(chǔ)過程名([參數(shù)列表]);

4、案例:使用存儲(chǔ)過程,向表中批量插入2000條數(shù)據(jù)

        (1)創(chuàng)建表t_users,該表中包含主鍵ID值、用戶名稱、用戶性別、用戶賬號(hào)、用戶密碼、用戶生日、用戶地址、用戶聯(lián)系方式。

-- 創(chuàng)建表t_users
CREATE TABLE IF NOT EXISTS t_users(
  uid INT AUTO_INCREMENT PRIMARY KEY COMMENT '主鍵ID值',
  uname VARCHAR(30) NOT NULL COMMENT '用戶名稱',
  ugender VARCHAR(10) NOT NULL COMMENT '用戶性別',
  uaccount VARCHAR(9) NOT NULL COMMENT '用戶賬號(hào)',
  upassword VARCHAR(9) NOT NULL COMMENT '用戶密碼',
  ubirthday VARCHAR(50) NOT NULL COMMENT '用戶生日',
  uaddress VARCHAR(100) NOT NULL COMMENT '用戶地址',
  uphone CHAR(11) NOT NULL COMMENT '用戶聯(lián)系方式'
);

        (2)創(chuàng)建存儲(chǔ)過程p_users,向表中批量插入2000條數(shù)據(jù):

                模擬生成姓名:先在姓氏列表中隨機(jī)生成一個(gè)姓氏,再根據(jù)性別在各自的名字庫中獲取隨機(jī)的名字,再將二者組合生成完整的名字;

                模擬生成賬號(hào):可以采用隨機(jī)數(shù)來做,范圍是[100000000,99999999);

                模擬生成賬號(hào):可以采用隨機(jī)數(shù)來做,密碼的范圍是數(shù)字6位或9位;

                模擬生成地址:這里采用的是江蘇省和其包含的市進(jìn)行隨機(jī)的組合;

                模擬生成生日:格式為‘××××-××-××’;

                模擬生成手機(jī)號(hào)碼:手機(jī)號(hào)碼的范圍為(10000000000,19999999999)。

-- 使用數(shù)據(jù)庫的存儲(chǔ)過程,向表中批量存儲(chǔ)2000條數(shù)據(jù)
  delimiter $$
  CREATE PROCEDURE p_users ()
  BEGIN
    DECLARE
    i INT DEFAULT 1; -- 計(jì)數(shù)器
    DECLARE
    user_name VARCHAR (30); -- 用戶姓名
    DECLARE
    user_gender VARCHAR (10); -- 用戶性別
    DECLARE
    user_account VARCHAR (9); -- 用戶賬號(hào)
    DECLARE
    user_password VARCHAR (9); -- 用戶密碼
    DECLARE
    user_birthday VARCHAR (50); -- 用戶生日
    DECLARE
    user_address VARCHAR (100); -- 用戶地址
    DECLARE
    user_phone CHAR(11); -- 用戶電話號(hào)碼
    -- 隨機(jī)生成數(shù)據(jù)
    -- 創(chuàng)建姓氏列表變量
    SET @last_names = '趙,錢,孫,李,周,吳,鄭,王,馮,陳,褚,衛(wèi),蔣,沈,韓,楊,朱,秦,尤,許,何,呂,施,張,孔,曹,嚴(yán),華,金,魏,田';
    -- 男性名字庫
    SET @male_names = '明軒,沐澤,宏杰,誠(chéng),棟盛,健,德清,明,柯鴻,學(xué)智,俊,國(guó)瑞,東旭,彥晟,哲源,旭磊,兵,海毅,軒俊,文錦,瀟陽,明煦,恒文,昌瑞';
    -- 女性名字庫
    SET @female_names = '欣瑾,沐璇,涵淇,韶涵,悅琪,凌蕊,凝萱,子琪,惜筠,怡木,巧云,春燕,初柔,雨,翠花,妍茜,捷,語蓉,藝歆,嵐菱,冰蕊,蝶靜,雅依,思怡';
    -- 江蘇省包含的市名字庫
    SET @country_names = '南京市,無錫市,徐州市,常州市,蘇州市,南通市,連云港市,淮安市,鹽城市,揚(yáng)州市,鎮(zhèn)江市,泰州市,宿遷市';
    -- 循環(huán)插入數(shù)據(jù)
    REPEAT
      -- 隨機(jī)生成用戶性別
      SET user_gender =
      IF(RAND() > 0.5, '男', '女');
        -- 隨機(jī)生成用戶姓名
        -- 隨機(jī)取出用戶的性
        SET @last_name = SUBSTRING_INDEX(SUBSTRING_INDEX(@last_names, ',', FLOOR(RAND() * 21 + 1)), ',', - 1);
        -- 根據(jù)性別取名
        IF user_gender = '男' THEN
          SET @first_name = SUBSTRING_INDEX(SUBSTRING_INDEX(@male_names, ',', FLOOR(RAND() * 24 + 1)), ',', - 1);
        ELSE
          SET @first_name = SUBSTRING_INDEX(SUBSTRING_INDEX(@female_names, ',', FLOOR(RAND() * 24 + 1)), ',', - 1);
        END IF;
        -- 組合名字
        SET user_name = CONCAT(@last_name, @first_name);
        -- 隨機(jī)生成賬號(hào):賬號(hào)的長(zhǎng)度為9位,范圍100000000 -- 999999999
        SET user_account = FLOOR(RAND() * 900000000 + 100000000);
        -- 隨機(jī)生成密碼: 密碼最少6位,最多九位
        SET user_password = FLOOR(RAND() * 999900000 + 100000);
        -- 隨機(jī)生成生日
        SET @month_random = FLOOR(RAND() * 12 + 1);
        SET @month_value =
        IF(@month_random < 10, CONCAT('0', @month_random), @month_random);
          SET @date_random = FLOOR(RAND() * 30 + 1);
          SET @date_value =
          IF(@date_random < 10, CONCAT('0', @date_random), @date_random);
            SET user_birthday = CONCAT(FLOOR(RAND() * 46 + 1980), '-', @month_value, '-', @date_value);
            -- 隨機(jī)生成地址
            -- 隨機(jī)市名
            SET @country_name = SUBSTRING_INDEX(SUBSTRING_INDEX(@country_names, ',', FLOOR(RAND() * 13 + 1)), ',', - 1);
            -- 組合地址信息
            SET user_address = CONCAT('江蘇省', @country_name);
            -- 隨機(jī)生成手機(jī)號(hào)碼 10000000000-19999999999
            SET user_phone = FLOOR(RAND() * 1000000000 + 10000000000);
            INSERT INTO t_users (uname, ugender, uaccount, upassword, ubirthday, uaddress, uphone)
            VALUES
            (user_name, user_gender, user_account, user_password, user_birthday, user_address, user_phone);
            -- 計(jì)數(shù)器+1
            SET i = i + 1;
          UNTIL i > 2000 END REPEAT;
          COMMIT;
        END $$
delimiter;

        (3)預(yù)編譯存儲(chǔ)過程,調(diào)用存儲(chǔ)過程

-- 調(diào)用存儲(chǔ)過程
CALL p_users();

        (4)成功生成2000條模擬數(shù)據(jù)

二、java如何調(diào)用存儲(chǔ)過程?

        在上面調(diào)用存儲(chǔ)過程的案例中,我們已經(jīng)成功生成2000條模擬數(shù)據(jù),那么下面以該表為例,通過調(diào)用存儲(chǔ)過程來實(shí)現(xiàn)查詢用戶名稱的操作。

1、創(chuàng)建存儲(chǔ)過程p_demo3,通過傳入?yún)?shù)賬號(hào)和密碼信息,獲取該用戶的名稱

-- 創(chuàng)建存儲(chǔ)過程:查詢?cè)撡~戶的用戶名稱
delimiter $$
CREATE PROCEDURE p_demo3(IN v_account VARCHAR(9),IN v_password VARCHAR(9),OUT v_name VARCHAR(30))
BEGIN
 -- into關(guān)鍵字是給一個(gè)變量賦值,如果產(chǎn)生多個(gè)值(2個(gè)及以上,需要用游標(biāo))
SELECT uname INTO v_name FROM t_users WHERE uaccount = v_account AND upassword = v_password;
END $$
delimiter;

2、調(diào)用存儲(chǔ)過程,以表中生成的第一條數(shù)據(jù)為例,輸入該用戶的賬號(hào)和密碼。

-- 調(diào)用存儲(chǔ)過程
CALL p_demo3('634678362','223980837', @uname);
SELECT @uname; -- 查詢返回的結(jié)果

        結(jié)果截圖:

3、通過上面兩步已經(jīng)通過存儲(chǔ)過程實(shí)現(xiàn)了對(duì)用戶姓名的查詢,下面在java中連接數(shù)據(jù)庫,調(diào)用存儲(chǔ)過程。

        (1)在pom.xml文件中添加依賴:

<dependencies>
            <!-- MySQL JDBC driver -->
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>8.0.28</version> <!-- 請(qǐng)使用最新版本 -->
            </dependency>
    </dependencies>

        (2)連接數(shù)據(jù)庫代碼:

import java.sql.*;
import java.util.Scanner;
public class Dao {
    //創(chuàng)建數(shù)據(jù)庫連接對(duì)象
    private Connection conn;
    public Dao(){
        //加載數(shù)據(jù)庫驅(qū)動(dòng)
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/computer_class","root","123456");
            System.out.println("數(shù)據(jù)庫computer_class連接成功?。?!");
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    public void call(String account,String password){
        //準(zhǔn)備調(diào)用語句
        String sql = "{call p_demo3(?,?,?)}";
        //預(yù)執(zhí)行語句
        try {
            CallableStatement cstmt = this.conn.prepareCall(sql);
            //注冊(cè)參數(shù)
            cstmt.setString(1,account);
            cstmt.setString(2,password);
            //返回值類型
            cstmt.registerOutParameter(3, Types.VARCHAR);
            //執(zhí)行存儲(chǔ)過程
            cstmt.execute();
            //獲取返回結(jié)果
            String str = cstmt.getString(3);
            System.out.println("執(zhí)行的結(jié)果為:"+str);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    public static void main(String[] args) {
        //創(chuàng)建scanner對(duì)象
        Scanner sc = new Scanner(System.in);
        //通過用戶輸入來獲取用戶的賬號(hào)和密碼信息
        System.out.println("請(qǐng)輸入賬號(hào):");
        String account = sc.nextLine();
        System.out.println("請(qǐng)輸入密碼:");
        String password = sc.nextLine();
        Dao  db  = new Dao();
        db.call(account,password);
    }
}

        (3)在控制臺(tái)中輸入賬號(hào)和密碼信息,以第一條數(shù)據(jù)為例

*****(4-1)在上面的案例中,調(diào)用的存儲(chǔ)過程的返回值只有一行。如果出現(xiàn)多行數(shù)據(jù)的情況,應(yīng)該使用游標(biāo)來獲取返回的結(jié)果。下面介紹一個(gè)使用到游標(biāo)的案例:查詢所有地址為江蘇省南京市的用戶名稱、用戶性別、地址信息,示例代碼:

-- 創(chuàng)建存儲(chǔ)過程:查詢所有地址為江蘇省南京市的用戶名稱、用戶性別、地址信息
-- 返回的結(jié)果是有多行數(shù)據(jù),是一個(gè)結(jié)果集,所以需要使用到游標(biāo)
delimiter $$
CREATE PROCEDURE p_demo4(IN v_address VARCHAR(100),OUT v_data VARCHAR(15000))
BEGIN
-- 聲明變量
DECLARE user_name VARCHAR(30);
DECLARE user_gender VARCHAR(10);
DECLARE user_address VARCHAR(100);
DECLARE v_str TEXT DEFAULT "";
-- 聲明游標(biāo)遍歷結(jié)束的標(biāo)志變量(必須是 BOOL/INT 類型,默認(rèn) NULL)
DECLARE done INT DEFAULT 0;
-- 游標(biāo)的定義就是sql的定義
DECLARE v_result CURSOR FOR SELECT uname,ugender,uaddress FROM t_users WHERE uaddress = v_address;
-- 聲明游標(biāo)結(jié)束處理器
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
 -- 打開游標(biāo)(執(zhí)行關(guān)聯(lián)的查詢,加載結(jié)果集到內(nèi)存)
    OPEN v_result;
    read_loop: LOOP
        -- 從游標(biāo)中讀取一行數(shù)據(jù),賦值給變量
        FETCH v_result INTO user_name,user_gender,user_address;
        IF done = 1 THEN
            LEAVE read_loop;
        END IF;
        -- 業(yè)務(wù)邏輯:處理當(dāng)前行的數(shù)據(jù)(示例:打印/計(jì)算/插入等)
       SET v_str = CONCAT(v_str ,user_name, '-', user_gender,'-',user_address,'|');    
    END LOOP;
    -- 6. 關(guān)閉游標(biāo)(釋放結(jié)果集內(nèi)存)
    CLOSE v_result;
    -- 完成對(duì)返回值的賦值
    SET v_data = v_str;
END $$
delimiter;

        (4-2)調(diào)用存儲(chǔ)過程

-- 調(diào)用存儲(chǔ)過程
CALL p_demo4('江蘇省南京市',@info)
SELECT @info

        (4-3)運(yùn)行結(jié)果截圖

三、什么是自定義函數(shù)?

1、自定義函數(shù)的定義:

        自定義函數(shù)(User-Defined Function,UDF)是 MySQL 中用戶自行定義的、可復(fù)用的 SQL 函數(shù),與內(nèi)置函數(shù)(如CONCAT()、SUM())類似,接收輸入?yún)?shù)、執(zhí)行邏輯并返回單個(gè)值(標(biāo)量),是數(shù)據(jù)庫層封裝簡(jiǎn)單 / 復(fù)用性高的計(jì)算邏輯的核心工具。

2、自定義函數(shù)的特性:

特性

說明

返回值

必須返回單個(gè)值(標(biāo)量),無返回值則報(bào)錯(cuò)

調(diào)用方式

可嵌入 SQL 語句中(如 SELECT、WHERE)

使用場(chǎng)景

簡(jiǎn)單計(jì)算、數(shù)據(jù)轉(zhuǎn)換、條件判斷(單值輸出)

語法限制

不能包含事務(wù)操作(COMMIT/ROLLBACK)

3、如何構(gòu)建自定義函數(shù)?

CREATE FUNCTION 函數(shù)名(參數(shù)列表)
DETERMINISTIC
BEGIN
-- 執(zhí)行的函數(shù)體
RETURN 返回值;
END;

4、案例:使用自定義函數(shù),通過輸入的賬號(hào)和密碼,來實(shí)現(xiàn)登錄功能,數(shù)據(jù)來源于上面案例創(chuàng)建的表。

        (1)構(gòu)建自定義函數(shù)f_login

CREATE FUNCTION f_login(v_account VARCHAR(9), v_passsword VARCHAR(9)) RETURNS VARCHAR(50)
DETERMINISTIC
BEGIN
-- 聲明計(jì)數(shù)器
DECLARE v_count INT;
-- 聲明返回信息、
DECLARE v_message VARCHAR(50);
-- 根據(jù)輸入的賬號(hào)和密碼查表
SELECT COUNT(*) INTO v_count FROM t_users WHERE uaccount = v_account AND upassword = v_passsword;
SET v_message = IF(v_count > 0,'登錄成功','登錄失敗,賬號(hào)或密碼錯(cuò)誤');
RETURN v_message;
END;

        (2)通過預(yù)編譯后,調(diào)用自定義函數(shù)f_login,以第一條數(shù)據(jù)為例。

-- 調(diào)用自定義函數(shù)
SELECT f_login('634678362','223980837') FROM DUAL;

        (3)返回結(jié)果截圖

四、java如何調(diào)用自定義函數(shù)?

        (1)示例代碼:

import java.sql.*;
public class UDFCall {
    //創(chuàng)建數(shù)據(jù)庫連接對(duì)象
    private Connection conn;
    public UDFCall(){
        //加載數(shù)據(jù)庫驅(qū)動(dòng)
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/computer_class","root","123456");
            System.out.println("數(shù)據(jù)庫computer_class連接成功!??!");
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    public void callfunc (String account,String password){
        //準(zhǔn)備調(diào)用語句
        String sql = "{ ? = call f_login(?,?)}";
        //預(yù)執(zhí)行語句
        try {
            CallableStatement cstmt = this.conn.prepareCall(sql);
            //返回值類型
            cstmt.registerOutParameter(1, Types.VARCHAR);
            //注冊(cè)參數(shù)
            cstmt.setString(2,account);
            cstmt.setString(3,password);
            //執(zhí)行存儲(chǔ)過程
            cstmt.execute();
            //獲取返回結(jié)果
            String str = cstmt.getString(1);
            System.out.println("登錄的結(jié)果為:"+str);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    public static void main(String[] args) {
        //創(chuàng)建實(shí)例對(duì)象
        UDFCall udf = new UDFCall();
        udf.callfunc("634678362", "223980837");
    }
}

        (2)運(yùn)行結(jié)果截圖:

五、MySQL數(shù)據(jù)庫的存儲(chǔ)過程和自定義函數(shù)的區(qū)別?

對(duì)比維度

存儲(chǔ)過程(Stored Procedure)

自定義函數(shù)(UDF)

核心定位

封裝多步業(yè)務(wù)邏輯(如事務(wù)、多表操作)

封裝單值計(jì)算邏輯(如數(shù)據(jù)轉(zhuǎn)換、簡(jiǎn)單運(yùn)算)

返回值規(guī)則

支持無返回值、單個(gè)返回值、多個(gè)返回值

僅能返回一個(gè)值(標(biāo)量,如 INT/VARCHAR)

調(diào)用方式

獨(dú)立調(diào)用:CALL 過程名(參數(shù)),不可嵌入 SQL

嵌入調(diào)用:可直接嵌入 SELECT/WHERE/ORDER BY 等 SQL 語句,也可單獨(dú)調(diào)用

參數(shù)類型

支持 IN/OUT/INOUT 三種參數(shù)(顯式聲明)

僅支持 IN 參數(shù)(默認(rèn),不可聲明 OUT/INOUT)

事務(wù)支持

完全支持:可包含 COMMIT/ROLLBACK 管理事務(wù)

完全不支持:禁止包含事務(wù)操作(執(zhí)行會(huì)報(bào)錯(cuò))

使用場(chǎng)景

復(fù)雜業(yè)務(wù)邏輯(訂單創(chuàng)建、數(shù)據(jù)同步、批量更新)

簡(jiǎn)單計(jì)算邏輯(時(shí)間轉(zhuǎn)換、積分計(jì)算、字符串處理)

SQL 嵌入性

不可嵌入 SELECT/UPDATE 等語句,僅能獨(dú)立 CALL

可嵌入任意 SQL 語句(如SELECT UDF(字段) FROM 表

語法限制

可包含 DDL(CREATE/DROP)、DML、DQL

避免包含 DDL,僅建議 DQL(讀取數(shù)據(jù))或純內(nèi)存計(jì)算

異常處理

支持 DECLARE HANDLER 捕獲異常,可回滾事務(wù)

支持捕獲異常,但僅能返回默認(rèn)值 / 拋?zhàn)远x異常

到此這篇關(guān)于Java調(diào)用MySQL數(shù)據(jù)庫的存儲(chǔ)過程和自定義函數(shù)及區(qū)別解析的文章就介紹到這了,更多相關(guān)java調(diào)用mysql存儲(chǔ)過程和自定義函數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

西丰县| 阳山县| 都匀市| 阳新县| 合肥市| 甘南县| 金秀| 关岭| 富宁县| 隆林| 邵武市| 赤城县| 雅江县| 界首市| 贵南县| 吉首市| 新绛县| 宜兴市| 扬州市| 大田县| 毕节市| 基隆市| 马鞍山市| 怀化市| 龙江县| 无极县| 文登市| 子长县| 庐江县| 黑山县| 山西省| 黄山市| 冷水江市| 鹤山市| 丰城市| 喜德县| 屏东市| 富裕县| 台北县| 江津市| 磐石市|