MySQL自定義函數零基礎學習教程

1. 引言

想象一下,你在用計算器做數學題。每次計算"圓形面積"時,你都要輸入:3.14 × 半徑 × 半徑。如果能把這個計算步驟保存起來,下次只要輸入半徑就自動算出面積,那該多方便!

MySQL自定義函數就是這樣的"保存的計算步驟"。它讓我們把復雜的計算過程寫成一個"函數",以后只要調用這個函數名,就能自動完成計算。

就像給計算器增加了一個新按鈕:輸入半徑,按下"計算圓面積"按鈕,就得到結果。

自定義函數解決了數據庫開發中的核心問題:如何優雅地處理復雜的業務邏輯計算,避免重復編寫相同的代碼,同時保持數據庫操作的高效性和一致性。

2. 基礎概念和語法

2.1 什么是MySQL自定義函數?

最簡單的理解:自定義函數就是你教給MySQL的一個新"技能"。

  • 輸入:給函數一些數據(叫做參數)
  • 處理:函數按照你寫的規則進行計算
  • 輸出:返回一個結果

就像數學中的函數:f(x) = x + 1

  • 輸入x=5,計算:5+1,輸出:6

2.2 基本語法結構

CREATE FUNCTION 函數名(參數名 參數類型)
RETURNS 返回類型
[函數特性]
BEGIN-- 函數體:業務邏輯代碼DECLARE 變量聲明;SET 變量賦值;RETURN 返回值;
END

各部分詳細說明

  • CREATE FUNCTION:告訴MySQL"我要創建一個新函數"
  • 函數名:給這個函數起個名字,遵循MySQL標識符命名規則
  • 參數列表:函數接受的輸入參數,格式:參數名 數據類型
  • RETURNS:指定函數返回值的數據類型,必須與實際返回值類型匹配
  • 函數特性:可選的函數屬性設置(DETERMINISTIC、READS SQL DATA等)
  • BEGIN...END:函數體的邊界標識,包含具體實現邏輯
  • DECLARE:聲明局部變量
  • RETURN:返回函數結果,函數必須包含return語句

2.3 關鍵字說明

關鍵字作用說明
DELIMITER設置語句分隔符避免函數體內分號與語句結束符沖突
CREATE FUNCTION創建函數函數定義的開始標識
RETURNS聲明返回類型必須指定,且與實際返回值類型匹配
DETERMINISTIC確定性函數相同輸入總是產生相同輸出
NOT DETERMINISTIC非確定性函數相同輸入可能產生不同輸出
READS SQL DATA讀取數據函數會讀取數據庫數據
NO SQL不含SQL函數不包含SQL語句
BEGIN...END函數體邊界包含函數的具體實現邏輯
DECLARE聲明變量在函數內部聲明局部變量
RETURN返回結果函數必須包含return語句

2.4 第一個函數:從最簡單開始

我們從最最簡單的開始:一個把數字乘以2的函數。

-- 告訴MySQL:現在用$$作為語句結束標記,不要用分號
DELIMITER $$CREATE FUNCTION double_number(x INT)
RETURNS INT
DETERMINISTIC
NO SQL
BEGINRETURN x * 2;  -- 這個分號不是語句結束,只是函數內部的分號
END $$  -- 這個$$才是語句結束-- 恢復默認的分隔符
DELIMITER ;

逐行解釋

  • DELIMITER $$:設置新的語句分隔符,避免函數內部分號沖突
  • CREATE FUNCTION double_number:創建一個叫"double_number"的函數
  • (x INT):函數需要一個整數輸入,命名為x
  • RETURNS INT:函數會返回一個整數
  • DETERMINISTIC:相同輸入總是相同輸出
  • NO SQL:函數不包含SQL查詢語句
  • RETURN x * 2:把輸入的數字乘以2并返回

使用這個函數

SELECT double_number(5);  -- 結果:10
SELECT double_number(8);  -- 結果:16

3. 函數特性詳解

3.1 DETERMINISTIC vs NOT DETERMINISTIC

DETERMINISTIC(確定性):告訴MySQL"這個函數很老實",相同的輸入總是得到相同的輸出。

DELIMITER $$-- 確定性函數:數學計算
CREATE FUNCTION add_two_numbers(a INT, b INT)
RETURNS INT
DETERMINISTIC
NO SQL
BEGINRETURN a + b;  -- 3+5總是等于8
END $$-- 確定性函數:字符串處理
CREATE FUNCTION format_phone(phone VARCHAR(20))
RETURNS VARCHAR(20)
DETERMINISTIC
NO SQL
BEGINRETURN CONCAT('(', LEFT(phone, 3), ') ', SUBSTRING(phone, 4, 3), '-', RIGHT(phone, 4));
END $$DELIMITER ;

NOT DETERMINISTIC(非確定性):相同的輸入可能得到不同的輸出,因為依賴于時間、隨機數等外部因素。

DELIMITER $$-- 非確定性函數:時間相關
CREATE FUNCTION get_current_hour()
RETURNS INT
NOT DETERMINISTIC
NO SQL
BEGINRETURN HOUR(NOW());  -- 每個小時返回的結果都不同
END $$-- 非確定性函數:隨機數
CREATE FUNCTION get_random_discount()
RETURNS DECIMAL(3,2)
NOT DETERMINISTIC
NO SQL
BEGINRETURN ROUND(RAND() * 0.2, 2);  -- 0到0.2之間的隨機折扣
END $$-- 非確定性函數:計算年齡
CREATE FUNCTION calculate_age(birth_year INT)
RETURNS INT
NOT DETERMINISTIC
NO SQL
BEGINRETURN YEAR(CURDATE()) - birth_year;  -- 結果隨當前年份變化
END $$DELIMITER ;

3.2 NO SQL vs READS SQL DATA

NO SQL:函數只做計算,不查詢數據庫表。

DELIMITER $$-- 純數學計算
CREATE FUNCTION calculate_circle_area(radius DECIMAL(5,2))
RETURNS DECIMAL(10,2)
DETERMINISTIC
NO SQL
BEGINRETURN 3.14159 * radius * radius;
END $$-- 字符串處理
CREATE FUNCTION mask_credit_card(card_number VARCHAR(20))
RETURNS VARCHAR(20)
DETERMINISTIC
NO SQL
BEGINIF LENGTH(card_number) < 4 THENRETURN card_number;END IF;RETURN CONCAT(REPEAT('*', LENGTH(card_number) - 4), RIGHT(card_number, 4));
END $$DELIMITER ;

