MySQL之存儲(chǔ)過程與存儲(chǔ)函數(shù)使用及說明
1、創(chuàng)建存儲(chǔ)過程
存儲(chǔ)過程就是一條或者多條 SQL 語句的集合,可以視為批文件。它可以定義批量插入的語句,也可以定義一個(gè)接收不同條件的 SQL。
創(chuàng)建存儲(chǔ)過程的語句為 “create procedure”,創(chuàng)建存儲(chǔ)函數(shù)的語句為 “create function”。
調(diào)用存儲(chǔ)過程的語句為 “CALL”。
調(diào)用存儲(chǔ)函數(shù)的形式就像調(diào)用 MySQL 內(nèi)部函數(shù)一樣。
DROP TABLE IF EXISTS t_student;
CREATE TABLE t_student
(
id INT(11) PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
age INT(11) NOT NULL
);
INSERT INTO t_student VALUES(NULL,'大宇',22),(NULL,'小宇',20);

如上述,t_student 表中的數(shù)據(jù)有兩條。如果我們要分別查詢出來這兩條數(shù)據(jù),顯然就是根據(jù) ID 來查詢。查詢出來了第一條數(shù)據(jù)后,我們可能會(huì)去做其它的操作。等過兩天,我們要查詢另外一條記錄的時(shí)候,可能又要再寫一次這樣的查詢語句。
存儲(chǔ)過程和存儲(chǔ)函數(shù)應(yīng)運(yùn)而生,這樣就可以對(duì)某些 SQL 語句進(jìn)行封裝,從而實(shí)現(xiàn)功能的復(fù)用。
定義一個(gè)根據(jù) ID 查詢學(xué)生記錄的存儲(chǔ)過程:
DROP PROCEDURE IF EXISTS getStuById; DELIMITER // -- 定義存儲(chǔ)過程結(jié)束符號(hào)為// CREATE PROCEDURE getStuById(IN stuId INT(11),OUT stuName VARCHAR(255),OUT stuAge INT(11)) -- 定義輸入與輸出參數(shù) COMMENT 'query students by their id' -- 提示信息 SQL SECURITY DEFINER -- DEFINER指明只有定義此SQL的人才能執(zhí)行,MySQL默認(rèn)也是這個(gè) BEGIN SELECT name ,age INTO stuName , stuAge FROM t_student WHERE id = stuId; -- 分號(hào)要加 END // -- 結(jié)束符要加 DELIMITER ; -- 重新定義存儲(chǔ)過程結(jié)束符為分號(hào)
語法:“create procedure sp_name(定義輸入輸出參數(shù)) 【存儲(chǔ)特性】begin SQL語句;END”
IN 表示輸入?yún)?shù);OUT 表示輸出參數(shù);INOUT 表示既可以輸入也可以輸出的參數(shù);sp_name 為存儲(chǔ)過程的名字。
如果此存儲(chǔ)過程沒有任何輸入、輸出,其實(shí)就沒有什么意義了,但是 sp_name() 的括號(hào)不能省略。
查看剛才創(chuàng)建的存儲(chǔ)過程。
SHOW PROCEDURE STATUS LIKE 'g%'

下面是調(diào)用儲(chǔ)存過程。對(duì)于存儲(chǔ)過程提供的臨時(shí)變量而言,MySQL 規(guī)定要加上 “@” 開頭。
#study 是當(dāng)前數(shù)據(jù)庫名稱 CALL study.getStuById(1,@name,@age); SELECT @name AS stuName,@age AS stuAge;

CALL getStuById(2,@name,@age); SELECT @name AS stuName,@age AS stuAge;

