版權(quán)聲明:本文為CSDN博主「zhouxinfeng」的原創(chuàng)文章,原文鏈接:https://blog.csdn.net/zhouxinfeng/article/details/77891771
MySQL - C語言接口-預(yù)處理語句
對于多次執(zhí)行的語句,預(yù)處理執(zhí)行比直接執(zhí)行快,主要原因在于,僅對查詢執(zhí)行一次解析操作。在直接執(zhí)行的情況下,每次執(zhí)行語句時(shí),均將進(jìn)行查詢。此外,由于每次執(zhí)行預(yù)處理語句時(shí)僅需發(fā)送參數(shù)的數(shù)據(jù),從而減少了網(wǎng)絡(luò)通信量
A: select * from tablename
B: select * from tablename
服務(wù)器一般處理方式:
A--->S--->A B--->S--->B
服務(wù)器采取預(yù)處理機(jī)制
A--->S--->A S--->B 減少一次解釋執(zhí)行
A:select * from tablename where id=?
B:select * from tablename where name=?
預(yù)處理機(jī)制特點(diǎn):
-
減少服務(wù)器負(fù)荷
-
提高服務(wù)器響應(yīng)的速度
-
可以提供參數(shù)機(jī)制,讓客戶有更多查詢方法
預(yù)處理機(jī)制數(shù)據(jù)類型
- MYSQL_STMT 該結(jié)構(gòu)表示預(yù)處理語句
- MYSQL_BIND 該結(jié)構(gòu)用于語句輸入(發(fā)送給服務(wù)器的數(shù)據(jù)值)和輸出(從服務(wù)器返回的結(jié)果值)
- 從客戶傳送數(shù)據(jù)到服務(wù)器
- 從服務(wù)器傳輸數(shù)據(jù)到客戶
函數(shù):
-
MYSQL_STMT *mysql_stmt_init(MYSQL *mysql)
創(chuàng)建MYSQL_STMT句柄。對于該句柄,應(yīng)使用mysql_stmt_close(MYSQL_STMT *)釋放 -
int mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned long length)
給定mysql_stmt_init()返回的語句句柄,準(zhǔn)備字符串查詢指向的SQL語句,并返回狀態(tài)值。字符串長度應(yīng)由“l(fā)ength”參量給出 -
my_bool mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bind)
用于為SQL語句中的參數(shù)標(biāo)記符綁定數(shù)據(jù) -
my_bool mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
mysql_stmt_bind_result()用于將結(jié)果集中的列與數(shù)據(jù)緩沖和長度緩沖關(guān)聯(lián)(綁定)起來 -
int mysql_stmt_execute(MYSQL_STMT *stmt)
mysql_stmt_execute()執(zhí)行與語句句柄相關(guān)的預(yù)處理查詢 -
int mysql_stmt_store_result(MYSQL_STMT *stmt)
以便后續(xù)的mysql_stmt_fetch()調(diào)用能返回緩沖數(shù)據(jù) -
int mysql_stmt_fetch(MYSQL_STMT *stmt)
mysql_stmt_fetch()返回結(jié)果集中的下一行 -
my_bool mysql_stmt_close(MYSQL_STMT *)
關(guān)閉預(yù)處理語句
預(yù)處理機(jī)制步驟:
-
MYSQL_STMT * st;
-
對處理的數(shù)據(jù)類型初始化 MYSQL_STMT * mysql_stmt_init(MYSQL*) st=mysql_stmt_init(MYSQL*);
-
將預(yù)處理句柄與具體sql語句綁定 int mysql_stmt_prepare(MYSQL_STMT * st,char * sql,int length);
mysql_stmt_prepare(st,sql,strlen(str));
-
mysql語句的參數(shù)
select * from tablename where id=? and name=?
給參數(shù)賦值
MYSQL_BIND para[n] //1.n根據(jù)語句中參數(shù)確定(客戶-->服務(wù)) 2.n根據(jù)語句中的字段數(shù)確定(服務(wù)-->客戶)
memset(para,0,sizeof(para));
對參數(shù)操作
para[0].buffer_type=MYSQL_TYPE_LONG //設(shè)置參數(shù)的數(shù)據(jù)類型
int id;
para[0].buffer=&id; //參數(shù)傳值
para[1].buffer_type=MYSQL_TYPE_STRING
char str[20];
para[1].buffer_length=sizeof(str);
para[1].buffer=str;
-
預(yù)處理與參數(shù)綁定 mysql_stmt_bind_param(st,para);
-
執(zhí)行 mysql_stmt_execute(st);
-
釋放預(yù)處理機(jī)制所占的空間 mysql_stmt_close(MYSQL_STMT *) mysql_stmt_close(st);
示例1: 預(yù)處理語句 插入
/*
* 客戶端到服務(wù)端
*/
#include <stdio.h>
#include <mysql.h>
#include <string.h>
int main(void)
{
MYSQL *conn = mysql_init(NULL); //初始化服務(wù)器句柄
/*登陸服務(wù)器*/
if(!mysql_real_connect(conn, "localhost", "root", "", "test", 0, NULL, 0))
{
fprintf(stderr, "mysql_real_connect: %s\n", mysql_error(conn));
return -1;
}
MYSQL_STMT *stmt = mysql_stmt_init(conn); //創(chuàng)建MYSQL_STMT句柄
char *query = "insert into stu values(?, ?);"; // ?問號(hào)為占位符,表示一個(gè)參數(shù);
if(mysql_stmt_prepare(stmt, query, strlen(query))) // stmt 綁定 SQL語句
{
fprintf(stderr, "mysql_stmt_prepare: %s\n", mysql_error(conn));
return -1;
}
int id; char name[20];
printf("id name: ");
scanf("%d %s", &id, name);
MYSQL_BIND params[2]; // 參數(shù)數(shù)組
memset(params, 0, sizeof(params));
params[0].buffer_type = MYSQL_TYPE_LONG; // 參數(shù)數(shù)組設(shè)定類型和內(nèi)容
params[0].buffer = &id; // 注意:int類型變量 需要用&符號(hào),即,buff只接收指針類型
params[1].buffer_type = MYSQL_TYPE_STRING;
params[1].buffer = name; // name已經(jīng)是指針了
params[1].buffer_length = strlen(name); // 如果是字符串還需要明確長度
mysql_stmt_bind_param(stmt, params); // stmt 與參數(shù)數(shù)組的綁定
mysql_stmt_execute(stmt); // 執(zhí)行與語句句柄相關(guān)的預(yù)處理
mysql_stmt_close(stmt); // 關(guān)閉 預(yù)處理
mysql_close(conn); // 關(guān)閉連接
return 0;
}
示例2: 預(yù)處理語句讀取
/*
* 服務(wù)端到客戶端
*/
#include <stdio.h>
#include <mysql.h>
#include <string.h>
int main(void)
{
MYSQL *conn = mysql_init(NULL); //初始化服務(wù)器句柄
/*登陸服務(wù)器*/
if(!mysql_real_connect(conn, "localhost", "root", "", "test", 0, NULL, 0))
{
fprintf(stderr, "mysql_real_connect: %s\n", mysql_error(conn));
return -1;
}
MYSQL_STMT *stmt = mysql_stmt_init(conn); //創(chuàng)建MYSQL_STMT句柄 預(yù)處理對象
char *query = "select * from stu;";
if(mysql_stmt_prepare(stmt, query, strlen(query))) // 無參數(shù)的預(yù)處理
{
fprintf(stderr, "mysql_stmt_prepare: %s\n", mysql_error(conn));
return -1;
}
int id; char name[20];
//printf("id name: ");
//scanf("%d %s", &id, name);
MYSQL_BIND params[2]; // 讀出內(nèi)容為2個(gè)
memset(params, 0, sizeof(params));
params[0].buffer_type = MYSQL_TYPE_LONG;
params[0].buffer = &id;
params[1].buffer_type = MYSQL_TYPE_STRING;
params[1].buffer = name;
params[1].buffer_length = sizeof(name);
//mysql_stmt_bind_param(stmt, params);
mysql_stmt_bind_result(stmt, params); //用于將結(jié)果集中的列與數(shù)據(jù)緩沖和長度緩沖關(guān)聯(lián)(綁定)起來
mysql_stmt_execute(stmt); //執(zhí)行與語句句柄相關(guān)的預(yù)處理
mysql_stmt_store_result(stmt); //以便后續(xù)的mysql_stmt_fetch()調(diào)用能返回緩沖數(shù)據(jù)
while(mysql_stmt_fetch(stmt) == 0) //返回結(jié)果集中的下一行
printf("%d\t%s\n", id, name);
mysql_stmt_close(stmt);
mysql_close(conn);
return 0;
}
示例3:
/*
* 客戶端到服務(wù)端,再到客戶端
*/
#include <stdio.h>
#include <mysql.h>
#include <string.h>
int main(void)
{
MYSQL *conn = mysql_init(NULL); //初始化服務(wù)器句柄
/*登陸服務(wù)器*/
if(!mysql_real_connect(conn, "localhost", "root", "", "test", 0, NULL, 0))
{
fprintf(stderr, "mysql_real_connect: %s\n", mysql_error(conn));
return -1;
}
MYSQL_STMT *stmt = mysql_stmt_init(conn); //創(chuàng)建MYSQL_STMT句柄
char *query = "select * from stu where id=?;";
if(mysql_stmt_prepare(stmt, query, strlen(query)))
{
fprintf(stderr, "mysql_stmt_prepare: %s\n", mysql_error(conn));
return -1;
}
int id; char name[20];
printf("id: ");
scanf("%d",&id);
MYSQL_BIND params[2];
memset(params, 0, sizeof(params));
params[0].buffer_type = MYSQL_TYPE_LONG;
params[0].buffer = &id;
params[1].buffer_type = MYSQL_TYPE_STRING;
params[1].buffer = name;
params[1].buffer_length = sizeof(name);
mysql_stmt_bind_param(stmt, params); // 綁定查詢參數(shù)
mysql_stmt_bind_result(stmt, params); // 綁定查詢結(jié)果;用于將結(jié)果集中的列與數(shù)據(jù)緩沖和長度緩沖關(guān)聯(lián)(綁定)起來
mysql_stmt_execute(stmt); //執(zhí)行與語句句柄相關(guān)的預(yù)處理
mysql_stmt_store_result(stmt); //以便后續(xù)的mysql_stmt_fetch()調(diào)用能返回緩沖數(shù)據(jù)
while(mysql_stmt_fetch(stmt) == 0) //返回結(jié)果集中的下一行
printf("%d\t%s\n", id, name);
mysql_stmt_close(stmt);
mysql_close(conn);
return 0;
}
mysql stmt語法_mysql中SQL執(zhí)行過程詳解與用于預(yù)處理語句的SQL語法
mysql中SQL執(zhí)行過程詳解
客戶端發(fā)送一條查詢給服務(wù)器;
服務(wù)器先檢查查詢緩存,如果命中了緩存,則立刻返回存儲(chǔ)在緩存中的結(jié)果。否則進(jìn)入下一階段。
服務(wù)器段進(jìn)行SQL解析、預(yù)處理,在優(yōu)化器生成對應(yīng)的執(zhí)行計(jì)劃;
mysql根據(jù)優(yōu)化器生成的執(zhí)行計(jì)劃,調(diào)用存儲(chǔ)引擎的API來執(zhí)行查詢。
用于預(yù)處理語句的SQL語法
MySQL 5.1對服務(wù)器一方的預(yù)制語句提供支持。如果您使用合適的客戶端編程界面,則這種支持可以發(fā)揮在MySQL 4.1中實(shí)施的高效客戶端/服務(wù)器二進(jìn)制協(xié)議的優(yōu)勢。候選界面包括MySQL C API客戶端庫(用于C程序)、MySQL Connector/J(用于Java程序)和MySQL Connector/NET。例如,C API可以提供一套能組成預(yù)制語句API的函數(shù)調(diào)用。請參見25.2.4節(jié),“C API預(yù)處理語句”。其它語言界面可以對使用了二進(jìn)制協(xié)議(通過在C客戶端庫中鏈接)的預(yù)制語句提供支持。有一個(gè)例子是PHP 5.0中的mysqli擴(kuò)展。
對預(yù)制語句,還有一個(gè)SQL界面可以利用。與在整個(gè)預(yù)制語句API中使用二進(jìn)制協(xié)議相比,本界面效率沒有那么高,但是它不要求編程,因?yàn)樵赟QL層級(jí),可以直接利用本界面:
· 當(dāng)您無法利用編程界面時(shí),您可以使用本界面。
· 有些程序允許您發(fā)送SQL語句到將被執(zhí)行的服務(wù)器中,比如mysql客戶端程序。您可以從這些程序中使用本界面。
· 即使客戶端正在使用舊版本的客戶端庫,您也可以使用本界面。唯一的要求是,您能夠連接到一個(gè)支持預(yù)制語句SQL語法的服務(wù)器上。
預(yù)制語句的SQL語法在以下情況下使用:
· 在編代碼前,您想要測試預(yù)制語句在您的應(yīng)用程序中運(yùn)行得如何?;蛘咭苍S一個(gè)應(yīng)用程序在執(zhí)行預(yù)制語句時(shí)有問題,您想要確定問題是什么。
· 您想要?jiǎng)?chuàng)建一個(gè)測試案例,該案例描述了您使用預(yù)制語句時(shí)出現(xiàn)的問題,以便您編制程序錯(cuò)誤報(bào)告。
· 您需要使用預(yù)制語句,但是您無法使用支持預(yù)制語句的編程API。
預(yù)制語句的SQL語法基于三個(gè)SQL語句:
PREPARE stmt_name FROM preparable_stmt;
EXECUTE stmt_name [USING @var_name [, @var_name] …];
{DEALLOCATE | DROP} PREPARE stmt_name;
PREPARE語句用于預(yù)備一個(gè)語句,并賦予它名稱stmt_name,借此在以后引用該語句。語句名稱對案例不敏感。preparable_stmt可以是一個(gè)文字字符串,也可以是一個(gè)包含了語句文本的用戶變量。該文本必須展現(xiàn)一個(gè)單一的SQL語句,而不是多個(gè)語句。使用本語句,‘?’字符可以被用于制作參數(shù),以指示當(dāng)您執(zhí)行查詢時(shí),數(shù)據(jù)值在哪里與查詢結(jié)合在一起?!?’字符不應(yīng)加引號(hào),即使您想要把它們與字符串值結(jié)合在一起,也不要加引號(hào)。參數(shù)制作符只能被用于數(shù)據(jù)值應(yīng)該出現(xiàn)的地方,不用于SQL關(guān)鍵詞和標(biāo)識(shí)符等。
如果帶有此名稱的預(yù)制語句已經(jīng)存在,則在新的語言被預(yù)備以前,它會(huì)被隱含地解除分配。這意味著,如果新語句包含一個(gè)錯(cuò)誤并且不能被預(yù)備,則會(huì)返回一個(gè)錯(cuò)誤,并且不存在帶有給定名稱語句。
預(yù)制語句的范圍是客戶端會(huì)話。在此會(huì)話內(nèi),語句被創(chuàng)建。其它客戶端看不到它。
在預(yù)備了一個(gè)語句后,您可使用一個(gè)EXECUTE語句(該語句引用了預(yù)制語句名稱)來執(zhí)行它。如果預(yù)制語句包含任何參數(shù)制造符,則您必須提供一個(gè)列舉了用戶變量(其中包含要與參數(shù)結(jié)合的值)的USING子句。參數(shù)值只能有用戶變量提供,USING子句必須準(zhǔn)確地指明用戶變量。用戶變量的數(shù)目與語句中的參數(shù)制造符的數(shù)量一樣多。
您可以多次執(zhí)行一個(gè)給定的預(yù)制語句,在每次執(zhí)行前,把不同的變量傳遞給它,或把變量設(shè)置為不同的值。
要對一個(gè)預(yù)制語句解除分配,需使用DEALLOCATE PREPARE語句。嘗試在解除分配后執(zhí)行一個(gè)預(yù)制語句會(huì)導(dǎo)致錯(cuò)誤。
如果您終止了一個(gè)客戶端會(huì)話,同時(shí)沒有對以前已預(yù)制的語句解除分配,則服務(wù)器會(huì)自動(dòng)解除分配。
以下SQL語句可以被用在預(yù)制語句中:CREATE TABLE, DELETE, DO, INSERT, REPLACE, SELECT, SET, UPDATE和多數(shù)的SHOW語句。目前不支持其它語句。
以下例子顯示了預(yù)備一個(gè)語句的兩種方法。該語句用于在給定了兩個(gè)邊的長度時(shí),計(jì)算三角形的斜邊。
第一個(gè)例子顯示如何通過使用文字字符串來創(chuàng)建一個(gè)預(yù)制語句,以提供語句的文本:
mysql> PREPARE stmt1 FROM ‘SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse’;
mysql> SET @a = 3;
mysql> SET @b = 4;
mysql> EXECUTE stmt1 USING @a, @b;
±-----------+
| hypotenuse |
±-----------+
| 5 |
±-----------+
mysql> DEALLOCATE PREPARE stmt1;
第二個(gè)例子是相似的,不同的是提供了語句的文本,作為一個(gè)用戶變量:
mysql> SET @s = ‘SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse’;
mysql> PREPARE stmt2 FROM @s;
mysql> SET @a = 6;
mysql> SET @b = 8;
mysql> EXECUTE stmt2 USING @a, @b;
±-----------+
| hypotenuse |
±-----------+
| 10 |
±-----------+
mysql> DEALLOCATE PREPARE stmt2;
預(yù)制語句的SQL語法不能被用于帶嵌套的風(fēng)格中。也就是說,被傳遞給PREPARE的語句本身不能是一個(gè)PREPARE, EXECUTE或DEALLOCATE PREPARE語句。
預(yù)制語句的SQL語法與使用預(yù)制語句API調(diào)用不同。例如,您不能使用mysql_stmt_prepare() C API函數(shù)來預(yù)備一個(gè)PREPARE, EXECUTE或DEALLOCATE PREPARE語句。文章來源:http://www.zghlxwxcb.cn/news/detail-419795.html
預(yù)制語句的SQL語法可以在已存儲(chǔ)的過程中使用,但是不能在已存儲(chǔ)的函數(shù)或觸發(fā)程序中使用。文章來源地址http://www.zghlxwxcb.cn/news/detail-419795.html
到了這里,關(guān)于MySQL - C語言接口-預(yù)處理語句的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!