READS SQL DATA:函數需要從數據庫表中讀取數據。

首先創建測試表:

-- 創建學生表
CREATE TABLE IF NOT EXISTS students (id INT PRIMARY KEY,name VARCHAR(50),score INT,class_id INT
);-- 插入測試數據
INSERT IGNORE INTO students VALUES 
(1, '小明', 85, 1),
(2, '小紅', 92, 1),
(3, '小李', 78, 2),
(4, '小王', 88, 2);
DELIMITER $$-- 查詢單個值
CREATE FUNCTION get_student_score(student_id INT)
RETURNS INT
READS SQL DATA
BEGINDECLARE student_score INT;SELECT score INTO student_score FROM students WHERE id = student_id;RETURN COALESCE(student_score, 0);
END $$-- 查詢統計數據
CREATE FUNCTION get_class_average(class_id INT)
RETURNS DECIMAL(5,2)
READS SQL DATA
BEGINDECLARE avg_score DECIMAL(5,2);SELECT AVG(score) INTO avg_scoreFROM students WHERE class_id = class_id;RETURN COALESCE(avg_score, 0.00);
END $$-- 查詢計數
CREATE FUNCTION count_excellent_students(min_score INT)
RETURNS INT
READS SQL DATA
BEGINDECLARE student_count INT;SELECT COUNT(*) INTO student_countFROM students WHERE score >= min_score;RETURN student_count;
END $$DELIMITER ;

測試函數

-- 純計算函數
SELECT calculate_circle_area(5.0);  -- 結果:78.54-- 數據查詢函數
SELECT get_student_score(1);        -- 結果:85
SELECT get_class_average(1);        -- 結果:88.50
SELECT count_excellent_students(90); -- 結果:1

3.3 函數特性選擇指南

場景推薦特性示例
純數學計算DETERMINISTIC + NO SQL計算面積、稅費、折扣
字符串格式化DETERMINISTIC + NO SQL電話號碼格式化、脫敏
時間相關計算NOT DETERMINISTIC + NO SQL計算年齡、當前時間
隨機數生成NOT DETERMINISTIC + NO SQL隨機折扣、驗證碼
簡單數據查詢DETERMINISTIC + READS SQL DATA查詢用戶信息、商品價格
統計分析NOT DETERMINISTIC + READS SQL DATA實時統計、動態分析

4. 變量和控制結構

4.1 變量的聲明和使用

變量就像一個"盒子",可以往里面放數據,也可以把數據取出來。

DELIMITER $$-- 基礎變量使用
CREATE FUNCTION demonstrate_variables(input_num INT)
RETURNS VARCHAR(100)
DETERMINISTIC
NO SQL
BEGINDECLARE num1 INT;                         -- 聲明整數變量,默認NULLDECLARE num2 INT DEFAULT 0;              -- 聲明整數變量,初始值0DECLARE message VARCHAR(50) DEFAULT 'Result: ';  -- 聲明字符串變量DECLARE final_result VARCHAR(100);       -- 聲明結果變量-- 變量賦值SET num1 = input_num;SET num2 = num2 + input_num * 2;-- 字符串拼接SET final_result = CONCAT(message, num1, ' + ', num2, ' = ', num1 + num2);RETURN final_result;
END $$-- 復雜變量操作
CREATE FUNCTION calculate_compound_result(principal DECIMAL(10,2), rate DECIMAL(4,3), years INT)
RETURNS DECIMAL(12,2)
DETERMINISTIC
NO SQL
BEGINDECLARE annual_amount DECIMAL(12,2);DECLARE total_amount DECIMAL(12,2);DECLARE interest_earned DECIMAL(12,2);DECLARE i INT DEFAULT 1;SET total_amount = principal;-- 使用WHILE循環計算復利WHILE i <= years DOSET total_amount = total_amount * (1 + rate);SET i = i + 1;END WHILE;RETURN ROUND(total_amount, 2);
END $$DELIMITER ;

4.2 條件判斷結構

IF語句
DELIMITER $$-- 簡單IF判斷
CREATE FUNCTION check_score_level(score INT)
RETURNS VARCHAR(20)
DETERMINISTIC
NO SQL
BEGINIF score >= 90 THENRETURN 'Excellent';ELSEIF score >= 80 THENRETURN 'Good';ELSEIF score >= 70 THENRETURN 'Average';ELSEIF score >= 60 THENRETURN 'Pass';ELSERETURN 'Fail';END IF;
END $$-- 復雜條件判斷
CREATE FUNCTION calculate_shipping_fee(weight DECIMAL(5,2), distance INT, is_express BOOLEAN)
RETURNS DECIMAL(8,2)
DETERMINISTIC
NO SQL
BEGINDECLARE base_fee DECIMAL(8,2);DECLARE distance_fee DECIMAL(8,2);DECLARE express_fee DECIMAL(8,2) DEFAULT 0;DECLARE total_fee DECIMAL(8,2);-- 基礎費用計算IF weight <= 1.0 THENSET base_fee = 8.00;ELSEIF weight <= 5.0 THENSET base_fee = 12.00;ELSEIF weight <= 10.0 THENSET base_fee = 18.00;ELSESET base_fee = 25.00;END IF;-- 距離費用IF distance <= 100 THENSET distance_fee = 0;ELSEIF distance <= 500 THENSET distance_fee = 5.00;ELSESET distance_fee = 10.00;END IF;-- 加急費用IF is_express THENSET express_fee = base_fee * 0.5;END IF;SET total_fee = base_fee + distance_fee + express_fee;RETURN total_fee;
END $$DELIMITER ;
CASE語句
DELIMITER $$-- 基礎CASE使用
CREATE FUNCTION get_month_name(month_num INT)
RETURNS VARCHAR(20)
DETERMINISTIC
NO SQL
BEGINCASE month_numWHEN 1 THEN RETURN 'January';WHEN 2 THEN RETURN 'February';WHEN 3 THEN RETURN 'March';WHEN 4 THEN RETURN 'April';WHEN 5 THEN RETURN 'May';WHEN 6 THEN RETURN 'June';WHEN 7 THEN RETURN 'July';WHEN 8 THEN RETURN 'August';WHEN 9 THEN RETURN 'September';WHEN 10 THEN RETURN 'October';WHEN 11 THEN RETURN 'November';WHEN 12 THEN RETURN 'December';ELSE RETURN 'Invalid Month';END CASE;
END $$-- 條件CASE使用
CREATE FUNCTION calculate_tax_rate(income DECIMAL(12,2), tax_type VARCHAR(20))
RETURNS DECIMAL(5,4)
DETERMINISTIC
NO SQL
BEGINDECLARE tax_rate DECIMAL(5,4);CASE tax_typeWHEN 'individual' THENCASEWHEN income <= 36000 THEN SET tax_rate = 0.03;WHEN income <= 144000 THEN SET tax_rate = 0.10;WHEN income <= 300000 THEN SET tax_rate = 0.20;ELSE SET tax_rate = 0.25;END CASE;WHEN 'corporate' THENCASEWHEN income <= 2500000 THEN SET tax_rate = 0.20;ELSE SET tax_rate = 0.25;END CASE;ELSESET tax_rate = 0.00;END CASE;RETURN tax_rate;
END $$DELIMITER ;