這樣的好處是,如果一段較為復(fù)雜的 SQL 語句,我們可能過了幾天再去寫它,又費(fèi)時(shí)費(fèi)力。存儲(chǔ)過程可以
封裝我們寫過的 SQL,在下次只需要調(diào)用它的時(shí)候,直接提供參數(shù)并指明查詢結(jié)果輸出到哪些變量中即可。
提示:如果存儲(chǔ)過程一次查詢出兩個(gè)記錄,將會(huì)提示出錯(cuò)。"[Err] 1172 - Result consisted of more than one row"。
所以需要在存儲(chǔ)過程的 SQL 后面加上 “limit 1”。從位偏移量為 0 的,即從查詢結(jié)果的第一條數(shù)據(jù)開始,查詢一條記錄。
2、創(chuàng)建存儲(chǔ)函數(shù)
存儲(chǔ)函數(shù)與存儲(chǔ)過程本質(zhì)上是一樣的,都是封裝一系列 SQL 語句,簡化調(diào)用。
我們自己編寫的存儲(chǔ)函數(shù)可以像 MySQL 函數(shù)那樣自由的被調(diào)用。
DROP FUNCTION IF EXISTS getStuNameById; DELIMITER // CREATE FUNCTION getStuNameById(stuId INT) -- 默認(rèn)是IN,但是不能寫上去。stuId視為輸入的臨時(shí)變量 RETURNS VARCHAR(255) -- 指明返回值類型 RETURN (SELECT name FROM t_student WHERE id = stuId); // -- 指明SQL語句,并使用結(jié)束標(biāo)記。注意分號(hào)位置 DELIMITER ;
使用存儲(chǔ)函數(shù):
SELECT getStuNameById(1);

提示:在 return 語句后面,有趣的是,分號(hào)在 SQL 語句的外面。如果不加分號(hào),查詢結(jié)果居然查詢出兩條記錄。
從上述存儲(chǔ)函數(shù)的寫法上來看,存儲(chǔ)函數(shù)有一定的缺點(diǎn)。首先與存儲(chǔ)過程一樣,只能返回一條結(jié)果記錄。另外就是存儲(chǔ)函數(shù)只能指明一列數(shù)據(jù)作為結(jié)果,而存儲(chǔ)過程能夠指明多列數(shù)據(jù)作為結(jié)果。
3、定義變量
如果希望 MySQL 執(zhí)行批量插入的操作,那么至少要有一個(gè)計(jì)數(shù)器來計(jì)算當(dāng)前插入的是第幾次。
這里的變量是用在存儲(chǔ)過程中的 SQL 語句中的,變量的作用范圍在 “begin … end” 中。
沒有 default 子句,初始值為 NULL。
定義變量的操作:
DECLARE name,address VARCHAR; -- 發(fā)現(xiàn)了嗎,SQL中一般都喜歡先定義變量再定義類型,與Java是相反的。 DECLARE age INT DEFAULT 20; -- 指定默認(rèn)值。若沒有DEFAULT子句,初始值為NULL。
為變量賦值:
SET name = 'jay'; -- 為name變量設(shè)置值 DECLARE var1,var2,var3 INT; SET var1 = 10,var2 = 20; -- 其實(shí)為了簡化記憶其語法,可以分開來寫 -- SET var1 = 10; -- SET var2 = 20; SET var3 = var1 + var2;
使用變量實(shí)例。如下表,在做了去除主鍵約束后,我又添加了一條 “id=1” 的數(shù)據(jù)?,F(xiàn)在希望查詢出 “id=1” 記錄的數(shù)量。

DROP PROCEDURE IF EXISTS contStById;
DELIMITER // -- 定義存儲(chǔ)過程結(jié)束符號(hào)為//
CREATE PROCEDURE contStById(IN sid INT(11),OUT result INT(11)) -- 定義輸入變量
BEGIN
DECLARE sCount INT;
SELECT COUNT(*) INTO sCount FROM t_student WHERE id = sid;
SET result = sCount; -- 用變量為輸出結(jié)果設(shè)值
END // -- 結(jié)束符要加
DELIMITER ; -- 重新定義存儲(chǔ)過程結(jié)束符為分號(hào)
CALL contStById(1,@result);
SELECT @result;

