MySQL学习(七)——存储过程

文章目录

  • 1. 基本语法
  • 2. 变量
    • 2.1 系统变量
    • 2.2 用户定义变量
    • 2.3 局部变量
  • 3. 逻辑关系
    • 3.1 if
    • 3.2 参数
    • 3.3 case
    • 3.4 while
    • 3.4 repeat
    • 3.5 loop
  • 4. 存储结构
    • 4.1 游标
    • 4.2 条件处理程序
    • 4.3 存储函数

存储过程是事先经过编译并存储在数据库中的一段 SQL 语句的集合,调用存储过程可以简化应用开发人员的很多工作,减少数据在数据库和应用服务器之间的传输,对于提高数据处理的效率是有好处的。

存储过程思想上很简单,就是数据库 SQL 语言层面的代码封装与重用。

其特点如下:

  • 封装,复用。可以把某一业务SQL封装在存储过程中,需要用到的时候直接调用即可。
  • 可以接收参数,也可以返回数据。再存储过程中,可以传递参数,也可以接收返回值。
  • 减少网络交互,效率提升。如果涉及到多条SQL,每执行一次都是一次网络传输。 而如果封装在存储过程中,我们只需要网络交互一次可能就可以了。

1. 基本语法

  • 创建

    CREATE PROCEDURE 存储过程名称 ([ 参数列表 ])
    BEGIN-- SQL语句
    END ;
    
  • 调用

    CALL 名称 ([ 参数 ]);
    
  • 查看

    SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA = 'xxx'; -- 查询指定数据库的存储过程及状态信息SHOW CREATE PROCEDURE 存储过程名称 ; -- 查询某个存储过程的定义
    
  • 删除

    DROP PROCEDURE [ IF EXISTS ] 存储过程名称 ;
    

代码演示:

-- 存储过程基本语法
-- 创建
create procedure p1()
beginselect count(*) from tb_user;
end;-- 调用
call p1();-- 查看
select * from information_schema.ROUTINES where ROUTINE_SCHEMA = 'study';
show create procedure p1;-- 删除
drop procedure if exists p1;

注意: 在命令行中,执行创建存储过程的SQL时,需要通过关键字 delimiter 指定SQL语句的结束符。

上面的注意是什么意思呢?让我们在命令行中执行上面创建的SQL语句。

在这里插入图片描述

可以看到,执行出现了报错。这是因为命令行中默认是读取到分号后进行执行一次程序的执行,这就完全与我们的语句相违背了。所以我们需要使用 delimiter 命令自定义结束的语句,这里我们以 $$ 定义为例,语句如下:

在这里插入图片描述

2. 变量

在MySQL中变量分为三种类型: 系统变量、用户定义变量、局部变量。

2.1 系统变量

系统变量 是MySQL服务器提供,不是用户定义的,属于服务器层面。分为全局变量(GLOBAL)、会话变量(SESSION)。

  • 全局变量(GLOBAL): 全局变量针对于所有的会话。
  • 会话变量(SESSION): 会话变量针对于单个会话,在另外一个会话窗口就不生效了。

其语法如下:

  • 查看系统变量

    SHOW [ SESSION | GLOBAL ] VARIABLES ; -- 查看所有系统变量SHOW [ SESSION | GLOBAL ] VARIABLES LIKE '......'; -- 可以通过LIKE模糊匹配方式查找变量SELECT @@[SESSION | GLOBAL] 系统变量名; -- 查看指定变量的值
    
  • 设置系统变量

    SET [ SESSION | GLOBAL ] 系统变量名 =;SET @@[SESSION | GLOBAL] 系统变量名 =;
    

注意:

  1. 如果没有指定SESSION/GLOBAL,默认是SESSION,会话变量。\
  2. mysql服务重新启动之后,所设置的全局参数会失效,要想不失效,可以在 /etc/my.ini 中配置。

2.2 用户定义变量

用户定义变量 是用户根据需要自己定义的变量,用户变量不用提前声明,在用的时候直接用 “@变量名” 使用就可以。其作用域为当前连接。

  • 赋值

    # 方式一,赋值时,可以使用 = ,也可以使用 :=
    SET @var_name = expr [, @var_name = expr] ... ;
    SET @var_name := expr [, @var_name := expr] ... ;# 方式二
    SELECT @var_name := expr [, @var_name := expr] ... ;
    SELECT 字段名 INTO @var_name FROM 表名;
    
  • 使用

    SELECT @var_name ;
    