4.3 NULL值處理

DELIMITER $$-- 基礎NULL處理
CREATE FUNCTION safe_divide(dividend DECIMAL(10,2), divisor DECIMAL(10,2))
RETURNS DECIMAL(10,2)
DETERMINISTIC
NO SQL
BEGIN-- 檢查NULL值IF dividend IS NULL OR divisor IS NULL THENRETURN NULL;END IF;-- 檢查除零IF divisor = 0 THENRETURN NULL;END IF;RETURN dividend / divisor;
END $$-- 使用COALESCE處理NULL
CREATE FUNCTION calculate_total_with_defaults(base_amount DECIMAL(10,2),tax_rate DECIMAL(4,3),discount_amount DECIMAL(10,2)
)
RETURNS DECIMAL(10,2)
DETERMINISTIC
NO SQL
BEGINDECLARE total DECIMAL(10,2);-- 使用默認值處理NULLSET base_amount = COALESCE(base_amount, 0.00);SET tax_rate = COALESCE(tax_rate, 0.000);SET discount_amount = COALESCE(discount_amount, 0.00);-- 計算總額SET total = base_amount * (1 + tax_rate) - discount_amount;-- 確保結果不為負IF total < 0 THENSET total = 0.00;END IF;RETURN total;
END $$-- 數據庫查詢中的NULL處理
CREATE FUNCTION get_student_info_safe(student_id INT)
RETURNS VARCHAR(200)
READS SQL DATA
BEGINDECLARE student_name VARCHAR(50);DECLARE student_score INT;DECLARE result VARCHAR(200);SELECT name, score INTO student_name, student_scoreFROM students WHERE id = student_id;-- 處理查詢結果為NULL的情況IF student_name IS NULL THENRETURN 'Student not found';END IF;SET result = CONCAT('Name: ', student_name,', Score: ', COALESCE(student_score, 0),', Level: ', CASEWHEN student_score IS NULL THEN 'No Score'WHEN student_score >= 90 THEN 'A'WHEN student_score >= 80 THEN 'B'WHEN student_score >= 70 THEN 'C'WHEN student_score >= 60 THEN 'D'ELSE 'F'END);RETURN result;
END $$DELIMITER ;

測試函數

-- 變量操作測試
SELECT demonstrate_variables(5);
SELECT calculate_compound_result(1000.00, 0.05, 3);-- 條件判斷測試
SELECT check_score_level(85);
SELECT calculate_shipping_fee(2.5, 300, TRUE);
SELECT get_month_name(6);
SELECT calculate_tax_rate(50000, 'individual');-- NULL處理測試
SELECT safe_divide(10, 3);
SELECT safe_divide(10, 0);
SELECT safe_divide(NULL, 5);
SELECT calculate_total_with_defaults(100.00, NULL, 10.00);
SELECT get_student_info_safe(1);
SELECT get_student_info_safe(99);

5. 實際應用場景

5.1 電商價格計算系統

創建電商相關表:

