MySQL - C语言接口-预处理语句

这篇具有很好参考价值的文章主要介绍了MySQL - C语言接口-预处理语句。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

版权声明:本文为CSDN博主「zhouxinfeng」的原创文章,原文链接:https://blog.csdn.net/zhouxinfeng/article/details/77891771

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=?

预处理机制特点:

  1. 减少服务器负荷

  2. 提高服务器响应的速度

  3. 可以提供参数机制,让客户有更多查询方法

预处理机制数据类型

  • MYSQL_STMT 该结构表示预处理语句
  • MYSQL_BIND 该结构用于语句输入(发送给服务器的数据值)和输出(从服务器返回的结果值)
  1. 从客户传送数据到服务器
  2. 从服务器传输数据到客户

函数:

  1. MYSQL_STMT *mysql_stmt_init(MYSQL *mysql)
    创建MYSQL_STMT句柄。对于该句柄,应使用mysql_stmt_close(MYSQL_STMT *)释放

  2. int mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, unsigned long length)
    给定mysql_stmt_init()返回的语句句柄,准备字符串查询指向的SQL语句,并返回状态值。字符串长度应由“length”参量给出

  3. my_bool mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bind)
    用于为SQL语句中的参数标记符绑定数据

  4. my_bool mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
    mysql_stmt_bind_result()用于将结果集中的列与数据缓冲和长度缓冲关联(绑定)起来

  5. int mysql_stmt_execute(MYSQL_STMT *stmt)
    mysql_stmt_execute()执行与语句句柄相关的预处理查询

  6. int mysql_stmt_store_result(MYSQL_STMT *stmt)
    以便后续的mysql_stmt_fetch()调用能返回缓冲数据

  7. int mysql_stmt_fetch(MYSQL_STMT *stmt)
    mysql_stmt_fetch()返回结果集中的下一行

  8. my_bool mysql_stmt_close(MYSQL_STMT *)
    关闭预处理语句

预处理机制步骤:

  1. MYSQL_STMT * st;

  2. 对处理的数据类型初始化 MYSQL_STMT * mysql_stmt_init(MYSQL*) st=mysql_stmt_init(MYSQL*);

  3. 将预处理句柄与具体sql语句绑定 int mysql_stmt_prepare(MYSQL_STMT * st,char * sql,int length);

    mysql_stmt_prepare(st,sql,strlen(str));

  4. 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;

  1. 预处理与参数绑定 mysql_stmt_bind_param(st,para);

  2. 执行 mysql_stmt_execute(st);

  3. 释放预处理机制所占的空间 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执行过程详解

MySQL - C语言接口-预处理语句

客户端发送一条查询给服务器;

服务器先检查查询缓存,如果命中了缓存,则立刻返回存储在缓存中的结果。否则进入下一阶段。

服务器段进行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语法可以在已存储的过程中使用,但是不能在已存储的函数或触发程序中使用。文章来源地址https://www.toymoban.com/news/detail-419795.html

到了这里,关于MySQL - C语言接口-预处理语句的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【C语言】预处理

    在ANSI C的任何一种实现中,存在两个不同的环境。 第1种是翻译环境,在这个环境中源代码被转换为可执行的机器指令。 第2种是执行环境,它用于实际执行代码。 1.翻译环境 组成一个程序的每个源文件通过编译过程分别转换成目标代码 每个目标文件由链接器(linker)捆绑在

    2024年02月17日
    浏览(70)
  • 【C语言】预处理详解

             本文目录 1 预定义符号 2 #define 2.1 #define 定义标识符 2.2 #define 定义宏 2.3 #define 替换规则 2.4 #和## 2.5 带副作用的宏参数 2.6 宏和函数对比 2.7 命名约定 3 #undef 4 命令行定义 5 条件编译 6 文件包含 6.1 头文件被包含的方式 6.2 嵌套文件包含 这些预定义符号都是语言内置

    2024年02月14日
    浏览(44)
  • C语言·预处理详解

            C语言设置了一些预定义符号,可以直接使用,预定义符号也是在预处理期间处理的                 __FILE__  进行编译的源文件                 __LINE__  文件当前的行号                 __DATE__  文件被编译的日期                 _

    2024年01月21日
    浏览(49)
  • C语言预处理详解

    上一篇博客中我们讲了C语言的编译与链接,在编译过程中有三个小阶段:预处理、编译、汇编。 本篇博客将详细讲述预处理部分的有关知识点 。 在C语言中,C语言本身设置了⼀些预定义符号,可以直接使⽤ ,预定义符号的处理也是在预处理期间进行的。 在这里介绍几个常

    2024年04月15日
    浏览(57)
  • C语言:预处理详解

    创作不易,来个三连呗! C语⾔设置了⼀些预定义符号, 可以直接使⽤ ,预定义符号也是在预处理期间处理的。 __FILE__ //进⾏编译的源⽂件 __LINE__ //⽂件当前的⾏号 __DATE__ //⽂件被编译的⽇期 __TIME__ //⽂件被编译的时间 __STDC__ //如果编译器遵循ANSI C,其值为1,否则未定义

    2024年01月19日
    浏览(49)
  • 详解C语言—预处理

    目录 一、预处理 1、预定义符号介绍 2、预处理指令 #define #define 定义标识符:  #define 定义宏: #define 替换规则 3、预处理操作符# 4、预处理操作符## 5、带副作用的宏参数 6、宏和函数对比 二、命名约定 三、预处理指令 #undef 四、命令行定义 五、条件编译  1、单分支#if:

    2024年02月08日
    浏览(57)
  • C语言【预处理器】

    1、一些关于预处理的知识 ​C代码中,一般带 # 的都是预处理指令,包括 宏替换、文件包含、条件编译 等。 ​为兼容一些老编译器, # 前后一般不写空格 ​预处理指令后面不加分号。 2、宏定义 3、文件包含 ​自定义头文件,用\\\" \\\" 。 引号里填相对路径或绝对路径。基于当

    2024年02月05日
    浏览(45)
  • <C语言> 预处理和宏

    这些预定义符号都是C语言内置的。 举个例子: #define 定义标识符形式: 其中, 标识符 是你希望定义的名称,而 值 可以是一个数值、一个字符串或一个表达式。 例子: #define 只是进行简单的文本替换,没有类型检查和错误检查。 建议 #define 后面不要加分号 #define机制包括

    2024年02月14日
    浏览(37)
  • 【C语言进阶】预处理详解

    对预处理的相关知识进行详细的介绍                  ✨  猪巴戒 :个人主页✨                 所属专栏 :《C语言进阶》         🎈 跟着猪巴戒 ,一起学习C语言🎈 目录 引言 预定义符号 #define定义常量 #define定义宏 带有副作用的宏参数 宏替换的规则 宏函数的

    2024年01月23日
    浏览(45)
  • 自然语言之文本预处理

    概念 分词就是将连续的字序列按照一定的规范重新组合成词序列的过程。在英文的行文中,单词之间是以空格作为自然分界符的,而中文只是字、句和段能通过明显的分界符来简单划界,唯独词没有一个形式上的分界符。分词过程就是找到这样分界符的过程. 作用 词作为语言

    2024年02月06日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包