注意: 用户定义的变量无需对其进行声明或初始化,只不过获取到的值为NULL

代码演示如下:

-- 赋值
set @myname = 'itcast';
set @myage := 10;
set @mygender := '男',@myhobby := 'java';select @mycolor := 'red';
select count(*) into @mycount from tb_user;-- 使用
select @myname,@myage,@mygender,@myhobby;select @mycolor , @mycount;select @abc;

2.3 局部变量

局部变量 是根据需要定义的在局部生效的变量,访问之前,需要DECLARE声明。可用作存储过程内的局部变量和输入参数,局部变量的范围是在其内声明的BEGIN ... END块。

  • 声明

    DECLARE 变量名 变量类型 [DEFAULT ... ] ;
    

    变量类型就是数据库字段类型:INT、BIGINT、CHAR、VARCHAR、DATE、TIME等。

  • 赋值

    SET 变量名 =;
    SET 变量名 :=;
    SELECT 字段名 INTO 变量名 FROM 表名 ... ;
    

    代码示例如下:

    -- 声明局部变量 - declare
    -- 赋值
    create procedure p2()
    begindeclare stu_count int default 0;select count(*) into stu_count from student;select stu_count;
    end;-- 调用存储过程
    call p2();
    

3. 逻辑关系

3.1 if

if 用于做条件判断,具体的语法结构为:

IF 条件1 THEN.....
ELSEIF 条件2 THEN    -- 可选.....
ELSE 				-- 可选.....
END IF;

if条件判断的结构中,ELSE IF 结构可以有多个,也可以没有。 ELSE结构可以有,也可以没有。

代码示例:

根据定义的分数age变量,判定当前年龄对应的阶段。

  • age <=30,视作青年
  • age <=60且age >= 30 ,视作中年
  • age> 60 ,视作老年
create procedure p3()
begindeclare age int default 40;declare result varchar(10);if age > 60 thenset result := '老年';elseif age >= 30 thenset result := '中年';elseset result := '青年';end if;select result;
end;call p3();

上述的需求我们虽然已经实现了,但是也存在一些问题,比如:age 我们是在存储过程中定义死的,而且最终计算出来的分数等级,我们也仅仅是最终查询展示出来而已。

那么我们能不能,把age动态的传递进来,计算出来的分数等级是否可以作为返回值返回呢?答案是肯定的,我们可以通过接下来所讲解的 参数 来解决上述的问题。

3.2 参数

参数的类型,主要分为以下三种:IN、OUT、INOUT。 具体的含义如下

类型含义备注
IN该类参数作为输入,也就是需要调用时传入值默认
OUT该类参数作为输出,也就是该参数可以作为返回值
INOUT既可以作为输入参数,也可以作为输出参数

语法如下:

CREATE PROCEDURE 存储过程名称 ([ IN/OUT/INOUT 参数名 参数类型 ])
BEGIN-- SQL语句
END ;

示例一:

我们将上述例子改为传入参数并且传出返回值的形式如下:

create procedure p4(in age int, out result varchar(10))
beginif age > 60 thenset result := '老年';elseif age >= 30 thenset result := '中年';elseset result := '青年';end if;select result;
end;-- 定义用户变量 @result来接收返回的数据, 用户变量可以不用声明
call p4(61, @result);
select @result

示例二

将传入的200分制的分数,进行换算,换算成百分制,然后返回。

create procedure p5(inout score double)
beginset score := score * 0.5;
end;set @score = 198;
call p5(@score);select @score;

3.3 case

case结构及作用,和我们在基础篇中所讲解的流程控制函数很类似。有两种语法格式:

语法一:

-- 含义: 当case_value的值为 when_value1 时,执行statement_list1,当值为 when_value2 时,执行statement_list2, 否则就执行 statement_list
CASE case_valueWHEN when_value1 THEN statement_list1[ WHEN when_value2 THEN statement_list2] ...[ ELSE statement_list ]
END CASE;

语法二:

-- 含义: 当条件search_condition1成立时,执行statement_list1,当条件search_condition2成立时,执行statement_list2, 否则就执行 statement_list
CASEWHEN search_condition1 THEN statement_list1[WHEN search_condition2 THEN statement_list2] ...[ELSE statement_list]
END CASE;