-- 商品表
CREATE TABLE IF NOT EXISTS products (id INT PRIMARY KEY,name VARCHAR(100),base_price DECIMAL(8,2),category VARCHAR(50),weight DECIMAL(5,2)
);-- 用戶表
CREATE TABLE IF NOT EXISTS customers (id INT PRIMARY KEY,name VARCHAR(50),level VARCHAR(20),total_orders INT
);-- 優惠券表
CREATE TABLE IF NOT EXISTS coupons (code VARCHAR(20) PRIMARY KEY,discount_type ENUM('percentage', 'fixed'),discount_value DECIMAL(8,2),min_amount DECIMAL(8,2),is_active BOOLEAN
);-- 插入測試數據
INSERT IGNORE INTO products VALUES 
(1, 'iPhone 15', 7999.00, 'Electronics', 0.2),
(2, 'T-Shirt', 99.00, 'Clothing', 0.3),
(3, 'Programming Book', 89.00, 'Books', 0.5);INSERT IGNORE INTO customers VALUES 
(1, '張三', 'VIP', 25),
(2, '李四', 'Gold', 15),
(3, '王五', 'Silver', 8);INSERT IGNORE INTO coupons VALUES 
('SAVE10', 'percentage', 10.00, 100.00, TRUE),
('SAVE50', 'fixed', 50.00, 200.00, TRUE),
('VIP20', 'percentage', 20.00, 500.00, TRUE);
DELIMITER $$-- 計算會員折扣率
CREATE FUNCTION get_member_discount_rate(customer_level VARCHAR(20))
RETURNS DECIMAL(4,3)
DETERMINISTIC
NO SQL
BEGINCASE customer_levelWHEN 'VIP' THEN RETURN 0.080;      -- 8%折扣WHEN 'Gold' THEN RETURN 0.050;     -- 5%折扣WHEN 'Silver' THEN RETURN 0.030;   -- 3%折扣WHEN 'Bronze' THEN RETURN 0.010;   -- 1%折扣ELSE RETURN 0.000;                 -- 無折扣END CASE;
END $$-- 計算運費
CREATE FUNCTION calculate_shipping_cost(weight DECIMAL(5,2), distance INT)
RETURNS DECIMAL(6,2)
DETERMINISTIC
NO SQL
BEGINDECLARE base_cost DECIMAL(6,2);DECLARE weight_cost DECIMAL(6,2);DECLARE distance_cost DECIMAL(6,2);-- 基礎運費SET base_cost = 8.00;-- 重量費用IF weight <= 0.5 THENSET weight_cost = 0.00;ELSEIF weight <= 2.0 THENSET weight_cost = 5.00;ELSEIF weight <= 5.0 THENSET weight_cost = 12.00;ELSESET weight_cost = 20.00;END IF;-- 距離費用IF distance <= 100 THENSET distance_cost = 0.00;ELSEIF distance <= 500 THENSET distance_cost = 8.00;ELSESET distance_cost = 15.00;END IF;RETURN base_cost + weight_cost + distance_cost;
END $$-- 應用優惠券
CREATE FUNCTION apply_coupon_discount(amount DECIMAL(10,2), coupon_code VARCHAR(20))
RETURNS DECIMAL(10,2)
READS SQL DATA
BEGINDECLARE discount_type ENUM('percentage', 'fixed');DECLARE discount_value DECIMAL(8,2);DECLARE min_amount DECIMAL(8,2);DECLARE is_active BOOLEAN;DECLARE discount_amount DECIMAL(10,2) DEFAULT 0.00;-- 查詢優惠券信息SELECT discount_type, discount_value, min_amount, is_activeINTO discount_type, discount_value, min_amount, is_activeFROM couponsWHERE code = coupon_code;-- 驗證優惠券IF discount_type IS NULL OR NOT is_active THENRETURN amount;  -- 優惠券無效,返回原價END IF;IF amount < min_amount THENRETURN amount;  -- 不滿足最低消費,返回原價END IF;-- 計算折扣IF discount_type = 'percentage' THENSET discount_amount = amount * (discount_value / 100);ELSESET discount_amount = discount_value;END IF;-- 確保折扣后價格不為負IF amount - discount_amount < 0 THENRETURN 0.00;END IF;RETURN amount - discount_amount;
END $$-- 綜合價格計算
CREATE FUNCTION calculate_final_price(product_id INT,quantity INT,customer_id INT,coupon_code VARCHAR(20),shipping_distance INT
)
RETURNS JSON
READS SQL DATA
BEGINDECLARE product_price DECIMAL(8,2);DECLARE product_weight DECIMAL(5,2);DECLARE customer_level VARCHAR(20);DECLARE subtotal DECIMAL(10,2);DECLARE member_discount DECIMAL(10,2);DECLARE coupon_discount DECIMAL(10,2);DECLARE shipping_cost DECIMAL(6,2);DECLARE final_total DECIMAL(10,2);DECLARE result JSON;-- 查詢商品信息SELECT base_price, weight INTO product_price, product_weightFROM products WHERE id = product_id;-- 查詢客戶等級SELECT level INTO customer_levelFROM customers WHERE id = customer_id;-- 驗證數據IF product_price IS NULL THENRETURN JSON_OBJECT('error', 'Product not found');END IF;-- 計算小計SET subtotal = product_price * quantity;-- 應用會員折扣SET member_discount = subtotal * get_member_discount_rate(COALESCE(customer_level, 'Bronze'));SET subtotal = subtotal - member_discount;-- 應用優惠券IF coupon_code IS NOT NULL THENSET coupon_discount = subtotal - apply_coupon_discount(subtotal, coupon_code);SET subtotal = apply_coupon_discount(subtotal, coupon_code);ELSESET coupon_discount = 0.00;END IF;-- 計算運費SET shipping_cost = calculate_shipping_cost(product_weight * quantity, shipping_distance);-- 最終總價SET final_total = subtotal + shipping_cost;-- 構建結果JSONSET result = JSON_OBJECT('product_id', product_id,'quantity', quantity,'unit_price', product_price,'subtotal_before_discount', product_price * quantity,'member_discount', member_discount,'coupon_discount', coupon_discount,'subtotal_after_discount', subtotal,'shipping_cost', shipping_cost,'final_total', final_total,'customer_level', COALESCE(customer_level, 'Bronze'));RETURN result;
END $$DELIMITER ;

5.2 學生成績管理系統

-- 擴展學生表
CREATE TABLE IF NOT EXISTS student_grades (id INT PRIMARY KEY,name VARCHAR(50),math DECIMAL(5,2),english DECIMAL(5,2),science DECIMAL(5,2),chinese DECIMAL(5,2),class_id INT
);INSERT IGNORE INTO student_grades VALUES 
(1, '小明', 85.5, 78.0, 92.5, 88.0, 1),
(2, '小紅', 92.0, 88.5, 85.0, 90.5, 1),
(3, '小李', 78.5, 85.0, 90.0, 82.5, 2),
(4, '小王', 88.0, 92.0, 78.5, 85.5, 2),
(5, '小張', 95.0, 89.5, 94.0, 93.5, 1);DELIMITER $$-- 計算學生總分和平均分
CREATE FUNCTION calculate_student_stats(student_id INT)
RETURNS JSON
READS SQL DATA
BEGINDECLARE math_score, english_score, science_score, chinese_score DECIMAL(5,2);DECLARE total_score DECIMAL(6,2);DECLARE average_score DECIMAL(5,2);DECLARE grade_level VARCHAR(10);DECLARE student_name VARCHAR(50);-- 查詢學生成績SELECT name, math, english, science, chineseINTO student_name, math_score, english_score, science_score, chinese_scoreFROM student_gradesWHERE id = student_id;-- 檢查學生是否存在IF student_name IS NULL THENRETURN JSON_OBJECT('error', 'Student not found');END IF;-- 處理NULL成績SET math_score = COALESCE(math_score, 0);SET english_score = COALESCE(english_score, 0);SET science_score = COALESCE(science_score, 0);SET chinese_score = COALESCE(chinese_score, 0);-- 計算總分和平均分SET total_score = math_score + english_score + science_score + chinese_score;SET average_score = total_score / 4;-- 確定等級CASEWHEN average_score >= 90 THEN SET grade_level = 'A';WHEN average_score >= 80 THEN SET grade_level = 'B';WHEN average_score >= 70 THEN SET grade_level = 'C';WHEN average_score >= 60 THEN SET grade_level = 'D';ELSE SET grade_level = 'F';END CASE;RETURN JSON_OBJECT('student_id', student_id,'name', student_name,'scores', JSON_OBJECT('math', math_score,'english', english_score,'science', science_score,'chinese', chinese_score),'total_score', total_score,'average_score', ROUND(average_score, 2),'grade_level', grade_level);
END $$-- 班級排名計算
CREATE FUNCTION get_student_rank_in_class(student_id INT)
RETURNS INT
READS SQL DATA
BEGINDECLARE student_avg DECIMAL(5,2);DECLARE student_class_id INT;DECLARE student_rank INT;-- 獲取學生平均分和班級SELECT (COALESCE(math,0) + COALESCE(english,0) + COALESCE(science,0) + COALESCE(chinese,0))/4, class_idINTO student_avg, student_class_idFROM student_gradesWHERE id = student_id;IF student_avg IS NULL THENRETURN 0;END IF;-- 計算排名(比該學生平均分高的人數 + 1)SELECT COUNT(*) + 1 INTO student_rankFROM student_gradesWHERE class_id = student_class_idAND (COALESCE(math,0) + COALESCE(english,0) + COALESCE(science,0) + COALESCE(chinese,0))/4 > student_avg;RETURN student_rank;
END $$-- 科目強弱分析
CREATE FUNCTION analyze_subject_strength(student_id INT)
RETURNS JSON
READS SQL DATA
BEGINDECLARE math_score, english_score, science_score, chinese_score DECIMAL(5,2);DECLARE max_score, min_score DECIMAL(5,2);DECLARE strongest_subject, weakest_subject VARCHAR(20);SELECT math, english, science, chineseINTO math_score, english_score, science_score, chinese_scoreFROM student_gradesWHERE id = student_id;IF math_score IS NULL THENRETURN JSON_OBJECT('error', 'Student not found');END IF;-- 處理NULL值SET math_score = COALESCE(math_score, 0);SET english_score = COALESCE(english_score, 0);SET science_score = COALESCE(science_score, 0);SET chinese_score = COALESCE(chinese_score, 0);-- 找最高分科目SET max_score = GREATEST(math_score, english_score, science_score, chinese_score);SET min_score = LEAST(math_score, english_score, science_score, chinese_score);-- 確定最強科目CASE max_scoreWHEN math_score THEN SET strongest_subject = 'Math';WHEN english_score THEN SET strongest_subject = 'English';WHEN science_score THEN SET strongest_subject = 'Science';WHEN chinese_score THEN SET strongest_subject = 'Chinese';END CASE;-- 確定最弱科目CASE min_scoreWHEN math_score THEN SET weakest_subject = 'Math';WHEN english_score THEN SET weakest_subject = 'English';WHEN science_score THEN SET weakest_subject = 'Science';WHEN chinese_score THEN SET weakest_subject = 'Chinese';END CASE;RETURN JSON_OBJECT('strongest_subject', strongest_subject,'strongest_score', max_score,'weakest_subject', weakest_subject,'weakest_score', min_score,'score_gap', max_score - min_score,'recommendation', CASEWHEN max_score - min_score > 20 THEN 'Focus on improving weak subjects'WHEN max_score - min_score > 10 THEN 'Balanced development needed'ELSE 'Well-balanced performance'END);
END $$DELIMITER ;