顯然,在存儲(chǔ)過程中的變量,可以直接與輸出變量進(jìn)行相應(yīng)的計(jì)算。本例直接把 “sCount” 這個(gè)變量的值賦值到輸出中。
4、定義條件與定義處理程序
- 定義條件 condition:指的是在執(zhí)行存儲(chǔ)過程中的 SQL 語句時(shí),可能出現(xiàn)的問題;
- 定義處理程序 handler:當(dāng)遇到了指定問題時(shí)應(yīng)該如何處理,避免存儲(chǔ)過程因執(zhí)行異常而停止。
定義條件和定義處理程序的位置應(yīng)該在 “begin … end” 之間。
定義條件的語法:“declare condition_name condition for 錯(cuò)誤碼或錯(cuò)誤值;”
錯(cuò)誤碼可以視為一個(gè)錯(cuò)誤的引用,比如 404,它代表的就是找不到頁面的錯(cuò)誤,而它的錯(cuò)誤值可能為 Null Pointer Exception。
DECLARE command_not_allowed CONDITION FOR SQLSTATE '42000'; -- 錯(cuò)誤值 DECLARE command_not_allowed CONDITION FOR 1148; -- 錯(cuò)誤碼
定義處理程序語法:“declare handler_type handler for condition_name sp_statement;”
handler_type 的值有三種,其中 MySQL支持的有兩種: continue 是指遇到錯(cuò)誤忽略,繼續(xù)執(zhí)行下面的 SQL。exit 表示遇到錯(cuò)誤退出,默認(rèn)的策略就是 exit。(undo 表示遇到錯(cuò)誤后撤回之前的操作,MySQL 目前還不支持)
condition_name 可以是我們自己定義的條件,也可以是 MySQL 內(nèi)置的條件,比如 SQL WARNING。sp_statement 指遇到錯(cuò)誤的時(shí)候,需要執(zhí)行餓存儲(chǔ)過程或存儲(chǔ)函數(shù)。

DECLARE CONTINUE HANDLER FOR SQLSATTE '42S02' SET @info = 'NO_SUCH_TABLE'; -- 忽略錯(cuò)誤值為42S02的SQL異常 DECLARE EXIT HANDLER FOR SQLEXCEPTION SET @info = 'ERROR_OCCUR'; -- 捕獲SQL執(zhí)行異常并輸出信息 DECLARE no_such_table CONDITION FOR 1146; -- 為錯(cuò)誤碼為1146的錯(cuò)誤定義條件 DECLARE CONTINUE HANDLER FOR no_such_table SET @info = 'no_such_table'; -- 為指定的條件設(shè)置處理程序
DROP TABLE IF EXISTS t_student;
CREATE TABLE t_student
(
id INT(11) PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
age INT(11) NOT NULL
);