示例:

根据传入的月份,判定月份所属的季节(要求采用case结构)。

  • 1-3月份,为第一季度
  • 4-6月份,为第二季度
  • 7-9月份,为第三季度
  • 10-12月份,为第四季度
create procedure p6(in month int)
begindeclare result varchar(10);casewhen month >= 1 and month <= 3 thenset result := '第一季度';when month >= 4 and month <= 6 thenset result := '第二季度';when month >= 7 and month <= 9 thenset result := '第三季度';when month >= 10 and month <= 12 thenset result := '第四季度';elseset result := '非法参数';end case ;select concat('您输入的月份为: ',month, ', 所属的季度为: ',result);
end;call p6(16);

3.4 while

while 循环是有条件的循环控制语句。满足条件后,再执行循环体中的SQL语句。具体语法为:

-- 先判定条件,如果条件为true,则执行逻辑,否则,不执行逻辑
WHILE 条件 DOSQL逻辑...
END WHILE;

示例:

计算从1累加到n的值,n为传入的参数值。

-- A. 定义局部变量, 记录累加之后的值;
-- B. 每循环一次, 就会对n进行减1 , 如果n减到0, 则退出循环
create procedure p7(in n int)
begindeclare total int default 0;while n>0 doset total := total + n;set n := n - 1;end while;select total;
end;call p7(100);

3.4 repeat

repeat是有条件的循环控制语句, 当满足until声明的条件的时候,则退出循环 。具体语法为:

-- 先执行一次逻辑,然后判定UNTIL条件是否满足,如果满足,则退出。如果不满足,则继续下一次循环
REPEATSQL逻辑...UNTIL 条件
END REPEAT;

示例:

计算从1累加到n的值,n为传入的参数值。(使用repeat实现)

-- A. 定义局部变量, 记录累加之后的值;
-- B. 每循环一次, 就会对n进行-1 , 如果n减到0, 则退出循环
create procedure p8(in n int)
begindeclare total int default 0;repeatset total := total + n;set n := n - 1;until n <= 0end repeat;select total;
end;call p8(10);
call p8(100);

3.5 loop

LOOP 实现简单的循环,如果不在SQL逻辑中增加退出循环的条件,可以用其来实现简单的死循环。

LOOP可以配合一下两个语句使用:

  • LEAVE :配合循环使用,退出循环。
  • ITERATE:必须用在循环中,作用是跳过当前循环剩下的语句,直接进入下一次循环。
[begin_label:] LOOPSQL逻辑...
END LOOP [end_label];LEAVE label; -- 退出指定标记的循环体
ITERATE label; -- 直接进入下一次循环

上述语法中出现的 begin_label, end_label, label 指的都是我们所自定义的标记。

示例一:

-- A. 定义局部变量, 记录累加之后的值;
-- B. 每循环一次, 就会对n进行-1 , 如果n减到0, 则退出循环 ----> leave xx
create procedure p9(in n int)
begindeclare total int default 0;sum:loopif n<=0 thenleave sum;if;set total := total + n;set n := n - 1;end loop sum;select total;
end;call p9(100);

示例二:

计算从1到n之间的偶数累加的值,n为传入的参数值。

-- A. 定义局部变量, 记录累加之后的值;
-- B. 每循环一次, 就会对n进行-1 , 如果n减到0, 则退出循环 ----> leave xx
-- C. 如果当次累加的数据是奇数, 则直接进入下一次循环. --------> iterate xx
create procedure p10(in n int)
begindeclare total int default 0;sum:loopif n<=0 thenleave sum;end if;if n%2 = 1 thenset n := n - 1;iterate sum;end if;set total := total + n;set n := n - 1;end loop sum;select total;
end;call p10(100);

4. 存储结构

4.1 游标

游标(CURSOR)是用来存储查询结果集的数据类型 , 在存储过程和函数中可以使用游标对结果集进行循环的处理。游标的使用包括游标的声明、OPENFETCH CLOSE,其语法分别如下。

  1. 声明游标

    DECLARE 游标名称 CURSOR FOR 查询语句 ;
    
  2. 打开游标

    OPEN 游标名称 ;
    
  3. 获取游标记录

    FETCH 游标名称 INTO 变量 [, 变量 ] ;
    
  4. 关闭游标

    CLOSE 游标名称 ;
    