5.3 金融計算系統

DELIMITER $$-- 復利計算
CREATE FUNCTION calculate_compound_interest(principal DECIMAL(12,2),annual_rate DECIMAL(6,4),years INT,compound_frequency INT
)
RETURNS JSON
DETERMINISTIC
NO SQL
BEGINDECLARE final_amount DECIMAL(12,2);DECLARE total_interest DECIMAL(12,2);DECLARE effective_rate DECIMAL(8,6);-- 輸入驗證IF principal <= 0 OR annual_rate < 0 OR years < 0 OR compound_frequency <= 0 THENRETURN JSON_OBJECT('error', 'Invalid input parameters');END IF;-- 計算復利:A = P(1 + r/n)^(nt)SET final_amount = principal * POWER(1 + annual_rate/compound_frequency, compound_frequency * years);SET total_interest = final_amount - principal;SET effective_rate = POWER(1 + annual_rate/compound_frequency, compound_frequency) - 1;RETURN JSON_OBJECT('principal', principal,'annual_rate_percent', annual_rate * 100,'years', years,'compound_frequency', compound_frequency,'final_amount', ROUND(final_amount, 2),'total_interest', ROUND(total_interest, 2),'effective_annual_rate_percent', ROUND(effective_rate * 100, 4));
END $$-- 貸款月供計算
CREATE FUNCTION calculate_loan_payment(loan_amount DECIMAL(12,2),annual_rate DECIMAL(6,4),years INT
)
RETURNS JSON
DETERMINISTIC
NO SQL
BEGINDECLARE monthly_rate DECIMAL(8,6);DECLARE total_payments INT;DECLARE monthly_payment DECIMAL(10,2);DECLARE total_paid DECIMAL(12,2);DECLARE total_interest DECIMAL(12,2);-- 輸入驗證IF loan_amount <= 0 OR annual_rate <= 0 OR years <= 0 THENRETURN JSON_OBJECT('error', 'Invalid input parameters');END IF;SET monthly_rate = annual_rate / 12;SET total_payments = years * 12;-- 計算月供:M = P * [r(1+r)^n] / [(1+r)^n - 1]IF monthly_rate = 0 THENSET monthly_payment = loan_amount / total_payments;ELSESET monthly_payment = loan_amount * (monthly_rate * POWER(1 + monthly_rate, total_payments)) / (POWER(1 + monthly_rate, total_payments) - 1);END IF;SET total_paid = monthly_payment * total_payments;SET total_interest = total_paid - loan_amount;RETURN JSON_OBJECT('loan_amount', loan_amount,'annual_rate_percent', annual_rate * 100,'loan_term_years', years,'monthly_payment', ROUND(monthly_payment, 2),'total_payments', total_payments,'total_amount_paid', ROUND(total_paid, 2),'total_interest_paid', ROUND(total_interest, 2));
END $$-- 投資回報率計算
CREATE FUNCTION calculate_investment_return(initial_investment DECIMAL(12,2),final_value DECIMAL(12,2),years DECIMAL(5,2)
)
RETURNS JSON
DETERMINISTIC
NO SQL
BEGINDECLARE absolute_return DECIMAL(12,2);DECLARE percentage_return DECIMAL(8,4);DECLARE annualized_return DECIMAL(8,4);-- 輸入驗證IF initial_investment <= 0 OR final_value < 0 OR years <= 0 THENRETURN JSON_OBJECT('error', 'Invalid input parameters');END IF;SET absolute_return = final_value - initial_investment;SET percentage_return = (final_value - initial_investment) / initial_investment;-- 年化收益率:(Final/Initial)^(1/years) - 1SET annualized_return = POWER(final_value / initial_investment, 1/years) - 1;RETURN JSON_OBJECT('initial_investment', initial_investment,'final_value', final_value,'investment_period_years', years,'absolute_return', ROUND(absolute_return, 2),'percentage_return', ROUND(percentage_return * 100, 2),'annualized_return_percent', ROUND(annualized_return * 100, 2),'performance_rating', CASEWHEN annualized_return >= 0.15 THEN 'Excellent'WHEN annualized_return >= 0.10 THEN 'Good'WHEN annualized_return >= 0.05 THEN 'Average'WHEN annualized_return >= 0 THEN 'Below Average'ELSE 'Loss'END);
END $$DELIMITER ;

