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

news2024/9/21 21:40:57

版权声明:本文为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=?

预处理机制特点:

  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执行过程详解

在这里插入图片描述

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

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

服务器段进行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语法可以在已存储的过程中使用,但是不能在已存储的函数或触发程序中使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/440660.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

集群聊天服务器项目(三)——负载均衡模块与跨服务器聊天

负载均衡模块 为什么要加入负载均衡模块 原因是&#xff1a;单台服务器并发量最多两三万&#xff0c;不够大。 负载均衡器 Nginx的用处或意义**&#xff08;面试题&#xff09;** 把client请求按负载算法分发到具体业务服务器Chatserver能和ChatServer保持心跳机制&#xf…

机器学习实战5-天气预测系列:利用数据集可视化分析数据,并预测某个城市的天气情况

大家好&#xff0c;我是微学AI&#xff0c;最近天气真的是多变啊&#xff0c;忽冷忽热&#xff0c;今天再次给大家带来天气的话题&#xff0c;机器学习实战5-天气预测系列&#xff0c;我们将探讨一个城市的气象数据集&#xff0c;并利用机器学习来预测该城市的天气状况。该数据…

迈入Java,一文告诉你学习Java的原因

前言 Java是一种流行的编程语言&#xff0c;由Sun Microsystems于1995年首次发布。自那时以来&#xff0c;Java已成为全球最广泛使用的编程语言之一。Java具有许多优点&#xff0c;包括跨平台、面向对象和安全性等&#xff0c;使其成为开发企业软件、Web应用程序和移动应用程序…

Consul TTL健康检查方式

consul比较常用的健康检查方式为http健康检查方式&#xff0c;也还有使用TTL方式来进行健康检查的&#xff0c;下面从spring-cloud-consul-discovery这个SDK来着手分析。 构建ConsulAutoRegistration&#xff0c;这里的工作是组成服务注册的报文&#xff0c;有一个setCheck方法…

【应急响应】战中溯源反制对抗上线CSGoby蚁剑Sqlmap等安全工具

文章目录 溯源反制-Webshell工具-Antsword正常情况下&#xff0c;PHP后门上线发现PHP后门&#xff0c;修改webshell进行反制 溯源反制-SQL注入工具-SQLMAP溯源反制-漏洞扫描工具-Goby&Awvs溯源反制-远程控制工具-CobaltStrike1、伪造流量批量上线&#xff08;欺骗防御&…

(IPC)进程间通信的常用的两种方式——管道、共享内存

前言&#xff1a; 众所周知&#xff0c;不同的进程之间&#xff0c;在正常情况下&#xff0c;由于其拥有独立的PCB、上下文等原因&#xff0c;每个进程都是独立且互不干扰&#xff0c;这不仅保证了进程的安全&#xff0c;也降低了OS对于进程的管理成本。 但是通常情况下&…

第04讲:实战掌握 Byte Buddy,体验代码生成的顺畅

为什么需要运行时代码生成 我们知道&#xff0c;Java 是一种强类型的编程语言&#xff0c;即要求所有变量和对象都有一个确定的类型&#xff0c;如果在赋值操作中出现类型不兼容的情况&#xff0c;就会抛出异常。强类型检查在大多数情况下是可行的&#xff0c;然而在某些特殊场…

猴子分桃与反转部分单链表

目录 一、编程题 1.猴子分桃 2.反转部分单向链表 二、选择题 1.如果希望监听 TCO 端口 9000&#xff0c;服务器端应该怎样创建 socket&#xff1f; 2. jre 判断程序是否执行结束的标准是&#xff08; &#xff09; 一、编程题 1.猴子分桃 链接&#xff1a;猴子分桃__…

C# 平台调用过程

