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

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

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

一、什么是存儲過程?

1、存儲過程的定義

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

2、存儲過程的特性

特性

說明

預編譯

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

封裝性

將復雜 SQL 邏輯封裝為單個單元,降低應用層代碼復雜度

可復用性

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

安全性

可通過權限控制僅允許調用存儲過程,不直接操作底層表

支持參數(shù)

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

流程控制

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

事務支持

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

3、如何構建存儲過程?

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

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

        (1)創(chuàng)建表t_users,該表中包含主鍵ID值、用戶名稱、用戶性別、用戶賬號、用戶密碼、用戶生日、用戶地址、用戶聯(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 '用戶賬號',
  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)建存儲過程p_users,向表中批量插入2000條數(shù)據(jù):

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

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

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

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

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

                模擬生成手機號碼:手機號碼的范圍為(10000000000,19999999999)。

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

        (3)預編譯存儲過程,調用存儲過程

-- 調用存儲過程
CALL p_users();

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

二、java如何調用存儲過程?

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

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

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

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

-- 調用存儲過程
CALL p_demo3('634678362','223980837', @uname);
SELECT @uname; -- 查詢返回的結果

        結果截圖:

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

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

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

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

import java.sql.*;
import java.util.Scanner;
public class Dao {
    //創(chuàng)建數(shù)據(jù)庫連接對象
    private Connection conn;
    public Dao(){
        //加載數(shù)據(jù)庫驅動
        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){
        //準備調用語句
        String sql = "{call p_demo3(?,?,?)}";
        //預執(zhí)行語句
        try {
            CallableStatement cstmt = this.conn.prepareCall(sql);
            //注冊參數(shù)
            cstmt.setString(1,account);
            cstmt.setString(2,password);
            //返回值類型
            cstmt.registerOutParameter(3, Types.VARCHAR);
            //執(zhí)行存儲過程
            cstmt.execute();
            //獲取返回結果
            String str = cstmt.getString(3);
            System.out.println("執(zhí)行的結果為:"+str);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    public static void main(String[] args) {
        //創(chuàng)建scanner對象
        Scanner sc = new Scanner(System.in);
        //通過用戶輸入來獲取用戶的賬號和密碼信息
        System.out.println("請輸入賬號:");
        String account = sc.nextLine();
        System.out.println("請輸入密碼:");
        String password = sc.nextLine();
        Dao  db  = new Dao();
        db.call(account,password);
    }
}

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

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

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

        (4-2)調用存儲過程

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

        (4-3)運行結果截圖

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

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

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

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

特性

說明

返回值

必須返回單個值(標量),無返回值則報錯

調用方式

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

使用場景

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

語法限制

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

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

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

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

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

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

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

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

        (3)返回結果截圖

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

        (1)示例代碼:

import java.sql.*;
public class UDFCall {
    //創(chuàng)建數(shù)據(jù)庫連接對象
    private Connection conn;
    public UDFCall(){
        //加載數(shù)據(jù)庫驅動
        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){
        //準備調用語句
        String sql = "{ ? = call f_login(?,?)}";
        //預執(zhí)行語句
        try {
            CallableStatement cstmt = this.conn.prepareCall(sql);
            //返回值類型
            cstmt.registerOutParameter(1, Types.VARCHAR);
            //注冊參數(shù)
            cstmt.setString(2,account);
            cstmt.setString(3,password);
            //執(zhí)行存儲過程
            cstmt.execute();
            //獲取返回結果
            String str = cstmt.getString(1);
            System.out.println("登錄的結果為:"+str);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
    public static void main(String[] args) {
        //創(chuàng)建實例對象
        UDFCall udf = new UDFCall();
        udf.callfunc("634678362", "223980837");
    }
}

        (2)運行結果截圖:

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

對比維度

存儲過程(Stored Procedure)

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

核心定位

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

封裝單值計算邏輯(如數(shù)據(jù)轉換、簡單運算)

返回值規(guī)則

支持無返回值、單個返回值、多個返回值

僅能返回一個值(標量,如 INT/VARCHAR)

調用方式

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

嵌入調用:可直接嵌入 SELECT/WHERE/ORDER BY 等 SQL 語句,也可單獨調用

參數(shù)類型

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

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

事務支持

完全支持:可包含 COMMIT/ROLLBACK 管理事務

完全不支持:禁止包含事務操作(執(zhí)行會報錯)

使用場景

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

簡單計算邏輯(時間轉換、積分計算、字符串處理)

SQL 嵌入性

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

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

語法限制

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

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

異常處理

支持 DECLARE HANDLER 捕獲異常,可回滾事務

支持捕獲異常,但僅能返回默認值 / 拋自定義異常

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

相關文章

最新評論

山东省| 全州县| 盐池县| 商城县| 汝阳县| 神农架林区| 八宿县| 府谷县| 克什克腾旗| 仁布县| 比如县| 谢通门县| 时尚| 八宿县| 湖北省| 滁州市| 常州市| 宜川县| 定南县| 桦南县| 报价| 金堂县| 汉中市| 崇义县| 永清县| 贵港市| 唐海县| 嘉祥县| 普兰县| 长汀县| 岚皋县| 杨浦区| 竹山县| 岫岩| 灵山县| 南投市| 汶川县| 平阳县| 霍城县| 商城县| 大邑县|