6. 性能優化和最佳實踐

6.1 性能優化原則

優化原則說明示例
最小化數據庫查詢盡量用一次查詢獲取多個值避免在函數中多次SELECT同一表
合適的數據類型使用精確的數據類型年齡用TINYINT而不是INT
避免在WHERE中使用函數防止索引失效建立計算列或使用其他優化方式
減少復雜計算避免在大數據集上使用復雜函數考慮預計算或緩存結果
合理使用DETERMINISTIC確定性函數可以被緩存純計算函數標記為DETERMINISTIC

6.2 常見錯誤和解決方案

-- ? 錯誤1:忘記DELIMITER
CREATE FUNCTION bad_function(x INT)
RETURNS INT
BEGINRETURN x * 2;  -- MySQL會在這里認為語句結束
END-- ? 正確寫法
DELIMITER $$
CREATE FUNCTION good_function(x INT)
RETURNS INT
DETERMINISTIC
NO SQL
BEGINRETURN x * 2;
END $$
DELIMITER ;-- ? 錯誤2:返回類型不匹配
DELIMITER $$
CREATE FUNCTION type_mismatch(x INT)
RETURNS INT  -- 聲明返回INT
DETERMINISTIC
NO SQL
BEGINRETURN 'hello';  -- 實際返回字符串
END $$
DELIMITER ;-- ? 正確寫法
DELIMITER $$
CREATE FUNCTION type_correct(x INT)
RETURNS VARCHAR(10)  -- 聲明返回字符串
DETERMINISTIC
NO SQL
BEGINRETURN 'hello';
END $$
DELIMITER ;-- ? 錯誤3:未處理NULL值
DELIMITER $$
CREATE FUNCTION unsafe_calculation(a INT, b INT)
RETURNS INT
DETERMINISTIC
NO SQL
BEGINRETURN a + b;  -- 如果a或b為NULL,結果也是NULL
END $$
DELIMITER ;-- ? 正確寫法
DELIMITER $$
CREATE FUNCTION safe_calculation(a INT, b INT)
RETURNS INT
DETERMINISTIC
NO SQL
BEGINRETURN COALESCE(a, 0) + COALESCE(b, 0);
END $$
DELIMITER ;-- ? 錯誤4:性能問題 - 多次查詢
DELIMITER $$
CREATE FUNCTION slow_student_info(student_id INT)
RETURNS VARCHAR(200)
READS SQL DATA
BEGINDECLARE name VARCHAR(50);DECLARE score INT;SELECT name INTO name FROM students WHERE id = student_id;SELECT score INTO score FROM students WHERE id = student_id;  -- 重復查詢RETURN CONCAT(name, ':', score);
END $$
DELIMITER ;-- ? 正確寫法
DELIMITER $$
CREATE FUNCTION fast_student_info(student_id INT)
RETURNS VARCHAR(200)
READS SQL DATA
BEGINDECLARE result VARCHAR(200);SELECT CONCAT(name, ':', COALESCE(score, 0)) INTO resultFROM students WHERE id = student_id;RETURN COALESCE(result, 'Student not found');
END $$
DELIMITER ;

6.3 調試和測試策略

DELIMITER $$-- 調試技巧:分步返回中間結果
CREATE FUNCTION debug_complex_calculation(input_val INT)
RETURNS DECIMAL(10,2)
DETERMINISTIC
NO SQL
BEGINDECLARE step1 DECIMAL(10,2);DECLARE step2 DECIMAL(10,2);DECLARE final_result DECIMAL(10,2);SET step1 = input_val * 1.5;SET step2 = step1 + 100;SET final_result = step2 * 0.8;-- 調試時可以返回中間值-- RETURN step1;  -- 調試第一步-- RETURN step2;  -- 調試第二步RETURN final_result;  -- 最終結果
END $$-- 錯誤處理和驗證
CREATE FUNCTION robust_calculation(amount DECIMAL(10,2),rate DECIMAL(5,4),periods INT
)
RETURNS JSON
DETERMINISTIC
NO SQL
BEGINDECLARE result DECIMAL(12,2);DECLARE error_msg VARCHAR(100) DEFAULT '';-- 輸入驗證IF amount IS NULL THENSET error_msg = 'Amount cannot be NULL';ELSEIF amount <= 0 THENSET error_msg = 'Amount must be positive';ELSEIF rate IS NULL THENSET error_msg = 'Rate cannot be NULL';ELSEIF rate < 0 THENSET error_msg = 'Rate cannot be negative';ELSEIF periods IS NULL THENSET error_msg = 'Periods cannot be NULL';ELSEIF periods <= 0 THENSET error_msg = 'Periods must be positive';END IF;-- 如果有錯誤,返回錯誤信息IF error_msg != '' THENRETURN JSON_OBJECT('error', error_msg);END IF;-- 執行計算SET result = amount * POWER(1 + rate, periods);RETURN JSON_OBJECT('success', TRUE,'input', JSON_OBJECT('amount', amount, 'rate', rate, 'periods', periods),'result', ROUND(result, 2));
END $$DELIMITER ;

7. 與相關技術對比

7.1 自定義函數 vs 存儲過程 vs 視圖

特性自定義函數存儲過程視圖
返回值必須返回單個值可以返回多個結果集或不返回返回查詢結果集
調用方式在SQL表達式中調用使用CALL語句調用像表一樣查詢
事務控制? 不支持? 完全支持? 不適用
參數支持只支持IN參數支持IN、OUT、INOUT參數? 不支持參數
數據修改🔸 受限支持? 完全支持? 受限支持
性能🔸 中等(計算密集)? 高(批處理)? 高(簡單查詢)
復用性? 很好? 很好🔸 受限
調試難度🔸 中等🔸 中等? 簡單

7.2 選擇指南

使用自定義函數的場景

  • ? 需要在SELECT語句中使用計算結果
  • ? 計算邏輯相對簡單
  • ? 需要返回單個值
  • ? 不需要事務控制

使用存儲過程的場景

  • ? 需要復雜的業務邏輯處理
  • ? 需要事務控制
  • ? 需要返回多個結果集
  • ? 涉及多表數據修改

使用視圖的場景

  • ? 簡化復雜查詢
  • ? 提供數據安全性
  • ? 查詢邏輯相對固定
  • ? 不適合動態計算

8. 面試常見問題

8.1 基礎概念類