案例演示:

根据传入的参数uage,来查询用户表tb_user中,所有的用户年龄小于等于uage的用户姓名(name)和专业(profession),并将用户的姓名和专业插入到所创建的一张新表(id,name,profession) 中。

其代码如下:

-- 逻辑:
-- A. 声明游标, 存储查询结果集
-- B. 准备: 创建表结构
-- C. 开启游标
-- D. 获取游标中的记录
-- E. 插入数据到新表中
-- F. 关闭游标
create procedure p11(in uage int)
begindeclare uname varchar(100);declare upro varchar(100);declare u_cursor cursor for select name,profession from tb_user where age <= uage;drop table if exists tb_user_pro;create table if not exists tb_user_pro(id int primary key auto_increment,name varchar(100),profession varchar(100));open u_cursor;while true dofetch u_cursor into uname,upro;insert into tb_user_pro values (null, uname, upro);end while;close u_cursor;
end;call p11(30);

上述的存储过程,最终我们在调用的过程中,会报错,之所以报错是因为上面的while循环中,并没有退出条件。当游标的数据集获取完毕之后,再次获取数据,就会报错,从而终止了程序的执行。

在这里插入图片描述

但是此时,tb_user_pro表结构及其数据都已经插入成功了,我们可以直接刷新表结构,检查表结构中的数据。

在这里插入图片描述

上述的功能,虽然我们实现了,但是逻辑并不完善,而且程序执行完毕,获取不到数据,数据库还报错。 接下来,我们就需要来完成这个存储过程,并且解决这个问题。

要想解决这个问题,就需要通过MySQL中提供的 条件处理程序 Handler 来解决。

4.2 条件处理程序

条件处理程序(Handler)可以用来定义在流程控制结构执行过程中遇到问题时相应的处理步骤。具体语法为:

DECLARE handler_action HANDLER FOR condition_value [, condition_value] ... statement ;handler_action 的取值:CONTINUE: 继续执行当前程序EXIT: 终止执行当前程序condition_value 的取值:SQLSTATE sqlstate_value: 状态码,如 02000-- 状态码简写SQLWARNING: 所有以01开头的SQLSTATE代码的简写NOT FOUND: 所有以02开头的SQLSTATE代码的简写SQLEXCEPTION: 所有没有被SQLWARNING 或 NOT FOUND捕获的SQLSTATE代码的简写

代码演示:

我们继续来完成在上一小节提出的这个需求,并解决其中的问题。
根据传入的参数uage,来查询用户表tb_user中,所有的用户年龄小于等于uage的用户姓名(name)和专业(profession),并将用户的姓名和专业插入到所创建的一张新表 (id,name,profession)中。

  • 通过SQLSTATE指定具体的状态码

    -- 逻辑:
    -- A. 声明游标, 存储查询结果集
    -- B. 准备: 创建表结构
    -- C. 开启游标
    -- D. 获取游标中的记录
    -- E. 插入数据到新表中
    -- F. 关闭游标
    create procedure p11(in uage int)
    begindeclare uname varchar(100);declare upro varchar(100);declare u_cursor cursor for select name,profession from tb_user where age <= uage;-- 声明条件处理程序 : 当SQL语句执行抛出的状态码为02000时,将关闭游标u_cursor,并退出declare exit handler for SQLSTATE '02000' close u_cursor;drop table if exists tb_user_pro;create table if not exists tb_user_pro(id int primary key auto_increment,name varchar(100),profession varchar(100));open u_cursor;while true dofetch u_cursor into uname,upro;insert into tb_user_pro values (null, uname, upro);end while;close u_cursor;
    end;
    call p11(30);
    
  • 通过SQLSTATE的代码简写方式 NOT FOUND

    02 开头的状态码,代码简写为 NOT FOUND。

    create procedure p12(in uage int)
    begindeclare uname varchar(100);declare upro varchar(100);declare u_cursor cursor for select name,profession from tb_user where age <=uage;-- 声明条件处理程序 : 当SQL语句执行抛出的状态码为02开头时,将关闭游标u_cursor,并退出declare exit handler for not found close u_cursor;drop table if exists tb_user_pro;create table if not exists tb_user_pro(id int primary key auto_increment,name varchar(100),profession varchar(100));open u_cursor;while true dofetch u_cursor into uname,upro;insert into tb_user_pro values (null, uname, upro);end while;close u_cursor;
    end;
    call p12(30);
    

