558
社区成员
发帖
与我相关
我的任务
分享
预处理语句的核心优势是:SQL语句先在服务器端编译(预处理),参数后续单独传递,避免重复编译提升效率,同时防止SQL注入(参数与SQL指令分离)。你提到的这些接口是预处理语句执行流程的关键环节。
1. mysql_stmt_init(MYSQL *mysql)
核心功能:初始化一个预处理语句句柄(MYSQL_STMT 类型指针),为后续的SQL预处理、参数绑定等操作分配内存和初始化相关资源。
参数:mysql 是已成功连接MySQL服务器的连接句柄(由 mysql_init() + mysql_real_connect() 创建)。
返回值:成功返回非空的 MYSQL_STMT* 句柄;失败返回 NULL(可通过 mysql_error(mysql) 获取错误信息)。
注意:该函数仅创建句柄,不与任何具体SQL语句绑定,后续需通过 mysql_stmt_prepare() 关联SQL。
2. mysql_stmt_prepare(MYSQL_STMT *stmt, const char *sql, unsigned long length)
核心功能:将SQL语句发送到MySQL服务器,进行解析、编译和优化(即“预处理”),生成服务器端可复用的执行计划。
参数说明:
stmt:由 mysql_stmt_init() 创建的预处理句柄;
sql:待预处理的SQL语句字符串(支持占位符 ?,用于接收后续动态参数,如 INSERT INTO t (name, age) VALUES (?, ?));
length:SQL字符串的长度(以字节为单位,若为UTF-8中文需注意字节长度;传入 0 时,函数会自动通过 strlen(sql) 获取长度)。
返回值:预处理成功返回 0;失败返回非0(可通过 mysql_stmt_error(stmt) 获取错误信息)。
关键优势:预处理后的执行计划可被多次执行(只需更换参数),无需重复解析编译,提升重复执行场景的效率。
3. MYSQL_BIND param = {0};
核心说明:MYSQL_BIND 是MySQL C API定义的数据绑定结构体,用于建立“应用程序变量”与“SQL占位符(?)”或“查询结果集字段”之间的关联。
这里 param = {0} 是对结构体进行零初始化,目的是清空结构体的所有成员变量,避免垃圾值导致的绑定异常或内存错误。
MYSQL_BIND 核心成员(参数绑定时常用):
buffer:指向存储参数数据的应用程序缓冲区(如 int age = 20; buffer = &age;);
buffer_type:指定参数的数据类型(如 MYSQL_TYPE_INT(整型)、MYSQL_TYPE_STRING(字符串)、MYSQL_TYPE_BLOB(二进制大对象)等);
buffer_length:缓冲区的字节长度(仅对字符串、BLOB等变长类型有效);
is_null:指向 my_bool 类型变量,标记该参数是否为 NULL;
length:指向 unsigned long 变量,存储实际参数数据的字节长度(用于变长类型)。
用途:此处用于“输入参数绑定”(后续通过 mysql_stmt_bind_param() 关联SQL占位符),也可用于“输出结果绑定”(关联查询结果集字段)。
4. mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bind)
核心功能:将 MYSQL_BIND 结构体数组(或单个结构体)与预处理语句中的 SQL占位符(?) 进行绑定,建立“应用程序参数”与“SQL动态参数”的映射关系。
参数说明:
stmt:已完成预处理的 MYSQL_STMT 句柄;
bind:指向 MYSQL_BIND 结构体数组的指针(数组长度需与SQL中占位符 ? 的数量一致,且顺序与占位符在SQL中的位置一一对应)。
返回值:绑定成功返回 0;失败返回非0(可通过 mysql_stmt_error(stmt) 获取错误信息)。
注意:绑定后,后续只需修改 MYSQL_BIND 结构体中 buffer 指向的变量值,即可更新传递给SQL的参数,无需重新绑定。
5. mysql_stmt_send_long_data(MYSQL_STMT *stmt, unsigned int param_number, const char *data, unsigned long length)
核心功能:用于分块发送超长数据(如大文本(TEXT)、大二进制数据(BLOB)、超大字符串等),解决一次性传递大数据导致的内存不足或数据包过大问题。
参数说明:
stmt:预处理语句句柄;
param_number:要发送数据的占位符索引(从 0 开始,对应SQL中占位符的顺序,如第一个 ? 对应 0);
data:本次要发送的分块数据缓冲区;
length:本次分块数据的字节长度。
使用场景与注意:
适用于数据大小超过缓冲区限制或MySQL数据包上限的场景(如上传几MB的图片、几KB的长文本);
需在 mysql_stmt_execute() 之前调用,可多次调用该函数向同一个占位符分块传递数据,服务器会自动拼接所有分块;
仅对支持超长数据的类型(TEXT、BLOB、VARCHAR(大长度) 等)有效。
6. mysql_stmt_execute(MYSQL_STMT *stmt)
核心功能:执行已完成预处理和参数绑定(或超长数据发送)的SQL语句,将绑定的参数数据传递给MySQL服务器,触发服务器执行预处理好的执行计划。
参数:stmt:已完成预处理、参数绑定的 MYSQL_STMT 句柄。
返回值:执行成功返回 0;失败返回非0(可通过 mysql_stmt_error(stmt) 获取错误信息)。
补充:
若为查询语句(SELECT),执行后需通过 mysql_stmt_store_result()、mysql_stmt_bind_result()、mysql_stmt_fetch() 等函数获取结果集;
若为更新/插入/删除语句(INSERT/UPDATE/DELETE),可通过 mysql_stmt_affected_rows(stmt) 获取受影响的行数。
7. mysql_stmt_close(MYSQL_STMT *stmt)
核心功能:关闭预处理语句句柄,释放句柄对应的客户端内存资源和服务器端的预处理执行计划资源,避免内存泄漏和服务器资源占用。
参数:stmt:由 mysql_stmt_init() 创建的预处理句柄(无论执行成功与否,都应调用该函数释放资源)。
注意:
调用后,该 MYSQL_STMT* 句柄将失效,不可再用于后续操作;
若句柄未关闭,多次创建预处理句柄可能导致内存泄漏;
即使SQL执行失败,也需调用该函数释放资源。
上述接口的典型调用顺序为:
mysql_stmt_init() → 初始化预处理句柄
mysql_stmt_prepare() → 预处理SQL语句(含占位符)
MYSQL_BIND param[] = {0}; → 初始化参数绑定结构体
mysql_stmt_bind_param() → 绑定参数与占位符
5.(可选)mysql_stmt_send_long_data() → 分块发送超长参数数据
mysql_stmt_execute() → 执行SQL语句
7.(可选)获取执行结果(查询语句需额外处理结果集)
mysql_stmt_close() → 关闭句柄释放资源
总结
这些接口是MySQL C API预处理语句的核心,实现了“初始化-预处理-绑定-执行-释放”的完整流程;
核心优势是高效(重复执行无需重新编译)、安全(防止SQL注入)、支持超长数据;
关键对应关系:MYSQL_BIND 绑定参数与占位符,mysql_stmt_send_long_data 补充超长数据,mysql_stmt_close 必须调用避免资源泄漏。
参考链接:https://github.com/0voice