Q: 什么是MySQL自定義函數?它有什么作用?

A: MySQL自定義函數是用戶創建的可重復使用的程序單元,它接受參數、執行特定的計算邏輯并返回一個確定的值。

核心作用:

  • 代碼復用:避免重復編寫相同的計算邏輯
  • 性能優化:在數據庫層面進行計算,減少數據傳輸
  • 邏輯封裝:將復雜的業務規則封裝成簡單的函數調用
  • 一致性保證:確保相同的計算在不同地方得到一致的結果

Q: DETERMINISTIC和NOT DETERMINISTIC有什么區別?什么時候使用?

A:

  • DETERMINISTIC(確定性):相同的輸入參數總是產生相同的輸出結果,不依賴于外部變量
  • NOT DETERMINISTIC(非確定性):相同的輸入可能產生不同的輸出,依賴于時間、隨機數等

使用場景:

-- DETERMINISTIC:純數學計算
CREATE FUNCTION calculate_tax(amount DECIMAL(10,2))
RETURNS DECIMAL(10,2)
DETERMINISTIC
BEGINRETURN amount * 0.08;  -- 相同金額總是相同稅費
END $$-- NOT DETERMINISTIC:時間相關
CREATE FUNCTION get_age(birth_year INT)
RETURNS INT
NOT DETERMINISTIC
BEGINRETURN YEAR(CURDATE()) - birth_year;  -- 結果隨年份變化
END $$

8.2 實際應用類

Q: 在什么情況下使用自定義函數?請舉例說明

A: 自定義函數適用于以下場景:

  1. 復雜計算需要復用
-- 電商積分計算
CREATE FUNCTION calculate_points(amount DECIMAL(10,2), level VARCHAR(20))
RETURNS INT
DETERMINISTIC
BEGINDECLARE multiplier DECIMAL(3,2);CASE levelWHEN 'VIP' THEN SET multiplier = 2.0;WHEN 'Gold' THEN SET multiplier = 1.5;ELSE SET multiplier = 1.0;END CASE;RETURN FLOOR(amount * multiplier / 10);
END $$
  1. 數據格式化和轉換
-- 手機號脫敏
CREATE FUNCTION mask_phone(phone VARCHAR(20))
RETURNS VARCHAR(20)
DETERMINISTIC
BEGINIF LENGTH(phone) >= 7 THENRETURN CONCAT(LEFT(phone, 3), '****', RIGHT(phone, 4));END IF;RETURN phone;
END $$

Q: 如何優化自定義函數的性能?

A: 主要優化策略:

  1. 減少數據庫查詢
-- ? 多次查詢
SELECT name INTO name FROM users WHERE id = user_id;
SELECT email INTO email FROM users WHERE id = user_id;-- ? 一次查詢
SELECT name, email INTO name, email FROM users WHERE id = user_id;
  1. 使用合適的數據類型
-- ? 精確的數據類型
CREATE FUNCTION get_age(birth_date DATE)
RETURNS TINYINT  -- 年齡用TINYINT足夠
  1. 避免在WHERE子句中使用函數
-- ? 無法使用索引
SELECT * FROM orders WHERE calculate_total(id) > 1000;-- ? 預計算或使用其他方式
ALTER TABLE orders ADD total_amount DECIMAL(10,2);
SELECT * FROM orders WHERE total_amount > 1000;

9. 學習總結

9.1 核心知識回顧

通過這份學習筆記,你現在應該掌握了:

基礎語法

  • CREATE FUNCTION的基本結構和各部分含義
  • DELIMITER的使用原因和正確方法
  • 函數特性的選擇和應用場景