4.3 存储函数

存储函数是有返回值的存储过程,存储函数的参数只能是IN类型的。具体语法如下:

CREATE FUNCTION 存储函数名称 ([ 参数列表 ])
RETURNS type [characteristic ...]
BEGIN-- SQL语句RETURN ...;
END ;

characteristic 说明:

  • DETERMINISTIC:相同的输入参数总是产生相同的结果

  • NO SQL :不包含 SQL 语句。

  • READS SQL DATA:包含读取数据的语句,但不包含写入数据的语句。

代码演示:

计算从1累加到n的值,n为传入的参数值。

create function fun1(n int)
returns int deterministic
begindeclare total int default 0;while n>0 doset total := total + n;set n := n - 1;end while;return total;
end;select fun1(50);

在mysql8.0版本中binlog默认是开启的,一旦开启了,mysql就要求在定义存储过程时,需要指定characteristic特性,否则就会报如下错误:

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

VMware安装银河麒麟高级服务器操作系统V10

目标 VMware安装银河麒麟高级服务器操作系统V10背景介绍环境准备安装步骤配置VM虚拟机系统安装 VMware安装银河麒麟高级服务器操作系统V10 背景介绍 近期&#xff0c;随着国产信创的持续发热和大众关注度的上升&#xff0c;我们公司决定与时俱进&#xff0c;针对国产技术趋势…

selenium教程 —— css定位

说明&#xff1a;本篇博客基于selenium 4.1.0 selenium-css定位 element_css driver.find_element(By.CSS_SELECTOR, css表达式) 复制代码 css定位说明 selenium中的css定位&#xff0c;实际是通过css选择器来定位到具体元素&#xff0c;css选择器来自于css语法 css定位优点…

优雅而高效——立即执行函数表达式()();

&#x1f606;博主&#xff1a;小猫娃来啦 &#x1f606;文章核心&#xff1a;优雅而高效——立即执行函数表达式()(); 文章目录 前言立即执行函数表达式的定义和特点立即执行函数表达式的应用场景封装私有变量和方法避免全局变量污染模块化开发 立即执行函数表达式的写法和示例…

pinia下载使用时报错如何解决?

报错 可能是因为pnpm下载的时候版本出现了问题 更新pnpm的版本 一、windowr打开终端 输入pnpm -v检查是否是最新版本 如果是8.6.2的话 就更新 更新步骤如下&#xff1a; 二&#xff1a;打开pnpm下载的网盘位置 我的是在c盘 找到里面的用户文件夹 点击选择dell里面的App data文…

【AI视野·今日Sound 声学论文速览 第二十六期】Mon, 16 Oct 2023

AI视野今日CS.Sound 声学论文速览 Mon, 16 Oct 2023 Totally 7 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Sound Papers Low-latency Speech Enhancement via Speech Token Generation Authors Huaying Xue, Xiulian Peng, Yan Lu现有的基于深度学习的语音增强…

数字孪生技术在智慧城市应用的推进建议

&#xff08;一&#xff09;坚持需求牵引&#xff0c;强场景重实效 必须始终坚持以人为本、场景导向、需求牵引&#xff0c;站在供给侧结构性改革的角度&#xff0c;突出以用促建&#xff0c;强调建用并重&#xff0c;真正发挥数字孪生城市应用建设的实效。从构建数字孪生创新…

分布式内存计算Spark环境部署与分布式内存计算Flink环境部署

目录 分布式内存计算Spark环境部署 1. 简介 2. 安装 2.1【node1执行】下载并解压 2.2【node1执行】修改配置文件名称 2.3【node1执行】修改配置文件&#xff0c;spark-env.sh 2.4 【node1执行】修改配置文件&#xff0c;slaves 2.5【node1执行】分发 2.6【node2、no…

Linux知识点 -- 高级IO(二)

Linux知识点 – 高级IO&#xff08;二&#xff09; 文章目录 Linux知识点 -- 高级IO&#xff08;二&#xff09;一、IO多路转接 -- poll1.poll接口2.poll实现3.poll优缺点 二、IO多路转接 -- epoll1.epoll接口2.epoll的工作原理3.epoll服务器实现4.epoll的优点5.epoll的工作模式…

Django REST Framework完整教程-认证与权限-JWT的使用

