mysql數據庫存儲過程及調用方法
?
mysql5.0以后就支持存儲過程了,目前mysql的6.0Alpha版也已經推出。6.0不僅支持大型數據庫如oracle等的絕大部分功 能,如存儲過程、視圖、觸發器、job等等,而且修正了這些功能所存在的bug,其中6.0.1還支持64位windows,以及表空間。
在c/c++中訪問mysql,常見的只是一些簡單的業務,使用c中嵌入簡單的查詢、 插入、更新等操作即可。隨著業務的復雜化,完成一個業務功能需要非常多的sql操作環節,把這些語句都嵌入c代碼中會導致c代碼越來越繁瑣、不清晰,這時 候,自然就想到了存儲過程來封裝所有的數據庫邏輯,通過c簡單調用mysql存儲過程接口即可達到目的,極大地減輕了c程序員的工作量,也便于前端業務處 理邏輯與數據庫處理邏輯的分離。下面就介紹c語言調用存儲過程的簡單的方法。
1、首先創建一張表
用于存放用戶信息
Create table student(
????? id int auto_increment,
????? name varchar(20),
????? age tinyint,
????? remark varchar(50),
????? ?primary key(id)
);
2、插入幾條信息
Insert into student values(1,"zhouys",90, "");
commit;
3、查看用戶信息
mysql> select * from student;
+------+-----------+------+----------+
| id?? | name?? | age?| remark |
+------+-----------+------+----------+
|??? 1 | zhouys |?? 90 |??????? |
+------+-----------+------+-----------+
1 row in set (0.00 sec)
mysql>
4、創建存儲過程
如下:
delimiter //
create procedure querystudent(
?????? in in_id int ,?? #0-?字符id 1-數字id????
?????? #
?????? out out_ret int,??????????????? #?返回結果
?????? out out_name varchar(20),??????? #?名字
?????? out out_age ??int????????? #?年齡????
)
label_a:begin
?????? declare v_name varchar(20) ;
?????? declare v_age tinyint ;
?????? #?參數判斷
?????? if (in_id<=0) then
set out_ret=-1; #id error
leave label_a;
?????? end if;
?????? SELECT name,age into v_name,v_age from student where id=in_id limit 1;
?????? if v_age is NULL then
set out_ret=-2; #don't found
leave label_a;
?????? end if;????
?????? set out_ret=0;
?????? set out_name=v_name;
?????? set out_age=v_age;
end;
//
delimiter ;
5、c語言調用存儲過程
調用方法或步驟:
5.1?、初始化?Mysql?句柄
if(!mysql_init(&mysql))
?????? {
printf("mysql_init failed!/n");
?????? ?????? return 0;
?????? }
5.2?、連接到?mysql
//login or connect
?????? if(!mysql_real_connect(&mysql,"localhost","root","","billingdb",0,NULL,CLIENT_MULTI_STATEMENTS))
?????? {
printf("mysql_real_connect() failed!/n");
mysql_close(&mysql);
return 0;
?????? }
5.3?、調用存儲過程
?????? //call
?????? strcpy(query,"call querystudent (1,@ret,@out_name,@out_age)");
?????? printf("query sql=[%s]/n",query);
??? ret= mysql_real_query(&mysql,query,(unsigned int)strlen(query));
5.4?、查詢結果集并保存
mysql_query(&mysql, "SELECT @ret,@ out_name,@ out_age ");
?????? //get result
?????? if (ret)
??? {
printf("Error exec query: %s/n",mysql_error(&mysql));
??? }
??? else
?????? {
printf("[%s] exec.../n", query);
??? }
?????? results = mysql_store_result(&mysql);
5.5?、獲取查詢結果
while((record = mysql_fetch_row(results))) {
printf("[%s]-[%s]-[%s]/n", record[0], record[1],record[2]);
?????? }
一般存儲過程只會有一行的返回結果,^_^.
5.6?、釋放資源與?mysql?連接句柄
mysql_free_result(results);
mysql_close(&mysql);
6、結束語
?????? Mysql?存儲過程可以實現相當強大的功能,這里只是拋磚引玉的做一些實踐,期望能夠給大家一些幫助。也歡迎大家交流…
----------------------------------------------------------------------------------------------------------------------------
Mysql?存儲例程的使用
??? 一、?簡介
??? 存儲過程(Stored Procedure)是一組為了完成特定功能的SQL語句集,經編譯后存儲在數據庫中。用戶通過指定存儲過程的名字并給出參數(如果該存儲過程帶有參數)來執行它。存儲過程是數據庫中的一個重要對象,任何一個設計良好的數據庫應用程序都應該用到存儲過程。
????雖然常用術語是存儲過程(stored procedure),但MySQL實際上實現了兩中類型,除了存儲過程外,還有存儲函數(stored routine),它們統稱為存儲例程。
???? 二、基本格式
1、存儲過程
??CREATE PROCEDURE?過程名?([過程參數[,...]])
??[特性?...]?過程體
如創建: CEATE PROCEDURE p1 (a INT)
SELECT a;
調用一下:CALL p1(8);??
將顯示:
+------+
| a????|
+------+
|????8 |
+------+
1 row in set (0.00 sec)
2、存儲函數
??CREATE FUNCTION?函數名?([函數參數[,...]])
??RETURNS?返回類型
??[特性?...]?函數體
如創建:CREATE FUNCTION f1 (x INT)
RETURNS INT
RETURN x;???????/*?過程函數一次只能返回一個值
調用一下:SELECT f1 (3);
將顯示:
+-------+
| f1(3) |
+-------+
|?????3 |
+-------+
1 row in set (0.00 sec)
3、過程參數
??[ IN | OUT | INOUT ]?參數名 參數類型
4、函數參數
??參數名 參數類型
5、返回類型
??有效的MySQL數據類型即可
6、過程體/函數體格式如下
BEGIN
有效的SQL語句
END
7、特性(一般不要求)
LANGUAGE SQL
| [NOT] DETERMINISTIC
| { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }
| SQL SECURITY { DEFINER | INVOKER }
| COMMENT 'string'
8、存儲過程中參數的IN,OUT,INOUT類型
????存儲過程可以接受輸入參數,并把參數返回給調用方。不過,對于每個參數,需要聲明其參數名、數據類型,還要指定此參數是用于向過程傳遞信息,還是從過程傳回信息,或是二者兼有。
????為聲明參數的作用,使用如下3個關鍵字之一:
?IN :??IN參數只用來向過程傳遞信息,為默認值。
?OUT : OUT參數只用來從過程傳回信息。
?INOUT?:?INOUT參數可以向過程傳遞信息,如果值改變,則可再從過程外調用。
如果僅僅想把數據傳給?MySQL?存儲過程,那就使用“in”?類型參數;如果僅僅從?MySQL?存儲過程返回值,那就使用“out”?類型參數;如果需要把數據傳給?MySQL?存儲過程,還要經過一些計算后再傳回給我們,此時,要使用“inout”?類型參數。
對于任何聲明為OUT或INOUT的參數,,當調用存儲過程時需要在參數名前加上@符號,這樣該參數就可以在過程外調用了。
下面舉三個實例:
MySQL?存儲過程?“in”?參數:跟?C?語言的函數參數的值傳遞類似,?MySQL?存儲過程內部可能會修改此參數,但對?in?類型參數的修改,對調用者(caller)來說是不可見的(not visible)。
create?procedure?pr_param_in
(
???in?id?int?--?in?類型的?MySQL?存儲過程參數
)
begin
???if?(id?is?not?null)?then
??????set?id?=?id?+?1;
???end?if;
???select?id?as?id_inner;
end;
set?@id?=?10;
call?pr_param_in(@id);
select?@id?as?id_out;
mysql>?call?pr_param_in(@id);
+----------+
|?id_inner?|
+----------+
|???????11?|
+----------+
mysql>?select?@id?as?id_out;
+--------+
|?id_out?|
+--------+
|?10?????|
+--------+
可以看到:用戶變量?@id?傳入值為?10,執行存儲過程后,在過程內部值為:11(id_inner),但外部變量值依舊為:10(id_out)。
MySQL?存儲過程?“out”?參數:從存儲過程內部傳值給調用者。在存儲過程內部,該參數初始值為?null,無論調用者是否給存儲過程參數設置值。
create?procedure?pr_param_out
(
???out?id?int
)
begin
???select?id?as?id_inner_1;????/*?id?初始值為?null*/
???if?(id?is?not?null)?then
??????set?id?=?id?+?1;
??????select?id?as?id_inner_2;
???else
??????select?1?into?id;
???end?if;
???select?id?as?id_inner_3;
end;
set?@id?=?10;
call?pr_param_out(@id);
select?@id?as?id_out;
mysql>?set?@id?=?10;
mysql>
mysql>?call?pr_param_out(@id);????/*外部變量不能傳給存儲過程*/
+------------+
|?id_inner_1?|
+------------+
|???????NULL?|
+------------+
+------------+
|?id_inner_3?|
+------------+
|??????????1?|
+------------+
mysql>?select?@id?as?id_out;??/*過程將改變的值傳給外部變量*/
+--------+
|?id_out?|
+--------+
|?1??????|
+--------+
可以看出,雖然我們設置了用戶定義變量?@id?為?10,傳遞?@id?給存儲過程后,在存儲過程內部,id?的初始值總是?null(id_inner_1)。最后?id?值(id_out = 1)傳回給調用者。
MySQL?存儲過程?inout?參數跟?out?類似,都可以從存儲過程內部傳值給調用者。不同的是:調用者還可以通過inout?參數傳遞值給存儲過程。
drop?procedure?if?exists?pr_param_inout;
create?procedure?pr_param_inout
(
???inout?id?int
)
begin
???select?id?as?id_inner_1;??--?id?值為調用者傳進來的值
???if?(id?is?not?null)?then
??????set?id?=?id?+?1;
??????select?id?as?id_inner_2;
???else
??????select?1?into?id;
???end?if;
???select?id?as?id_inner_3;
end;
set?@id?=?10;
call?pr_param_inout(@id);
select?@id?as?id_out;
mysql>?set?@id?=?10;
mysql>
mysql>?call?pr_param_inout(@id);
+------------+
|?id_inner_1?|
+------------+
|?????????10?|
+------------+
+------------+
|?id_inner_2?|
+------------+
|?????????11?|
+------------+
+------------+
|?id_inner_3?|
+------------+
|?????????11?|
+------------+
mysql>
mysql>?select?@id?as?id_out;
+--------+
|?id_out?|
+--------+
|?11?????|
+--------+
從結果可以看出:我們把?@id(10),傳給存儲過程后,存儲過程最后又把計算結果值?11(id_inner_3)傳回給調用者。?MySQL?存儲過程?inout?參數的行為跟?C?語言函數中的引用傳值類似。
通過以上例子:如果僅僅想把數據傳給?MySQL?存儲過程,那就使用“in”?類型參數;如果僅僅從?MySQL?存儲過程返回值,那就使用 “out”?類型參數;如果需要把數據傳給?MySQL?存儲過程,還要經過一些計算后再傳回給我們,此時,要使用“inout”?類型參數。
9、聲明和設置變量
(1) 聲明變量
???在存儲例程使用局部變量之前,必須聲明局部變量,變量聲明通過DECLARE語句實現,其原型如下:
???DECLARE variable_name TYPE ;
如:DECLARE x VARCHAR(254);
???在聲明變量時,聲明必須放在BEGIN/END塊中。此外聲明必須在執行該塊任何其它語句之前進行。
(2) 設置變量
SET語句用來設置聲明的存儲例程變量值。其原型如下:
SET??variable_name =value;
如下聲明和設置變量過程:
??DECLARE??x??INT;
SET??x = 155;
也可使用SELECT…..INTO語句設置變量。
??如:
SELECT??155??INTO??x;
當然,此變量是聲明該變量的BEGIN/END塊作用范圍內的一個局部變量。如果希望在存儲例程外使用此變量,需要將其作為OUT變量傳遞。
10、執行存儲例程
????執行存儲例程一般是通過CALL和SELECT語句來完成的。
????三、多語句存儲例程
單語句存儲例程非常有用,但存儲例程的真正功能在于它能夠封裝和執行多個SQL語句。
下面介紹創建多語句存儲例程時常用的語法。
? 1、BEGIN和END
當創建多語句存儲例程時,需要將語句包圍在BEGIN/END塊中。
此塊的原型如下:
BEGIN
?????statement 1;
?????statement 2;
?????……
?????statement N;
END
注意,塊中每條語句必須以分號結尾。
?2、條件語句
?IF-ELSEIF-ELSE語句
?和C語言中if語句相似。
其原型如下:
IF condition1 THEN
statement1;
ELSEIF condition2 THEN
Statement2;
…….
END IF
?CASE語句
需要比較一組可能的值時CASE語句很有用。也是一種條件判斷語句。
其原型如下:
CASE
WHEN condition1 THEN statement1;
WHEN condition2 THEN statement2;
………
END CASE;
3、迭代
有些任務需要能夠重復地執行一組語句。下面介紹能夠迭代執行和退出循環的各種方法。
?ITERATE語句
執行ITERATE語句將使嵌入該語句的LOOP、REPEAT或WHILE循環返回頂部,并在此執行。
其原型如下:
ITERATE??label
?LEAVE語句
在得到變量的值或特定任務的結果后,可能希望通過LEAVE命令立即退出循環或BEGIN/END塊。
其原型如下:
LEAVE??label
?LOOP語句
LOOP語句將不斷的迭代處理定義在其代碼塊中的一組語句,直到遇到LEAVE為止。
其原型如下:
[begin_label:]??LOOP
???Statement_list
END LOOP??[end_label]
???????REPEAT語句
? ??? ?REPEAT語句在操作上幾乎與WHILE相同,很想C語言中的DO….WHERE語句。
??????其原型如下:
?REPEAT
???????Statement_list
?UNTIL condition
?END REPEAT
?WHILE語句
?其原型如下:
? WHILE condition DO
????Statement_list
????? ??END WHILE
下面寫一個循環語句的存儲過程:
DELIMITER $$
DROP PROCEDURE IF EXISTS `yyw`.`p2` $$
CREATE PROCEDURE `yyw`.`p2` ()
BEGIN
????????declare v int;
?set v=0;
?LOOP_LABLE:loop
??????????if v=3 then
??????set v=v+1;
??????ITERATE LOOP_LABLE;
???end if;
???insert into vs values(v);??????????/*將循環值插入數據表vs中*/
???set v=v+1;
???if v>=5 then
?????leave LOOP_LABLE;
???end if;
?end loop;
END $$
DELIMITER ;
??? 四、從另一個例程中調用例程
DELIMITER //
CREATE PROCEDURE??p1()
BEGIN
???Statement_list
END//
CREATE PROCEDURE??p2()
BEGIN
???Statement_list
END//
CREATE PROCEDURE??p3()
BEGIN
???CALL??p1();
???CALL??p2();
END//
注意:直接采用MySQL的Administrator管理器編輯時,可以直接采用函數文本錄入;
????但若在腳本中自動導入存儲過程或函數時,由于MySQL默認以";"為分隔符,則過程體的每一句都被MySQL以存儲過程編譯,則編譯過程會報錯;所以要事先用DELIMITER關鍵字申明當前段分隔符
用完了就把分隔符還原。 如下所示:
DELIMITER?$$
Stored Procedures and Functions
DELIMITER ;
??? 五、刪除和查看存儲例程
1、刪除存儲例程
要刪除存儲例程,可以執行DROP語句。
其原型如下:
?DROP??(PROCEDURE|FUNCTION)??P_name;
?? 2、查看例程狀態
其原型如下:
SHOW??(PROCEDURE|FUNCTION)??STATUS??LIKE??‘P_name’
如:
SHOW??PROCEDURE??STATUS??LIKE??‘P3’/G;
注意:?使用/G選項以垂直格式顯示輸出信息。
?? 3、查看例程的創建語法
???通過SHOW CREATE語句可以查看創建特定例程所用的語法。
?? 其原型如下;
????? SHOW CREATE??(PROCEDURE|FUNCTION)??Db_name.P_name
??? 六、實例
?? 一般在MySQL Query Browser中更方便的創建存儲過程及修改內容。
(1)簡單的加法運算
DELIMITER $$
DROP PROCEDURE IF EXISTS `yyw`.`p4` $$
CREATE DEFINER=`yang`@`10.10.19.161` PROCEDURE `p4`(a int,b int)
BEGIN
???declare c int;?????????????/*聲明的變量
if a is null then????????????/*IF語句??
??????set a = 0;
???end if;
if b is null then
??????set b = 0;
???end if;
set c = a + b;
select c as sum;??????????/*結果顯示c的值
END $$
DELIMITER ;
調用以下:CALL??p4(3,4);
將顯示:
+------+
| sum??|
+------+
|????7 |
+------+
1 row in set (0.00 sec)
(2)存儲過程中的循環語句、數據表數據的導入導出及SQL函數的使用
DELIMITER $$
DROP PROCEDURE IF EXISTS `yyw`.`p4` $$
CREATE DEFINER=`yang`@`10.10.19.161` PROCEDURE ‘pro_prime2’(in num int)
BEGIN
? declare i,j,x,y int default 0;????/*聲明變量并默認為0*/
????? select??yywID into j from text1;??/*從數據表txte1中字段yywID的值賦給變量j*/
????? select 'count ',j;???????????/*顯示count字符和j的值*/
????? while i<num do??????????/*while……do循環語句*/
???????? set x=2;
???????? pp1:while x<=sqrt(j) do????/*調用內部函數SQRT用于求平方*/
if j%x=0 then???????????????/*if循環語句*/
set y=1;
leave pp1;
else
set x=x+1;
end if;
???????? end while;
???????? if y=1 then
?????????? set y=0;
???????? else
?????????? set i=i+1;
?????????? insert into text2 values(j);????/*將j的值插入數據表text2*/
???????? end if;
?????????? set j=j+1;????????????/*實現j的自增*/
????? end while;
?END $$
DELIMITER ;
假如原先在數據庫中分別建立表text1和text2,text1中有一個字段初始值為3,text2為空;
下面執行一下此存儲過程:
mysql> CALL pro_prime2(5);
+--------+------+
| count??| j????|
+--------+------+
| count??|????3 |
+--------+------+
1 row in set (0.00 sec)
mysql> select *from text2;
+-------+
| yywID |
+-------+
|?????3 |
|?????5 |
|?????7 |
|????11 |
|????13 |
+-------+
5 rows in set (0.00 sec)
(3)用存儲過程實現計算數據庫中某個成績表總分及平均分,并且調用過程后
能夠自動顯示基本信息(如學號、姓名、總分、平均分等)。
????首先在數據庫中建一個成績表(命名為chengjibiao)如下:
+-----+------+--------+-------+--------+
| NUM | Name | Enlish | Maths | Physis |
+-----+------+--------+-------+--------+
|?? 1 |?楊業?| 92???? | 87??? | 96???? |
|?? 2 |?劍鋒 | 82???? | 98??? | 93???? |
|?? 3 |?張美 | 96???? | 86??? | 94???? |
|?? 4 |?張文 | 76???? | 99??? | 95???? |
|?? 5 |?葉倩 | 97???? | 86??? | 88???? |
|?? 6 |?方文 | 87???? | 96??? | 94???? |
|?? 7 |?李麗 | 97???? | 86??? | 83???? |
|?? 8 |?賈宇 | 67???? | 89??? | 77???? |
|?? 9 |?王勃 | 89???? | 67??? | 75???? |
|? 10 |?劉三 | 85???? | 78??? | 95???? |
+-----+------+--------+-------+--------+
??用SQL語句寫存儲過程p1?????
?????????????????DELIMITER $$
DROP PROCEDURE IF EXISTS `yyw`.`p1` $$
????????????????CREATE DEFINER=`yang`@`10.10.19.161` PROCEDURE `p1`(N int)
BEGIN
????????????????declare a int;??????????????????/*????變量的聲明???*/
declare b int;
declare c int;
declare d int;
declare e int;
????????????????declare f char(100);
declare g decimal(4,2);
set e=1;
create table zongping (NUM int,Name char(255),Enlish int,Maths int,Physis int,Total int,aver decimal(??????? 4,2));?????????????????????/*??建一個數據表以存放要顯示的內容*/
repeat?????????????????/*?引進一個REPEAT循環,來計算每位學生總分及平均分*/
select??Enlish,Maths,Physis,Name into a,b,c,f from chengjibiao where NUM=e;
/*?導出數據庫chengjibiao中的三門成績及姓名,并把它們分別賦給變量a,b,c,f;*/
set d=a+b+c;?????????/*求和*/
set g=(a+b+c)/3;??????/*求平均分*/
insert into zongping (NUM,Name,Enlish,Maths,Physis,Total,aver) values (e,f,a,b,c,d,g);
?????????????????/*將學號,姓名,三門成績,總分,平均分的數據插入新建的數據表zongping中
set e=e+1;???????/*該條件可結束循環*/
until e=N??????/*N是調用存儲過程時根據學生數目來設定的*/
end repeat;
?select *from zongping;???????????/*?以數據表的形式顯示運行結果*/
???????????????drop table zongping;??????????/*顯示結果后刪除表,也可不刪*/
END $$
DELIMITER ;
??l?調用存儲過程
CALL??P1 (11);??????????/*?因為原成績表中有10列數據?,故設N=11,也可根據不同的成績表另設
???????顯示結果如下:
???+------+------+--------+-------+--------+-------+
?| Name | Enlish | Maths | Physis | Total | Aver? |
+------+------+--------+-------+--------+-------+-------+
|??? 1 |?楊業?|???? 92 |??? 87 |???? 96 |?? 275 | 91.67 |
|??? 2 |?劍鋒 |???? 82 |??? 98 |???? 93 |?? 273 | 91.00 |
|??? 3 |?張美 |???? 96 |??? 86 |???? 94 |?? 276 | 92.00 |
|??? 4 |?姜文 |???? 76 |??? 99 |???? 95 |?? 270 | 90.00 |
|??? 5 | 葉倩?|???? 97 |??? 86 |???? 88 |?? 271 | 90.33 |
|??? 6 |?方文 |???? 87 |??? 96 |???? 94 |?? 277 | 92.33 |
|??? 7 |?李麗 |???? 97 |??? 86 |???? 83 |?? 266 | 88.67 |
|??? 8 |?賈宇 |???? 67 |??? 89 |???? 77 |?? 233 | 77.67 |
|??? 9 |?王勃 |???? 89 |??? 67 |???? 75 |?? 231 | 77.00 |
|?? 10 |?劉三 |???? 85 |??? 78 |???? 95 |?? 258 | 86.00 |
+------+------+--------+-------+--------+-------+-------+
------------------------------------------------------------------------------------------------------------------------------------------
1.?數據庫名:test?;
??表名:chengjibiao;
??字段:Id? int , Name char , English int , Maths int , Physis int ;?
2.?存儲過程:
DELIMITER $$
DROP PROCEDURE IF EXISTS `test`.`query` $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `query`( in N int, out s char(254) )
BEGIN
? declare a,b,c,d,e int;
? declare f char(100);
? declare g decimal(4,2);
? set e=1;
? drop table if exists zongping;
? create table zongping(NUM int,Name char(255),English int,Maths int,Physis int,Total int,aver decimal(4,2));
? repeat
? select English,Maths,Physis,Name into a,b,c,f from chengjibiao where Id=e;
? set d=a+b+c;
? set g=(a+b+c)/3;
? insert into zongping(NUM,Name,English,Maths,Physis,Total,aver) values( e,f,a,b,c,d,g );
? set e=e+1;
? until e=N
? end repeat;
? select *from zongping as s;
? drop table zongping;
END $$
DELIMITER ;?
3.?主函數(在文件main.c?中):
#include "stdio.h" #include "stdlib.h" #include "string.h" #include "/usr/include/mysql/mysql.h" #include "/usr/include/mysql/mysql_version.h" #include "/usr/include/mysql/errmsg.h"
int main( int argc,char **argv[] ) { MYSQL mysql; MYSQL_ROW results,record; char query[50],s[254]; /** 鏈接數據庫 **/ if(!mysql_init(&mysql)) { printf("mysql_init failed!/n"); return 0; } if(!mysql_real_connect(&mysql,"localhost","root","123456","test",0,NULL,CLIENT_MULTI_STATEMENTS)) { printf("mysql_real_connect() failed!/n"); mysql_close(&mysql); return 0; }
/** 調用存儲過程 **/ strcpy(query,"call query(7,@s)"); mysql_real_query(&mysql,query,(unsigned int)strlen(query)); /** 取得存儲過程返回值 **/ mysql_query(&mysql, "SELECT @s "); results = mysql_store_result(&mysql);
/** 輸出返回值 **/ printf( "Id Name Maths English Physis Total aver/n" ); while((record = mysql_fetch_row(results))) { printf("%1s%10s%8s%12s%11s%10s%10s/n", record[0], record[1],record[2],record[3],record[4],record[5],record[6]); } mysql_free_result(results); mysql_close(&mysql); return 0; }
(編譯:gcc -o main main.c -L/usr/lib/mysql/ -lmysqlclient -lz?)
?
4.
成績表:
+----+-------+-------+---------+--------+
| Id | Name??| Maths | English | Physis |
+----+-------+-------+---------+--------+
|??1 | liu????|????90 |??????80 |?????86 |
|??2 | zhang |????88 |??????86 |?????87 |
|??3 | xiao??|????78 |??????88 |?????98 |
|??4 | wang??|????77 |??????87 |?????97 |
|??5 | li????|????79 |??????89 |?????99 |
|??6 | yi????|????67 |??????77 |?????87 |
運行程序得到的結果:
Id????Name???Maths???English???Physis??Total??????aver
??1????liu?????90??????????80?????86?????256?????85.33
??2??zhang?????88??????????86?????87?????261?????87.00
??3???xiao?????78??????????88?????98?????264?????88.00
??4???wang?????77??????????87?????97?????261?????87.00
??5?????li?????79??????????89?????99?????267?????89.00
??6?????yi?????67??????????77?????87?????231?????77.00
------------------------------------------------------------------------------------------------------------------------------------------------------------------------- #include "stdio.h" #include "stdlib.h" #include "string.h" #include "/usr/include/mysql/mysql.h" #include "/usr/include/mysql/mysql_version.h" #include "/usr/include/mysql/errmsg.h" int main( int argc,char **argv[] ) { MYSQL my_connection; MYSQL_RES *results; MYSQL_ROW record; MYSQL_FIELD *field; int row, column,i,j; /** 鏈接數據庫 **/ if(!mysql_init(&my_connection)) { printf("mysql_init failed!/n"); return 0; } if(!mysql_real_connect(&my_connection,"localhost","root","123456","yyw",0,NULL,CLIENT_MULTI_STATEMENTS)) { printf("mysql_real_connect() failed!/n"); mysql_close(&my_connection); return 0; }
/*這句話是設置查詢編碼為utf8,這樣支持中文*/ mysql_query(&my_connection, "set names utf8"); /** 調用存儲過程p1**/ mysql_real_query(&my_connection, "call p1(11)", (unsigned int)strlen("call p1(11)")); /** 取得存儲過程返回值 **/ results = mysql_store_result(&my_connection); if (results) { /*取得結果的行數和*/ column = mysql_num_fields(results); row = mysql_num_rows(results) + 1; printf("查詢到 %lu 行/n", row); /*輸出結果的字段名*/ for (i = 0; field = mysql_fetch_field(results); i++) printf("%s/t", field->name); printf("/n"); /*按行輸出結果*/ for (i = 1; i < row; i++) { record = mysql_fetch_row(results); for (j = 0; j < column; j++) printf("%s/t", record[j]); printf("/n"); } } mysql_free_result(results); mysql_close(&my_connection); return 0; }
編輯一下:
[root@localhost home]# gcc -o?test test.c -L/usr/lib/mysql/ -lmysqlclient -lz
執行:
[root@localhost home]# ./test
顯示:
?
查詢到 10 行
NUM???? Name??? Enlish? Maths?? Physis? Total?? Aver
1?????? 楊業??? 92????? 87????? 96????? 275???? 91.67
2?????? 劍鋒??? 82????? 98????? 93????? 273???? 91.00
3?????? 張美??? 96????? 86????? 94????? 276???? 92.00
4?????? 張文??? 76????? 99????? 95????? 270???? 90.00
5?????? 葉倩??? 97????? 86????? 88????? 271???? 90.33
6?????? 方文??? 87????? 96????? 94????? 277???? 92.33
7?????? 李麗??? 97????? 86????? 83????? 266???? 88.67
8?????? 賈宇??? 67????? 89????? 77????? 233???? 77.67
9?????? 王勃??? 89????? 67????? 75????? 231???? 77.00
10????? 劉三??? 85????? 78????? 95????? 258???? 86.00