編程構造

  • 變量聲明(DECLARE)和賦值(SET
  • 條件判斷(IF...THEN...ELSECASE...WHEN
  • NULL值處理的重要性和方法

實際應用

  • 數學計算、字符串處理、日期時間函數
  • 電商、教育、金融等業務場景的函數設計
  • 性能優化和錯誤處理的最佳實踐

9.2 下一步學習建議

初學者(剛完成本教程)

  1. 練習編寫20-30個不同類型的簡單函數
  2. 嘗試將日常計算需求封裝成函數
  3. 學會調試和測試函數

進階學習者

  1. 學習存儲過程(Stored Procedures)
  2. 學習觸發器(Triggers)
  3. 深入理解MySQL的執行計劃和性能優化

實踐建議

  • 在實際項目中應用所學知識
  • 關注函數的性能表現和優化
  • 建立自己的函數庫和最佳實踐

記住:好的程序員是通過不斷練習和學習成長的。每掌握一個概念,都要確保真正理解后再繼續。祝你學習愉快!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/86417.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/86417.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/86417.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

八股---7.JVM

1. JVM組成 1.1 JVM由哪些部分組成?運行流程? 難易程度:☆☆☆ 出現頻率:☆☆☆☆ Java Virtual Machine:Java 虛擬機,Java程序的運行環境(java二進制字節碼的運行環境)好處:一次編寫,到處運行;自動內存管理,垃圾回收機制程序運行之前,需要先通過編譯器將…

企業級AI-DevOps工具鏈的構成及實現方案

企業級AI-DevOps工具鏈的構成及實現方案 DevOps在AI大模型研發中的重要性及應用背景一、場景驅動的AI產品研發運營機制二、AI-DevOps生產線建設三、基于DevOps的AI大模型研發機制四、基于DevOps的智能體場景研發機制五、場景驅動的應用評估分析機制 DevOps在AI大模型研發中的重…

在 Spring Boot 項目里,MYSQL中json類型字段使用

前言&#xff1a; 因為程序特殊需求導致&#xff0c;需要mysql數據庫存儲json類型數據&#xff0c;因此記錄一下使用流程 1.java實體中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…

Python競賽環境搭建全攻略

Python環境搭建競賽技術文章大綱 競賽背景與意義 競賽的目的與價值Python在競賽中的應用場景環境搭建對競賽效率的影響 競賽環境需求分析 常見競賽類型&#xff08;算法、數據分析、機器學習等&#xff09;不同競賽對Python版本及庫的要求硬件與操作系統的兼容性問題 Pyth…

在 Win10 上 WSL 安裝 Debian 12 后,Linux 如何啟動 SMTP 服務?

在 WSL 的 Debian 12 中啟動 SMTP 服務&#xff08;以 Postfix 為例&#xff09;&#xff0c;請按以下步驟操作&#xff1a; 1. 安裝 Postfix sudo apt update sudo apt install postfix mailutils安裝過程中會彈出配置窗口&#xff1a; General type of mail configuration&a…

樹莓派超全系列教程文檔--(59)樹莓派攝像頭rpicam-apps

這里寫目錄標題 rpicam-apps libcamera 文章來源&#xff1a; http://raspberry.dns8844.cn/documentation 原文網址 rpicam-apps 樹莓派操作系統 Bookworm 將相機捕捉應用程序從 libcamera-\* 重命名為 rpicam-*。符號鏈接允許用戶暫時使用舊名稱。盡快采用新的應用程序名稱…

【數據結構】圖論最短路徑算法深度解析:從BFS基礎到全算法綜述?

最短路徑 導讀一、最短路徑1.1 單源最短路徑1.2 各頂點間的最短路徑1.3 最短路徑算法 二、BFS算法結語內容回顧下一篇預告&#xff1a;挑戰帶權最短路徑&#xff01; 導讀 大家好&#xff0c;很高興又和大家見面啦&#xff01;&#xff01;&#xff01; 歡迎繼續探索圖算法的…

中國政務數據安全建設細化及市場需求分析

(基于新《政務數據共享條例》及相關法規) 一、引言 近年來,中國政府高度重視數字政府建設和數據要素市場化配置改革。《政務數據共享條例》(以下簡稱“《共享條例》”)的發布,與《中華人民共和國數據安全法》(以下簡稱“《數據安全法》”)、《中華人民共和國個人信息…

Linux信號保存與處理機制詳解

Linux信號的保存與處理涉及多個關鍵機制&#xff0c;以下是詳細的總結&#xff1a; 1. 信號的保存 進程描述符&#xff08;task_struct&#xff09;&#xff1a;每個進程的PCB中包含信號相關信息。 pending信號集&#xff1a;記錄已到達但未處理的信號&#xff08;未決信號&a…

【Redis】筆記|第10節|京東HotKey實現多級緩存架構

緩存架構 京東HotKey架構 代碼結構 代碼詳情 功能點&#xff1a;&#xff08;如代碼有錯誤&#xff0c;歡迎討論糾正&#xff09; 多級緩存&#xff0c;先查HotKey緩存&#xff0c;再查Redis&#xff0c;最后才查數據庫熱點數據重建邏輯使用分布式鎖&#xff0c;二次查詢更新…

php apache構建 Web 服務器

虛擬機配置流程winsever2016配置Apache、Mysql、php_windows server 2016配置web服務器-CSDN博客 PHP 和 Apache 通過 ??模塊化協作?? 共同構建 Web 服務器&#xff0c;以下是它們的交互機制和工作流程&#xff1a; ??一、核心組件分工?? 組件角色??Apache??Web …

二分查找排序講解

一、二分查找&#xff08;Binary Search&#xff09; 核心思想&#xff1a; 前提&#xff1a;數組必須是 有序的&#xff08;比如從小到大排列&#xff09;。目標&#xff1a;在數組中快速找到某個數&#xff08;比如找 7&#xff09;。方法&#xff1a;每次排除一半的數&…

【Redis實戰:緩存與消息隊列的應用】

在現代互聯網開發中&#xff0c;Redis 作為一款高性能的內存數據庫&#xff0c;廣泛應用于緩存和消息隊列等場景。本文將深入探討 Redis 在這兩個領域的應用&#xff0c;并通過代碼示例比較兩個流行的框架&#xff08;Redis 和 RabbitMQ&#xff09;的特點與適用場景&#xff0…

[拓撲優化] 1.概述

常見的拓撲優化方法有&#xff1a;均勻化法、變密度法、漸進結構優化法、水平集法、移動可變形組件法等。 常見的數值計算方法有&#xff1a;有限元法、有限差分法、邊界元法、離散元法、無網格法、擴展有限元法、等幾何分析等。 將上述數值計算方法與拓撲優化方法結合&#…

【openssl】升級為3.3.1,避免安全漏洞

本文檔旨在形成 對Linux系統openssl版本進行升級 的搭建標準操作過程&#xff0c;搭建完成后&#xff0c;實現 openssl 達到3.3以上版本&#xff0c;避免安全漏洞 效果。 一、查看當前版本 版本不高于3.1的&#xff0c;均需要升級。 # 服務器上運行以下命令&#xff0c;查看…

基于正點原子阿波羅F429開發板的LWIP應用(6)——SNTP功能和lwiperf測速

說在開頭 正點原子F429開發板主芯片采用的是STM32F429IGT6&#xff0c;網絡PHY芯片采用的是LAN8720A(V1)和YT8512C(V2)&#xff0c;采用的是RMII連接&#xff0c;PHY_ADDR為0&#xff1b;在代碼中將會對不同的芯片做出適配。 CubeMX版本&#xff1a;6.6.1&#xff1b; F4芯片組…

C:\Users\中文名修改為英文名

C:\Users\中文名修改為英文名 背景操作步驟 背景 買了臺新電腦&#xff0c;初始化好不知道啥操作把自己的登錄用戶名改成了中文&#xff0c;有些安裝的軟件看見有中文直接就水土不服了。 操作步驟 以下稱中文用戶名為張三。 正常登錄張三用戶 進入用戶管理頁面修改用戶名&a…

YOLOv12環境配置,手把手教你使用YOLOv12訓練自己的數據集和推理(附YOLOv12網絡結構圖),全文最詳細教程

文章目錄 前言一、YOLOv12代碼下載地址1.YOLOv12模型結構圖 二、YOLO環境配置教程1.創建虛擬環境2.激活虛擬環境3.查詢自己電腦可支持最高cuda版本是多少&#xff08;無顯卡的同學可以跳過這個步驟&#xff09;4.pytorch安裝5.驗證 PyTorch GPU 是否可用&#xff08;沒有顯卡的…

ES6(ES2015)特性全解析

ES6&#xff08;ECMAScript 2015&#xff09;是 JavaScript 語言發展史上的一個重要里程碑&#xff0c;它引入了許多新的語法特性和功能&#xff0c;提升了代碼的可讀性、可維護性和開發效率。 1. 塊級作用域變量&#xff1a;let 和 const ES6 引入了 let 和 const 關鍵字&am…

jvm 垃圾收集算法 詳解

垃圾收集算法 分代收集理論 垃圾收集器的理論基礎&#xff0c;它建立在兩個分代假說之上&#xff1a; 弱分代假說&#xff1a;絕大多數對象都是朝生夕滅的。強分代假說&#xff1a;熬過越多次垃圾收集過程的對象就越難以消亡。 這兩個分代假說共同奠定了多款常用的垃圾收集…