文章目录 1.认证(Authentication)与权限(Permission)1.1.视图添加权限1.2.登录验证1.3.常用DRF自带权限类1.4.自定义权限类1.5.全局权限1.6.函数视图权限 2.认证详解2.1.认证方案2.2.如何使用TokenAuthentication&#xff1f; 3.JSON Web Token(JWT)认证3.1.工作原理3.2.安装3.…

Java学习笔记(四)——程序控制结构

一、顺序控制 二、分支控制 &#xff08;一&#xff09;单分支 &#xff08;二&#xff09;双分支 &#xff08;三&#xff09;多分支 &#xff08;四&#xff09;嵌套分支 &#xff08;五&#xff09;switch分支结构 &#xff08;六&#xff09;if和switch的选择 三、循…

Megatron-LM GPT 源码分析(一) Tensor Parallel分析

引用 本文基于开源代码 https://github.com/NVIDIA/Megatron-LM &#xff0c;通过GPT的模型运行示例&#xff0c;从三个维度 - 模型结构、代码运行、代码逻辑说明 对其源码做深入的分析。 Tensor Parallel源码分析

uniapp(uncloud) 使用生态开发接口详情4(wangeditor 富文本, 云对象, postman 网络请求)

wangeditor 官网: https://www.wangeditor.com/v4/pages/01-%E5%BC%80%E5%A7%8B%E4%BD%BF%E7%94%A8/01-%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8.html 这里用vue2版本,用wangeditor 4 终端命令: npm i wangeditor --save 开始使用 在项目pages > sy_news > add.vue 页面中…

免密码方式获取Hive元数据

前言 开发中可能用到hive的元数据信息 ,如获取hive表列表、hive表字段、hive表数据量大小、hive表文件大小等信息,要想获取hive元数据信息即需要hive元数据库的账号及密码,此次提供的是一种不需要hive元数据库密码及可获取元数据信息的方式,且此种方式是只读 组件:hive …

程序员必备的IP查询工具

shigen坚持日更的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。坚持记录和分享从业两年以来的技术积累和思考&#xff0c;不断沉淀和成长。 hello&#xff0c;今天shigen给大家分享一下如何优雅的查询IP的工具。我们先看一下效果&a…

CSS的美化(文字、背景) Day02

一、文字控制属性 分为&#xff1a;字体样式属性 、文本样式属性 1.1 CSS字体样式属性 1.color定义元素内文字颜色2.font-size 字号大小3 font-family 字体4 font-weight 字体粗细5.font-style 字体风格6.font 字体综合属性 1.1.1 > 文字颜色 color 属性名: color color …

序列化和反序列化指令在PLC通信上的应用

在了解本篇博客之前,大家可以熟悉下序列化指令的相关介绍,详细内容如下: 博途PLC 1200/1500 PLC 序列化和反序列化指令编程应用_博图序列化和反序列化-CSDN博客序列化最重要的作用:在传递和保存对象时.保证对象的完整性和可传递性。对象转换为有序字节流,以便在网络上传输…

在 Python 脚本中设置环境变量

环境变量是与系统进程交互的一种深入方式&#xff1b; 它允许用户获得有关系统属性、路径和已经存在的变量的更详细信息。 我们如何使用环境变量 如上所述&#xff0c;环境变量促使我们与系统进程进行交互。 我们可以使用环境变量来访问系统中的所有变量和键。 为此&#xff…

6 个可解锁部分 GPT-4 功能的 Chrome 扩展(无需支付 ChatGPT Plus 费用)

在过去的几个月里&#xff0c;我广泛探索了 ChatGPT 的所有可用插件。在此期间&#xff0c;我发现了一些令人惊叹的插件&#xff0c;它们改进了我使用 ChatGPT 的方式&#xff0c;但现在&#xff0c;我将透露一些您需要了解的内容。 借助 Chrome 扩展程序&#xff0c;所有 Chat…

Windows:VS Code IDE安装ESP-IDF【保姆级】

物联网开发学习笔记——目录索引 Visual Studio Code&#xff08;简称“VS Code”&#xff09;是Microsoft向开发者们提供的一款真正的跨平台编辑器。 参考&#xff1a; VS Code官网&#xff1a;Visual Studio Code - Code Editing. Redefined 乐鑫官网&#xff1a;ESP-IDF…