現(xiàn)在通過存儲(chǔ)過程,為這張表插入數(shù)據(jù)。因?yàn)?id 屬性有主鍵約束,所以不能插入相同的 id。
DROP PROCEDURE IF EXISTS insertStu;
DELIMITER // -- 定義存儲(chǔ)過程結(jié)束符號(hào)為//
CREATE PROCEDURE insertStu(OUT result INT) -- 指定輸出結(jié)果
BEGIN
DECLARE flag INT(11) DEFAULT 0; -- 指定變量為0
DECLARE primary_key_limit CONDITION FOR SQLSTATE '23000'; -- 主鍵約束的錯(cuò)誤值
DECLARE CONTINUE HANDLER FOR primary_key_limit SET @info = -1; -- 設(shè)計(jì)如果出現(xiàn)錯(cuò)誤,@info將會(huì)被設(shè)置為 -1
INSERT INTO t_student(id,name,age) VALUES(1,'dayu',22); -- 插入值,設(shè)置主鍵為1
SET flag = 1; -- 普通變量設(shè)值為1
SET result = flag; -- 如果下面的SQL執(zhí)行出現(xiàn)異常,那么就退出,只有上面的SQL生效。將普通變量的值給輸出
INSERT INTO t_student(id,name,age) VALUES(1,'dayu',22); -- 插入值,設(shè)置主鍵為1
SET flag = 2; -- 如果處理程序是EXIT,那么就不會(huì)執(zhí)行到這一步了
SET result = flag; -- 將普通變量的值給輸出
END // -- 結(jié)束符要加
DELIMITER ; -- 重新定義存儲(chǔ)過程結(jié)束符為分號(hào)
continue 是指遇到錯(cuò)誤忽略,繼續(xù)執(zhí)行下面的 SQL。因?yàn)槭?continue 來處理程序,所以遇到錯(cuò)誤后將會(huì)繼續(xù)執(zhí)行。
另外,第二次插入記錄,因?yàn)檫`反了主鍵約束,所以插入失敗,但是存儲(chǔ)過程仍然繼續(xù)執(zhí)行完畢。
CALL insertStu(@result); SELECT @result,@info; -- @info沒有申明就能調(diào)用到,可能是是全局變量吧
運(yùn)行結(jié)果:

再次查看 t_student 表,只插入了一條記錄,但是所有的存儲(chǔ)過程都執(zhí)行完畢了。

現(xiàn)在,重新執(zhí)行下面的 SQL。先重新建表,再將處理程序的處理策略換位 exit;在執(zhí)行存儲(chǔ)過程中遇到了錯(cuò)誤,那么就立即退出。
DROP TABLE IF EXISTS t_student;
CREATE TABLE t_student
(
id INT(11) PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
age INT(11) NOT NULL
);
DROP PROCEDURE IF EXISTS insertStu;
DELIMITER // -- 定義存儲(chǔ)過程結(jié)束符號(hào)為//
CREATE PROCEDURE insertStu(OUT result INT) -- 指定輸出結(jié)果
BEGIN
DECLARE flag INT(11) DEFAULT 0; -- 指定變量為0
DECLARE primary_key_limit CONDITION FOR SQLSTATE '23000'; -- 主鍵約束的錯(cuò)誤值
DECLARE EXIT HANDLER FOR primary_key_limit SET @info = -1; -- 使用EXIT策略,遇到SQL錯(cuò)誤將會(huì)結(jié)束這次存儲(chǔ)過程
-- 出現(xiàn)SQL錯(cuò)誤則直接退出存儲(chǔ)過程的執(zhí)行
INSERT INTO t_student(id,name,age) VALUES(1,'dayu',22); -- 插入值,設(shè)置主鍵為1
SET flag = 1; -- 普通變量設(shè)值為1
SET result = flag; -- 如果下面的SQL執(zhí)行出現(xiàn)異常,那么就退出,只有上面的SQL生效。將普通變量的值給輸出
INSERT INTO t_student(id,name,age) VALUES(1,'dayu',22); -- 插入值,設(shè)置主鍵為1
SET flag = 2; -- 如果處理程序是EXIT,那么就不會(huì)執(zhí)行到這一步了
SET result = flag; -- 將普通變量的值給輸出
END // -- 結(jié)束符要加
DELIMITER ; -- 重新定義存儲(chǔ)過程結(jié)束符為分號(hào)
CALL insertStu(@result);
SELECT @result,@info; -- @info沒有申明就能調(diào)用到,可能是是全局變量吧

@result 的結(jié)果為 1,說明執(zhí)行第二條 SQL 的時(shí)候,出現(xiàn)了異常。同樣,@info 的值為 -1,也提示處理?xiàng)l件中定義的存儲(chǔ)過程被觸發(fā)。
最后,數(shù)據(jù)庫表中的數(shù)據(jù)也是:

如果都是正確的 SQL,會(huì)是什么情況呢?
DROP TABLE IF EXISTS t_student;
CREATE TABLE t_student
(
id INT(11) PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
age INT(11) NOT NULL
);
DROP PROCEDURE IF EXISTS insertStu;
DELIMITER // -- 定義存儲(chǔ)過程結(jié)束符號(hào)為//
CREATE PROCEDURE insertStu(OUT result INT) -- 指定輸出結(jié)果
BEGIN
DECLARE flag INT(11) DEFAULT 0; -- 指定變量為0
DECLARE primary_key_limit CONDITION FOR SQLSTATE '23000'; -- 主鍵約束的錯(cuò)誤值
DECLARE EXIT HANDLER FOR primary_key_limit SET @info = -1; -- 設(shè)計(jì)如果出現(xiàn)錯(cuò)誤,@info將會(huì)被設(shè)置為 -1
INSERT INTO t_student(id,name,age) VALUES(NULL,'dayu',22); --
SET flag = 1; -- 普通變量設(shè)值為1
SET result = flag; -- 如果下面的SQL執(zhí)行出現(xiàn)異常,那么就退出,只有上面的SQL生效。將普通變量的值給輸出
INSERT INTO t_student(id,name,age) VALUES(NULL,'dayu',22); --
SET flag = 2; -- 如果處理程序是EXIT,那么就不會(huì)執(zhí)行到這一步了
SET result = flag; -- 將普通變量的值給輸出
END // -- 結(jié)束符要加
DELIMITER ; -- 重新定義存儲(chǔ)過程結(jié)束符為分號(hào)
CALL insertStu(@result);
SELECT @result,@info; -- @info沒有申明就能調(diào)用到,可能是是全局變量吧


6、流程控制的使用
(1)if 語句的使用
DROP PROCEDURE IF EXISTS testIf;
DELIMITER //
CREATE PROCEDURE testIf(OUT result VARCHAR(255))
BEGIN
DECLARE val VARCHAR(255);
SET val = 'a';
IF val IS NULL
THEN SET result = 'IS NULL';
ELSE SET result = 'IS NOT NULL';
END IF;
END //
DELIMITER ;
CALL testIf(@result);
SELECT @result;

(2)case 語句
DROP PROCEDURE IF EXISTS testCase;
DELIMITER //
CREATE PROCEDURE testCase(OUT result VARCHAR(255))
BEGIN
DECLARE val VARCHAR(255);
SET val = 'a';
CASE val IS NULL
WHEN 1 THEN SET result = 'val is true';
WHEN 0 THEN SET result = 'val is false';
ELSE SELECT 'else';
END CASE;
END //
DELIMITER ;
CALL testCase(@result);
SELECT @result;

(3)loop
loop 用于重復(fù)執(zhí)行 SQL。leave 用于退出循環(huán)。
DROP PROCEDURE IF EXISTS testLoop;
DELIMITER //
CREATE PROCEDURE testLoop(OUT result VARCHAR(255))
BEGIN
DECLARE id INT DEFAULT 0;
add_loop:LOOP
SET id = id + 1;
IF id>10 THEN LEAVE add_loop; -- 可在此處修改成批量插入
END IF;
SET result = id;
END LOOP add_loop;
END //
DELIMITER ;
CALL testLoop(@result);
SELECT @result;

下面是一個(gè)批量插入的例子:
DROP TABLE IF EXISTS t_student;
CREATE TABLE t_student
(
id INT(11) PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255) NOT NULL,
age INT(11) NOT NULL
);
DROP PROCEDURE IF EXISTS testLoop;
DELIMITER //
CREATE PROCEDURE testLoop(IN columnCount INT(11))
BEGIN
DECLARE id INT DEFAULT 0;
add_loop:LOOP
SET id = id + 1;
IF id>columnCount THEN LEAVE add_loop;
END IF;
INSERT INTO t_student(id,name,age) VALUES(id,'dayu',22);
END LOOP add_loop;
END //
DELIMITER ;
CALL testLoop(15);

(4)while
DROP PROCEDURE IF EXISTS testWhile;
DELIMITER //
CREATE PROCEDURE testWhile(IN myCount INT(11),OUT result INT(11))
BEGIN
DECLARE i INT DEFAULT 0 ; -- 定義變量
WHILE i < myCount DO -- 符合條件就循環(huán)
-- 核心循環(huán)SQL;
SET i = i + 1 ; -- 計(jì)數(shù)器+1
END WHILE; -- 當(dāng)不滿足條件,結(jié)束循環(huán) --分號(hào)一定要加!
SET result = i; -- 將變量賦值到輸出
END //
CALL testWhile(10,@result); SELECT @result AS 循環(huán)次數(shù);

7、使用 “show status” 查看存儲(chǔ)過程或函數(shù)的狀態(tài)
SHOW PROCEDURE STATUS LIKE 'C%';

SHOW FUNCTION STATUS LIKE 'C%';

知道了存儲(chǔ)過程,如果希望查看具體的存儲(chǔ)過程或者存儲(chǔ)函數(shù)的定義:
SHOW CREATE PROCEDURE study.CountStu; -- Create Procedure 列為核心語句 CREATE DEFINER=`root`@`localhost` PROCEDURE `CountStu`(IN stu_sex CHAR,OUT num INT) BEGIN SELECT COUNT(*) INTO num FROM t_student WHERE sex = stu_sex; END

提示:帶上數(shù)據(jù)庫的名字,小心查詢不到。
查看存儲(chǔ)函數(shù)有哪些:
SHOW FUNCTION STATUS LIKE 'C%'

查看具體的存儲(chǔ)函數(shù)創(chuàng)建語句:
SHOW CREATE FUNCTION study.countStu2 -- Create Function 列的語句 CREATE DEFINER=`root`@`localhost` FUNCTION `countStu2`(stu_sex CHAR) RETURNS int(11) RETURN (SELECT COUNT(*) FROM t_student WHERE sex = stu_sex)

8、從 information_schema.Routines 表中查詢存儲(chǔ)過程與函數(shù)
原來,MySQL 中的存儲(chǔ)過程與存儲(chǔ)函數(shù)都存放在 information_schema 數(shù)據(jù)庫下的 Routines 表中。
SELECT * FROM information_schema.ROUTINES WHERE ROUTINE_NAME LIKE 'C%'

如果什么時(shí)候忘記了存儲(chǔ)函數(shù)或者存儲(chǔ)過程的名字,可以查詢這張表的數(shù)據(jù)。然后確定了是某個(gè)存儲(chǔ)過程或者是存儲(chǔ)函數(shù),就可以使用 “show create procedure/function 數(shù)據(jù)庫.sp_name” 查看指定的創(chuàng)建語句了。
9、修改存儲(chǔ)過程
語法:“alter procedure | function sp_name [存儲(chǔ)特性]”
修改存儲(chǔ)過程,將讀寫權(quán)限改為 MODIFIES SQL DATE 并指明調(diào)用者 ALTER PROCEDURE countStu2 MODIFIES SQL DATE -- 表示子程序中包含寫數(shù)據(jù)的語句 SQL SECURITY INVOKER -- 表示調(diào)用者才能執(zhí)行

存儲(chǔ)過程與存儲(chǔ)函數(shù)的補(bǔ)充
1、存儲(chǔ)過程如何修改代碼?
雖然提供了 “alter procedure sp_name [存儲(chǔ)特性]”,但是只能修改存儲(chǔ)過程的存儲(chǔ)特性,不能修改 SQL。需要?jiǎng)h除并重新創(chuàng)建。
2、存儲(chǔ)過程中能調(diào)用其它存儲(chǔ)過程嗎?
可以在存儲(chǔ)過程中的 SQL 中通過 CALL 調(diào)用其它存儲(chǔ)過程,但是不能用 drop 刪除其它存儲(chǔ)過程。
3、存儲(chǔ)過程中的 in 參數(shù)可能是中文怎么辦?
在定義存儲(chǔ)過程的時(shí)候,加上 “character set gbk”
DELIMITER //
CREATE PROCEDURE getAddressByName(IN u_name VARCHAR(50) character set gbk , OUT address VARCHAR(50))
BEGIN
SQL;
END//
DELIMITER ;
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
MySql 存儲(chǔ)引擎和索引相關(guān)知識(shí)總結(jié)
這篇文章主要介紹了MySql 存儲(chǔ)引擎和索引相關(guān)知識(shí)總結(jié),文中講解非常細(xì)致,代碼幫助大家更好的理解和學(xué)習(xí),感興趣的朋友可以了解下2020-06-06
MySQL快速復(fù)制一張表的四種核心方法(包括表結(jié)構(gòu)和數(shù)據(jù))
本文詳細(xì)介紹了四種復(fù)制MySQL表(結(jié)構(gòu)+數(shù)據(jù))的方法,并對(duì)每種方法進(jìn)行了對(duì)比分析,適用于不同場景和數(shù)據(jù)量的復(fù)制需求,特別是針對(duì)超大表(1億+行)和跨實(shí)例復(fù)制提供了具體的操作命令和注意事項(xiàng),感興趣的朋友跟隨小編一起看看吧2025-12-12
windows下如何解決mysql secure_file_priv null問題
這篇文章主要介紹了windows下如何解決mysql secure_file_priv null問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
Mysql啟動(dòng)報(bào)ERROR:2002的分析與解決
這篇文章主要給大家介紹了關(guān)于Mysql啟動(dòng)時(shí)報(bào)ERROR:2002問題的分析與解決方法,文中通過示例代碼介紹將該問題分析的非常詳細(xì),對(duì)同樣遇到這個(gè)問題的朋友們具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧。2017-08-08

