版权声明:本文为CSDN博主「zhouxinfeng」的原创文章,原文链接:https://blog.csdn.net/zhouxinfeng/article/details/77891771
目录
- MySQL - C语言接口-预处理语句
- 预处理机制特点:
- 预处理机制数据类型
- 函数:
- 预处理机制步骤:
- 示例1: 预处理语句 插入
- 示例2: 预处理语句读取
- 示例3:
- mysql stmt语法_mysql中SQL执行过程详解与用于预处理语句的SQL语法
- mysql中SQL执行过程详解
- 用于预处理语句的SQL语法
MySQL - C语言接口-预处理语句
对于多次执行的语句,预处理执行比直接执行快,主要原因在于,仅对查询执行一次解析操作。在直接执行的情况下,每次执行语句时,均将进行查询。此外,由于每次执行预处理语句时仅需发送参数的数据,从而减少了网络通信量
A: select * from tablename
B: select * from tablename
服务器一般处理方式:
A--->S--->A B--->S--->B
服务器采取预处理机制
A--->S--->A S--->B 减少一次解释执行
A:select * from tablename where id=?
B:select * from tablename where name=?
预处理机制特点:
-
减少服务器负荷
-
提高服务器响应的速度
-
可以提供参数机制,让客户有更多查询方法
预处理机制数据类型
- MYSQL_STMT 该结构表示预处理语句
- MYSQL_BIND 该结构用于语句输入(发送给服务器的数据值)和输出(从服务器返回的结果值)
- 从客户传送数据到服务器
- 从服务器传输数据到客户
函数:
-
MYSQL_STMT *mysql_stmt_init(MYSQL *mysql)
创建MYSQL_STMT句柄。对于该句柄,应使用mysql_stmt_close(MYSQL_STMT *)释放 -
int mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned long length)
给定mysql_stmt_init()返回的语句句柄,准备字符串查询指向的SQL语句,并返回状态值。字符串长度应由“length”参量给出 -
my_bool mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bind)
用于为SQL语句中的参数标记符绑定数据 -
my_bool mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
mysql_stmt_bind_result()用于将结果集中的列与数据缓冲和长度缓冲关联(绑定)起来 -
int mysql_stmt_execute(MYSQL_STMT *stmt)
mysql_stmt_execute()执行与语句句柄相关的预处理查询 -
int mysql_stmt_store_result(MYSQL_STMT *stmt)
以便后续的mysql_stmt_fetch()调用能返回缓冲数据 -
int mysql_stmt_fetch(MYSQL_STMT *stmt)
mysql_stmt_fetch()返回结果集中的下一行 -
my_bool mysql_stmt_close(MYSQL_STMT *)
关闭预处理语句
预处理机制步骤:
-
MYSQL_STMT * st;
-
对处理的数据类型初始化 MYSQL_STMT * mysql_stmt_init(MYSQL*) st=mysql_stmt_init(MYSQL*);
-
将预处理句柄与具体sql语句绑定 int mysql_stmt_prepare(MYSQL_STMT * st,char * sql,int length);
mysql_stmt_prepare(st,sql,strlen(str));
-
mysql语句的参数
select * from tablename where id=? and name=?
给参数赋值
MYSQL_BIND para[n] //1.n根据语句中参数确定(客户-->服务) 2.n根据语句中的字段数确定(服务-->客户)
memset(para,0,sizeof(para));
对参数操作
para[0].buffer_type=MYSQL_TYPE_LONG //设置参数的数据类型
int id;
para[0].buffer=&id; //参数传值
para[1].buffer_type=MYSQL_TYPE_STRING
char str[20];
para[1].buffer_length=sizeof(str);
para[1].buffer=str;
-
预处理与参数绑定 mysql_stmt_bind_param(st,para);
-
执行 mysql_stmt_execute(st);
-
释放预处理机制所占的空间 mysql_stmt_close(MYSQL_STMT *) mysql_stmt_close(st);
示例1: 预处理语句 插入
/*
* 客户端到服务端
*/
#include <stdio.h>
#include <mysql.h>
#include <string.h>
int main(void)
{
MYSQL *conn = mysql_init(NULL); //初始化服务器句柄
/*登陆服务器*/
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); //创建MYSQL_STMT句柄
char *query = "insert into stu values(?, ?);"; // ?问号为占位符,表示一个参数;
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]; // 参数数组
memset(params, 0, sizeof(params));
params[0].buffer_type = MYSQL_TYPE_LONG; // 参数数组设定类型和内容
params[0].buffer = &id; // 注意:int类型变量 需要用&符号,即,buff只接收指针类型
params[1].buffer_type = MYSQL_TYPE_STRING;
params[1].buffer = name; // name已经是指针了
params[1].buffer_length = strlen(name); // 如果是字符串还需要明确长度
mysql_stmt_bind_param(stmt, params); // stmt 与参数数组的绑定
mysql_stmt_execute(stmt); // 执行与语句句柄相关的预处理
mysql_stmt_close(stmt); // 关闭 预处理
mysql_close(conn); // 关闭连接
return 0;
}
示例2: 预处理语句读取
/*
* 服务端到客户端
*/
#include <stdio.h>
#include <mysql.h>
#include <string.h>
int main(void)
{
MYSQL *conn = mysql_init(NULL); //初始化服务器句柄
/*登陆服务器*/
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); //创建MYSQL_STMT句柄 预处理对象
char *query = "select * from stu;";
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 name: ");
//scanf("%d %s", &id, name);
MYSQL_BIND params[2]; // 读出内容为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);
mysql_stmt_bind_result(stmt, params); //用于将结果集中的列与数据缓冲和长度缓冲关联(绑定)起来
mysql_stmt_execute(stmt); //执行与语句句柄相关的预处理
mysql_stmt_store_result(stmt); //以便后续的mysql_stmt_fetch()调用能返回缓冲数据
while(mysql_stmt_fetch(stmt) == 0) //返回结果集中的下一行
printf("%d\t%s\n", id, name);
mysql_stmt_close(stmt);
mysql_close(conn);
return 0;
}
示例3:
/*
* 客户端到服务端,再到客户端
*/
#include <stdio.h>
#include <mysql.h>
#include <string.h>
int main(void)
{
MYSQL *conn = mysql_init(NULL); //初始化服务器句柄
/*登陆服务器*/
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); //创建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); // 绑定查询参数
mysql_stmt_bind_result(stmt, params); // 绑定查询结果;用于将结果集中的列与数据缓冲和长度缓冲关联(绑定)起来
mysql_stmt_execute(stmt); //执行与语句句柄相关的预处理
mysql_stmt_store_result(stmt); //以便后续的mysql_stmt_fetch()调用能返回缓冲数据
while(mysql_stmt_fetch(stmt) == 0) //返回结果集中的下一行
printf("%d\t%s\n", id, name);
mysql_stmt_close(stmt);
mysql_close(conn);
return 0;
}
mysql stmt语法_mysql中SQL执行过程详解与用于预处理语句的SQL语法
mysql中SQL执行过程详解
客户端发送一条查询给服务器;
服务器先检查查询缓存,如果命中了缓存,则立刻返回存储在缓存中的结果。否则进入下一阶段。
服务器段进行SQL解析、预处理,在优化器生成对应的执行计划;
mysql根据优化器生成的执行计划,调用存储引擎的API来执行查询。
用于预处理语句的SQL语法
MySQL 5.1对服务器一方的预制语句提供支持。如果您使用合适的客户端编程界面,则这种支持可以发挥在MySQL 4.1中实施的高效客户端/服务器二进制协议的优势。候选界面包括MySQL C API客户端库(用于C程序)、MySQL Connector/J(用于Java程序)和MySQL Connector/NET。例如,C API可以提供一套能组成预制语句API的函数调用。请参见25.2.4节,“C API预处理语句”。其它语言界面可以对使用了二进制协议(通过在C客户端库中链接)的预制语句提供支持。有一个例子是PHP 5.0中的mysqli扩展。
对预制语句,还有一个SQL界面可以利用。与在整个预制语句API中使用二进制协议相比,本界面效率没有那么高,但是它不要求编程,因为在SQL层级,可以直接利用本界面:
· 当您无法利用编程界面时,您可以使用本界面。
· 有些程序允许您发送SQL语句到将被执行的服务器中,比如mysql客户端程序。您可以从这些程序中使用本界面。
· 即使客户端正在使用旧版本的客户端库,您也可以使用本界面。唯一的要求是,您能够连接到一个支持预制语句SQL语法的服务器上。
预制语句的SQL语法在以下情况下使用:
· 在编代码前,您想要测试预制语句在您的应用程序中运行得如何。或者也许一个应用程序在执行预制语句时有问题,您想要确定问题是什么。
· 您想要创建一个测试案例,该案例描述了您使用预制语句时出现的问题,以便您编制程序错误报告。
· 您需要使用预制语句,但是您无法使用支持预制语句的编程API。
预制语句的SQL语法基于三个SQL语句:
PREPARE stmt_name FROM preparable_stmt;
EXECUTE stmt_name [USING @var_name [, @var_name] …];
{DEALLOCATE | DROP} PREPARE stmt_name;
PREPARE语句用于预备一个语句,并赋予它名称stmt_name,借此在以后引用该语句。语句名称对案例不敏感。preparable_stmt可以是一个文字字符串,也可以是一个包含了语句文本的用户变量。该文本必须展现一个单一的SQL语句,而不是多个语句。使用本语句,‘?’字符可以被用于制作参数,以指示当您执行查询时,数据值在哪里与查询结合在一起。‘?’字符不应加引号,即使您想要把它们与字符串值结合在一起,也不要加引号。参数制作符只能被用于数据值应该出现的地方,不用于SQL关键词和标识符等。
如果带有此名称的预制语句已经存在,则在新的语言被预备以前,它会被隐含地解除分配。这意味着,如果新语句包含一个错误并且不能被预备,则会返回一个错误,并且不存在带有给定名称语句。
预制语句的范围是客户端会话。在此会话内,语句被创建。其它客户端看不到它。
在预备了一个语句后,您可使用一个EXECUTE语句(该语句引用了预制语句名称)来执行它。如果预制语句包含任何参数制造符,则您必须提供一个列举了用户变量(其中包含要与参数结合的值)的USING子句。参数值只能有用户变量提供,USING子句必须准确地指明用户变量。用户变量的数目与语句中的参数制造符的数量一样多。
您可以多次执行一个给定的预制语句,在每次执行前,把不同的变量传递给它,或把变量设置为不同的值。
要对一个预制语句解除分配,需使用DEALLOCATE PREPARE语句。尝试在解除分配后执行一个预制语句会导致错误。
如果您终止了一个客户端会话,同时没有对以前已预制的语句解除分配,则服务器会自动解除分配。
以下SQL语句可以被用在预制语句中:CREATE TABLE, DELETE, DO, INSERT, REPLACE, SELECT, SET, UPDATE和多数的SHOW语句。目前不支持其它语句。
以下例子显示了预备一个语句的两种方法。该语句用于在给定了两个边的长度时,计算三角形的斜边。
第一个例子显示如何通过使用文字字符串来创建一个预制语句,以提供语句的文本:
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;
第二个例子是相似的,不同的是提供了语句的文本,作为一个用户变量:
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;
预制语句的SQL语法不能被用于带嵌套的风格中。也就是说,被传递给PREPARE的语句本身不能是一个PREPARE, EXECUTE或DEALLOCATE PREPARE语句。
预制语句的SQL语法与使用预制语句API调用不同。例如,您不能使用mysql_stmt_prepare() C API函数来预备一个PREPARE, EXECUTE或DEALLOCATE PREPARE语句。
预制语句的SQL语法可以在已存储的过程中使用,但是不能在已存储的函数或触发程序中使用。