(1&#xff09;调用LoadLibrary加载非托管DLL到内存中,并调用GetProcAddress 获得内存中非托管函数的指针。 (2) 为包含非托管函数地址的托管签名生成一个DllImport存根&#xff08;stub)。 (3) 压入被调用方保存的寄存器。 (4&#xff09;创建一个DllImport帧&#xff08;fr…

Node.js—http模块

目录 1、HTTP 协议1.1 概念1.2 请求报文的组成1.3 HTTP 的请求行1.4 HTTP 请求头1.5 HTTP 的请求体1.6 响应报文的组成 2、创建 HTTP 服务2.1 操作步骤2.2 测试2.3 注意事项 3、获取 HTTP 请求报文3.1 请求方法 request.method3.2 请求版本 request.httpVersion3.3 请求路径 re…

shell 初级

判断当前磁盘剩余空间是否有20G&#xff0c;如果小于20G&#xff0c;则将报警邮件发送给管理员&#xff0c;每天检查一次磁盘剩余空间。 [rootlocalhost ~]# bash c.sh c.sh: line 7: echo剩余内存:1GB,小于20GB 判断web服务是否运行&#xff08;1、查看进程的方式判断该程序是…

ctfshow_愚人杯WEB之easy_flask

1、easy_flask 百度了下什么是flask&#xff0c;flask是一款非常流行的python web框架。 2、尝试步骤 &#xff08;1&#xff09;、搜索博文&#xff0c;查看该题是如何破解的 先注册账号&#xff0c;登录自己注册的账号&#xff0c;查看可访问内容&#xff08;可以查看到部…

深入探讨Linux驱动开发:字符设备驱动开发与测试

文章目录 一、字符设备驱动介绍1.设备驱动介绍 二、设备号1.设备号介绍2.分配与释放设备编号①dev_t类型②静态分配设备号③动态分配设备号④释放主次设备号⑤手动创建设备节点⑥自动创建设备节点⑦删除设备节点 三、字符设备注册1.cdev结构体2.注册cdev到内核 三、字符设备驱动…

黑马点评实战篇问题总结

缓存穿透 用户查询的数据在缓存和数据库中都不存在 这样的请求每次都会打到数据库上 解决方案&#xff1a; 1.缓存空字符串&#xff08;额外的内存消耗&#xff0c;可能造成短期的不一致&#xff09; 2.布隆过滤&#xff08;内存占用少&#xff0c;没有多余key&#xff0c;实现…

访问若依vue版后端api接口

访问若依vue版后端api接口 如何使用Talend API Tester进行访问若依vue-前后端分离版的后端api接口&#xff1f; 方法一&#xff1a; 写好一个后台api接口&#xff0c;启动项目 直接使用Talend API Tester进行访问后台api出现如下错误&#xff0c;原因是因为若依系统有jwt认证…

2023软件测试工程师涨薪攻略,3年如何达到30K?

1.软件测试如何实现涨薪 首先涨薪并不是从8000涨到9000这种涨薪&#xff0c;而是从8000涨到15K加到25K的涨薪。基本上三年之内就可以实现。 如果我们只是普通的有应届毕业生或者是普通本科那我们就只能从小公司开始慢慢往上走。 有些同学想去做测试&#xff0c;是希望能够日…

数据可视化的web工具 apache-superset

文章目录 简介安装window10Ubuntu1804CentOS8 配置连接数据库创建仪表板创建图表图表加入仪表板时间序列折线图 简介 Superset是一款由Airbnb开源的、目前由Apache孵化的&#xff0c;基于Flask-appbuilder搭建的“现代化的企业级BI&#xff08;商业智能&#xff09;Web应用程序…

很合适新手入门使用的Python游戏开发包pygame实例教程-02[如何控制飞行]

前面一篇博文&#xff0c;我们让飞机动起来了&#xff0c;但不是那么完美&#xff0c;我们继续来完善我们的游戏代码&#xff0c;本篇博文主要介绍获取按键的方式已经飞行的控制。 文章目录 一、获取按键的三种方式1、通过event.get配合pygame.key枚举2、通过event.get配合ord…

C++入门教程||C++ 文件和流||C++ 异常处理

C 文件和流 C 文件和流 到目前为止&#xff0c;我们已经使用了 iostream 标准库&#xff0c;它提供了 cin 和 cout 方法分别用于从标准输入读取流和向标准输出写入流。 本教程介绍如何从文件读取流和向文件写入流。这就需要用到 C 中另一个标准库 fstream&#xff0c;它定义…

《我的第一本算法书》读书笔记

《我的第一本算法书》读书笔记 作者&#xff1a;宫崎修一 石田保辉 ◆ 1-3 数组 在链表和数组中&#xff0c;数据都是线性地排成一列。在链表中访问数据较为复杂&#xff0c;添加和删除数据较为简单&#xff1b;而在数组中访问数据比较简单&#xff0c;添加和删除数据却比较复…