MYSQL十、MYSQL的存储过程和触发器的基本认识

news2024/11/25 0:49:39

存储过程

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

    • 存储过程思想上很简单,其实就是数据库 SQL 语言层面的代码封装与重用
  2. 存储过程的特点:

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

1、存储过程的基本语法

  • 创建存储过程
CREATE  PROCEDURE   存储过程名称 ([ 参数列表 ])
BEGIN
	-- SQL语句
END ;
  • 创建例子:
-- 创建一个名为p1的存储过程,无参的
create procedure p1()
 begin
    select count(*) from student;
 end;
  • 调用存储过程
 CALL  名称  ([ 参数 ]); 
  • 调用的例子:
-- 调用p1存储过程
call p1();
  • 查看存储过程
-- 查询指定数据库的存储过程及状态信息
 SELECT * FROM INFORMATION_SCHEMA.ROUTINES WHERE ROUTINE_SCHEMA = 'xxx';  

-- 查询某个存储过程的定义
SHOW  CREATE  PROCEDURE   存储过程名称 ;  
  • 查看存储过程的例子
-- 查看dadao数据库的存储过程和状态信息
select * from information_schema.ROUTINES where ROUTINE_SCHEMA = 'dadao';

-- 查询p1存储过程的定义
show create procedure p1;
  • 删除存储过程
DROP  PROCEDURE   [ IF EXISTS ]  存储过程名称 ;
  • 删除存储过程的例子
-- 删除存储过程p1
drop procedure if exists p1;
  • 在命令行中,执行创建存储过程的SQL时,需要通过关键字 delimiter 指定SQL语句的结束符

2、变量

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

系统变量

  1. 系统变量是MySQL服务器提供,不是用户定义的,属于服务器层面。分为全局变量(GLOBAL)会话变量(SESSION)
  • 查看系统变量的语法:
-- 查看所有系统变量
 SHOW  [ SESSION | GLOBAL ]   VARIABLES ;   
       
-- 可以通过LIKE模糊匹配方式查找变量           
SHOW  [ SESSION | GLOBAL ]   VARIABLES  LIKE  '......';    

--  查看指定变量的值
SELECT  @@[SESSION. | GLOBAL.]系统变量名;                  
  • 查看系统变量的例子:
-- 查看所有的系统变量
show variables;

-- 查看所有的全局系统变量
show session variables

-- 查看所有的会话系统变量
show session variables ;

-- 进行模糊匹配
show session variables like 'auto%';
show global variables like 'auto%';

# 查看指定的系统变量,两个@@表示要查看系统变量,@@系统变量名
select @@autocommit;

 select @@global.autocommit;
 select @@session.autocommit;
  • 设置系统变量的语法
SET  [ SESSION | GLOBAL ]   系统变量名 =; 

SET  @@[SESSION. | GLOBAL.]系统变量名 =; 
  • 设置系统变量例子:

set session autocommit = 1;

# 设置指定变量的值
SET @@session.autocommit = 1;

set global autocommit  = 0;

  • 如果没有指定SESSION/GLOBAL,默认是SESSION,会话变量。
    • mysql服务重新启动之后,所设置的全局参数会失效,要想不失效,可以在 /etc/my.cnf 中配置
  • 全局变量(GLOBAL): 全局变量针对于所有的会话
  • 会话变量(SESSION): 会话变量针对于单个会话,在另外一个会话窗口就不生效了

用户自定义变量

  1. 用户定义变量 是用户根据需要自己定义的变量,用户变量不用提前声明,在用的时候直接用 “@变量名” 使用就可以。其作用域为当前连接。
  • 用户定义变量的赋值语法:
    • 赋值时,可以使用 = ,也可以使用 :=
# 方法一:直接赋值
 SET   @var_name = expr  [, @var_name = expr] ... ; 
SET   @var_name := expr  [, @var_name := expr] ... ; 

# 方法二:
SELECT   @var_name := expr  [, @var_name := expr] ... ;

# 从表名获取到的字段名的值赋值给 @var_name
SELECT  字段名  INTO @var_name  FROM  表名;
  • 赋值例子:
-- 赋值
set @myname = 'dadao';
 set @myage := 10;
 set @mygender := '男',@myhobby := 'java';
 select @mycolor := 'red';
# 从tb_user查出来的count(*)的值赋值给@mycount这个变量
 select count(*) into @mycount from tb_user;
 

  • 用户定义变量的使用(查看变量的值)语法:
 SELECT   @var_name ;
  • 使用的例子:
select @myname,@myage,@mygender,@myhobby;
 select @mycolor , @mycount;

局部变量

  1. 局部变量 是根据需要定义的在局部生效的变量,访问之前,需要DECLARE声明。可用作存储过程内的局部变量和输入参数。(局部变量的范围是在其内声明的BEGIN … END块)
  • 局部变量的声明语法:
    • 变量类型就是数据库字段类型:INT、BIGINT、CHAR、VARCHAR、DATE、TIME等
 DECLARE 变量名 变量类型 [DEFAULT ... ] ;
 # default是为变量设定默认值
  • 局部变量的声明的例子:
create procedure p2()
 begin
    declare stu_count int default 0;  # 声明一个变量
    select count(*) into stu_count from student; # 为变量stu_count赋值
    select stu_count;
 end;
  • 局部变量的赋值语法:
 SET  变量名 =;
 SET  变量名 :=;
 SELECT  字段名  INTO  变量名  FROM  表名 ... ; 
  • 局部变量的赋值的例子:
create procedure p2()
 begin
    declare stu_count int default 0;  # 声明一个变量
    select count(*) into stu_count from student; # 为变量stu_count赋值
    select stu_count;
 end;

if条件判断

  1. if条件的语法:
IF  条件1  THEN 
    .....
 ELSEIF  条件2  THEN       -- 可选
    .....
 ELSE                     -- 可选
    .....
 END  IF;
  1. 使用例子:
# score >= 85分,等级为优秀。
# score >= 60分 且 score < 85分,等级为及格。
# score < 60分,等级为不及格。
create procedure p3()
 begin
    declare score int default 58;
    declare result varchar(10);
    if score >= 85 then
        set result := '优秀';
    elseif score >= 60 then
        set result := '及格';
    else
        set result := '不及格';
    end if;
    select result;
 end;
 call p3();

参数

  1. 参数的介绍:参数的类型,主要分为以下三种:IN、OUT、INOUT。
    在这里插入图片描述
  2. 用法:
CREATE  PROCEDURE   存储过程名称 ([ IN/OUT/INOUT  参数名  参数类型 ])
 BEGIN
    -- SQL语句
END ;
  1. 使用的例子:
根据传入参数score,判定当前分数对应的分数等级,并返回。 
score >= 85分,等级为优秀。
score >= 60分 且 score < 85分,等级为及格。
score < 60分,等级为不及格。

create procedure p(in score int, out result varchar(10))
 begin
    if score >= 85 then
        set result := '优秀';
    elseif score >= 60 then
     set result := '及格';
    else
        set result := '不及格';
    end if;
end;-- 定义用户变量 @result来接收返回的数据, 用户变量可以不用声明

call p(18, @result);

select @result;

case

  1. case的两种语法格式
  • 第一种:

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

 CASE
  WHEN  search_condition1  THEN  statement_list1
  [WHEN  search_condition2  THEN  statement_list2] ...
  [ELSE  statement_list]
 END CASE;
-- 含义: 当条件search_condition1成立时,执行statement_list1,当条件search_condition2成立时,执行statement_list2, 否则就执行 statement_list
  1. 使用案例:
根据传入的月份,判定月份所属的季节(要求采用case结构)。
1-3月份,为第一季度
4-6月份,为第二季度
7-9月份,为第三季度
10-12月份,为第四季度


 create procedure p(in month int)
 begin
    declare result varchar(10);
    case
        when month >= 1 and month <= 3 then
            set result := '第一季度';
        when month >= 4 and month <= 6 then
            set result := '第二季度';
        when month >= 7 and month <= 9 then
            set result := '第三季度';
             when month >= 10 and month <= 12 then
            set result := '第四季度';
        else
            set result := '非法参数';
    end case ;
    select concat('您输入的月份为: ',month, ', 所属的季度为: ',result);
 end;

 call  p(16);

如果判定条件有多个,多个条件之间,可以使用 and 或 or 进行连接。

while

  1. while 循环是有条件的循环控制语句。满足条件后,再执行循环体中的SQL语句。具体语法为:
-- 先判定条件,如果条件为true,则执行逻辑,否则,不执行逻辑
WHILE  条件  DO
    SQL逻辑...    
END WHILE;
  1. 例子:
# 计算从1累加到n的值,n为传入的参数值。
-- A. 定义局部变量, 记录累加之后的值;-- B. 每循环一次, 就会对n进行减1 , 如果n减到0, 则退出循环
create procedure p(in n int)
 begin
    declare total int default 0;
    
    while n>0 do
    set total := total + n;
         set n := n - 1;
    end while;
    
    select total;
 end;
 
 call p(100);

repeat

  1. repeat是有条件的循环控制语句, 当满足until声明的条件的时候,则退出循环 。具体语法为:
-- 先执行一次逻辑,然后判定UNTIL条件是否满足,如果满足,则退出。如果不满足,则继续下一次循环
REPEAT
    SQL逻辑...  
    UNTIL  条件
END REPEAT;
  1. 例子:
# 计算从1累加到n的值,n为传入的参数值。(使用repeat实现)
-- A. 定义局部变量, 记录累加之后的值;-- B. 每循环一次, 就会对n进行-1 , 如果n减到0, 则退出循环
create procedure p(in n int)
 begin
    declare total int default 0;
    repeat
        set total := total + n;
        set n := n - 1;
    until  n <= 0
    end repeat;
    select total;
end;
 
call p(10);

loop

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

    • LEAVE :配合循环使用,退出循环。
    • ITERATE:必须用在循环中,作用是跳过当前循环剩下的语句,直接进入下一次循环。
  2. 语法:

 [begin_label:]  LOOP
    SQL逻辑...  
END  LOOP  [end_label];


 LEAVE  label;   -- 退出指定标记的循环体
ITERATE  label; -- 直接进入下一次循环
  1. 例子:
# 计算从1累加到n的值,n为传入的参数值。
-- A. 定义局部变量, 记录累加之后的值;
-- B. 每循环一次, 就会对n进行-1 , 如果n减到0, 则退出循环 ----> leave xx
 create procedure p(in n int)
 begin
    declare total int default 0;
    sum:loop
        if n<=0 then
            leave sum;
        end if;
			 set total := total + n;
			 set n := n - 1;
	 end loop sum;
		 select total;
 end;
 
 call p(100);

游标

  1. 介绍:游标(CURSOR)是用来存储查询结果集的数据类型 , 在存储过程和函数中可以使用游标对结果集进行循环的处理。游标的使用包括游标的声明、OPEN、FETCH 和 CLOSE,其语法分别如下:
  • 声明游标
 DECLARE   游标名称  CURSOR  FOR  查询语句 ;
  • 打开游标
 OPEN   游标名称 ;
  • 获取游标记录
 FETCH  游标名称  INTO  变量 [, 变量  ] ;
  • 关闭游标
 CLOSE   游标名称 ;
  1. 例子:
# 根据传入的参数uage,来查询用户表tb_user中,所有的用户年龄小于等于uage的用户姓名(name)和专业(profession),并将用户的姓名和专业插入到所创建的一张新表(id,name,profession)中。
-- 逻辑:
-- A. 声明游标, 存储查询结果集
-- B. 准备: 创建表结构
-- C. 开启游标
-- D. 获取游标中的记录
-- E. 插入数据到新表中
-- F. 关闭游标
create procedure p(in uage int)
 begin
	 declare 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 do
	 fetch u_cursor into uname,upro;
	 insert into tb_user_pro values (null, uname, upro);
 end while;
 
 close u_cursor;
 end;
 
 call p(30);
  • 上述的存储过程,最终我们在调用的过程中,会报错,之所以报错是因为上面的while循环中,并没有退出条件。当游标的数据集获取完毕之后,再次获取数据,就会报错,从而终止了程序的执行。
  • 但是此时,tb_user_pro表结构及其数据都已经插入成功了,我们可以直接刷新表结构,检查表结构中的数据
  • 上述的功能,虽然我们实现了,但是逻辑并不完善,而且程序执行完毕,获取不到数据,数据库还报错。 接下来,我们就需要来完成这个存储过程,并且解决这个问题。
    • 要想解决这个问题,就需要通过MySQL中提供的 条件处理程序 Handler 来解决。

条件处理程序

  1. 条件处理程序(Handler)可以用来定义在流程控制结构执行过程中遇到问题时相应的处理步骤。
  2. 语法为:
 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代码的简写
  1. 例子:
# 根据传入的参数uage,来查询用户表tb_user中,所有的用户年龄小于等于uage的用户姓名(name)和专业(profession),并将用户的姓名和专业插入到所创建的一张新表(id,name,profession)中。
  • 第一步:通过SQLSTATE指定具体的状态码
-- 逻辑:
-- A. 声明游标, 存储查询结果集
-- B. 准备: 创建表结构
-- C. 开启游标
-- D. 获取游标中的记录
-- E. 插入数据到新表中
-- F. 关闭游

create procedure p(in uage int)
 begin
	 declare 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 do
	 fetch u_cursor into uname,upro;
	 insert into tb_user_pro values (null, uname, upro);
 end while;
 
 close u_cursor;
 end;
 
 call p(30);
  • 第二步: 通过SQLSTATE的代码简写方式 NOT FOUND
    • 02 开头的状态码,代码简写为 NOT FOUND
 create procedure p(in uage int)
 begin
	 declare 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 do
	 fetch u_cursor into uname,upro;
	 insert into tb_user_pro values (null, uname, upro);
 end while;
 close u_cursor;
 end;
 
 call p(30);

存储函数(很少用,可以使用存储过程代替)

  1. 存储函数的介绍:存储函数是有返回值的存储过程,存储函数的参数只能是IN类型(即参数是输入参数)的。
  2. 语法:
CREATE  FUNCTION   存储函数名称 ([ 参数列表 ])
 RETURNS  type  [characteristic ...]
 BEGIN-- SQL语句
RETURN ...;
 END ;
  • characteristic说明:
    • DETERMINISTIC:相同的输入参数总是产生相同的结果
    • NO SQL :不包含 SQL 语句。
    • READS SQL DATA:包含读取数据的语句,但不包含写入数据的语句。
  • 在mysql8.0版本中binlog默认是开启的,一旦开启了,mysql就要求在定义存储过程时,需要指定characteristic特性,否则就会报错。
  1. 案例:
# 计算从1累加到n的值,n为传入的参数值
create function fun1(n int)
 returns int deterministic
 begin
    declare total int default 0;
    
    while n>0 do
        set total := total + n;
        set n := n - 1;
    end while;
    
    return total;
 end;
# 调用存储函数
 select fun1(50);

触发器

  1. 触发器的介绍:触发器是与有关的数据库对象,指在insert/update/delete之前(BEFORE)或之后(AFTER),触发并执行触发器中定义的SQL语句集合。
    • 触发器的这种特性可以协助应用在数据库端确保数据的完整性 , 日志记录 , 数据校验等操作 。
    • 使用别名OLD和NEW来引用触发器中发生变化的记录内容,这与其他的数据库是相似的。现在触发器还只支持行级触发支持语句级触发。
      • 行级触发(Row-Level Trigger):行级触发器在每一行数据被插入、更新或删除时都会立即执行。它们提供了一个非常细粒度的控制,允许开发者对单个数据更改做出反应。行级触发器通常用于确保数据的一致性和完整性,例如审计日志、业务规则验证等。当满足特定条件时,触发器会自动激活并执行相应的存储过程或SQL语句。
      • 语句级触发(Statement-Level Trigger):语句级触发器是在整个SQL语句执行完毕后才会执行的。这意味着它们会在一次操作(如一个INSERT、UPDATE或DELETE语句)的所有行都处理完毕后才被触发。这种触发方式更适合于执行一些全局操作,比如记录所有操作的整体效果,或者进行批量处理。语句级触发器通常比行级触发器的性能更好,因为它们减少了事务的开销。
        在这里插入图片描述
  2. 触发器语法:
CREATE  TRIGGER  trigger_name 
BEFORE/AFTER  INSERT/UPDATE/DELETE
 ON tbl_name   FOR EACH ROW  -- 行级触发器
BEGIN
 trigger_stmt ;
END;
  1. 查看触发器:
show triggers;
  1. 删除触发器:
-- 如果没有指定schema_name,默认为当前数据库
drop trigger [schema_name.]trigger_name; 

触发器案例:

  1. 通过触发器记录 tb_user 表的数据变更日志,将变更日志插入到日志表user_logs中, 包含增加, 修改 , 删除 ;
  2. 日志表的准备:
#  日志表 user_logs
 create table user_logs(
	 id int(11) not null auto_increment,
	 operation varchar(20) not null comment '操作类型, insert/update/delete',
	 operate_time datetime not null comment '操作时间',
	 operate_id int(11) not null comment '操作的ID',
	 operate_params varchar(500) comment '操作参数',
	 primary key(`id`)
 )engine=innodb default charset=utf8;
  • 插入(insert)触发器
create trigger tb_user_insert_trigger
after insert on tb_user for each row
 begin
   insert into user_logs(id, operation, operate_time, operate_id, operate_params) 
   VALUES (null, 'insert', now(), new.id, concat('插入的数据内容为: id=',new.id,',name=',new.name, ', phone=', NEW.phone, ', email=', NEW.email, ', profession=', NEW.profession));
 end;
-- 查看
show triggers ;

-- 插入数据到tb_user
 insert into tb_user(id, name, phone, email, profession, age, gender, status, createtime) VALUES (26,'大哥大','18809091212','erhuangzi@163.com','软件工程',23,'1','1',now());
  • 修改(update)触发器
create trigger tb_user_update_trigger
after update on tb_user for each row
 begin
 insert into user_logs(id, operation, operate_time, operate_id, operate_params) 
VALUES
 (null, 'update', now(), new.id,concat('更新之前的数据: id=',old.id,',name=',old.name, ', phone=', old.phone, ', email=', old.email, ', profession=', old.profession,' | 更新之后的数据: id=',new.id,',name=',new.name, ', phone=', NEW.phone, ', email=', NEW.email, ', profession=', NEW.profession));
 end;
-- 查看
show triggers ;

-- 更新
update tb_user set profession = '会计' where id = 23;
update tb_user set profession = '会计' where id <= 5;
  • 删除(delete)触发器
 create trigger tb_user_delete_trigger
 after delete on tb_user for each row
 begin
	 insert into user_logs(id, operation, operate_time, operate_id, operate_params) 
	VALUES
	 (null, 'delete', now(), old.id,concat('删除之前的数据: id=',old.id,',name=',old.name, ', phone=', old.phone, ', email=', old.email, ', profession=', old.profession));
 end;

-- 查看
show triggers ;

-- 删除数据
delete from tb_user where id = 26;

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

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

相关文章

springboot网上商城系统的设计与实现-计算机毕业设计源码08789

摘 要 随着互联网趋势的到来&#xff0c;各行各业都在考虑利用互联网将自己推广出去&#xff0c;最好方式就是建立自己的互联网系统&#xff0c;并对其进行维护和管理。在现实运用中&#xff0c;应用软件的工作规则和开发步骤&#xff0c;采用Java技术建设网上商城系统。 本设…

Selenium IED-控制已打开的Chrome浏览器

本文已收录于专栏 《自动化测试》 目录 背景介绍优势特点操作步骤总结提升 背景介绍 在我们进行自动化测试的过程中有时候会遇见一个很棘手的问题那就是登录的过程中需要图片验证码&#xff0c;图片验证码设计的初衷其实就是为了防自动化&#xff0c;防止一些人利用自动工具恶意…

蒙特卡洛算法简介及应用

文章目录 基础简介蒙特卡洛方法示例其他应用 基础简介 蒙特卡洛算法&#xff08;Monte Carlo Algorithm&#xff09;是一种基于随机抽样或统计试验的数值计算方法&#xff0c;用于求解各种数学问题&#xff0c;尤其是那些解析解难以获得或者是高维度的积分问题。这种方法的核心…

浏览器断点调试(用图说话)

浏览器断点调试&#xff08;用图说话&#xff09; 1、开发者工具2、添加断点3、查看变量值 浏览器断点调试 有时候我们需要在浏览器中查看 html页面的js中的变量值。1、开发者工具 打开浏览器的开发者工具 按F12 &#xff0c;没反应的话按FnF12 2、添加断点 3、查看变量值

手慢无!限量奶茶免费领,千元大奖组队赢!

&#x1f680; AI 卡片大作战全新启动&#xff01;&#xff01;&#x1f552; 限时两周&#xff0c;组队狂欢&#xff01;&#x1f46b; 邀请好友&#xff0c;解锁免费奶茶福利&#xff01;&#x1f4b0; 学习卡片&#xff0c;赢取 1888 超级现金大奖心动不如行动&#xff0c;快…

搜维尔科技:「研讨会」惯性动捕技术在工效学领域应用研讨会

Movella将于7月2日&#xff08;周二&#xff09;下午2点举行主题为惯性动捕技术在工效学领域应用的研讨会。来自Movella的伙伴赋能经理Jeffrey Muller作为嘉宾出席&#xff0c;届时主讲人将为大家带来Xsens惯性动捕技术在工效学领域的应用分享。同时&#xff0c;研讨会还邀请多…

C++编程(二)引用

文章目录 一、C中的引用&#xff08;一&#xff09;引用1. 语法格式2. 作用3. 注意事项 &#xff08;二&#xff09;常引用2. 其他场景 &#xff08;三&#xff09;引用和函数结合使用1. 引用可以作为函数的参数2. 引用可以作为函数的返回值 &#xff08;四&#xff09;引用和指…

用final和loombok来实现依赖注入

在Java中&#xff0c;RequiredArgsConstructor 是一个由 Lombok 库提供的注解&#xff0c;它能够自动为类生成一个构造函数&#xff0c;该构造函数包含所有被标记为 final 或者非 final 但在类中没有默认值的字段。这个注解特别适用于当你需要一个构造函数来初始化所有字段&…

Android 14 权限等级剖析

Android 14 权限等级剖析 Android 14 引入了新的权限等级&#xff0c;为应用程序访问敏感信息和功能提供了更细粒度的控制。了解这些新的权限等级及其应用场景对于开发人员至关重要。 1. 概述 Android 一直以来都使用权限机制来控制应用程序对系统资源和用户数据的访问。随着…

第三十篇——等价性:如何从等价信息里找答案?

目录 一、背景介绍二、思路&方案三、过程1.思维导图2.文章中经典的句子理解3.学习之后对于投资市场的理解4.通过这篇文章结合我知道的东西我能想到什么&#xff1f; 四、总结五、升华 一、背景介绍 知道了等价性的逻辑&#xff0c;通过等价性去衡量事物&#xff0c;像是给…

如何验证Rust中的字符串变量在超出作用域时自动释放内存?

讲动人的故事,写懂人的代码 在公司内部的Rust培训课上,讲师贾克强比较了 Rust、Java 和 C++ 三种编程语言在变量越过作用域时自动释放堆内存的不同特性。 Rust 通过所有权系统和借用检查,实现了内存安全和自动管理,从而避免了大部分内存泄漏。Rust 自动管理标准库中数据类…

Vue3学习笔记<->开发环境安装

背景 公司开始做产品开发&#xff0c;前端就选择使用了vue&#xff0c;替换了传统的jsp。公司要求每个开发人员都要前后端都可以开发&#xff0c;于是就开始学习vue了。 安装环境 安装node.js node.js下载地址&#xff1a;node.js下载地址 安装&#xff1a;选在安装路径&…

晶方科技:台积电吃饱,封装迎春?

半导体产业链掀起涨价潮&#xff0c;先进封装迎接利好。 这里我们来聊国内先进封装企业——晶方科技。 近期&#xff0c;由于产能供不应求&#xff0c;台积电决定上调先进封装产品价格&#xff0c;还表示订单已经排到2026年。 大哥吃不下了&#xff0c;剩下的订单全都是空间。…

【golang学习之旅】复杂数据类型——指针 函数

系列文章 【golang学习之旅】使用VScode安装配置Go开发环境 【golang学习之旅】报错&#xff1a;a declared but not used 【golang学习之旅】Go 的基本数据类型 【golang学习之旅】深入理解字符串string数据类型 【golang学习之旅】go mod tidy 【golang学习之旅】记录一次 p…

【嵌入式Linux】<总览> 进程间通信(更新中)

文章目录 前言 一、管道 1. 概念 2. 匿名管道 3. 有名管道 二、内存映射区 1. 概念 2. mmap函数 3. 进程间通信&#xff08;有血缘关系&#xff09; 4. 进程间通信&#xff08;没有血缘关系&#xff09; 5. 拷贝文件 前言 在文章【嵌入式Linux】&#xff1c;总览&a…

RAID详解及配置实战

目录 一、RAID磁盘阵列及详解 1.1 了解RAID 1.1.1 简单理解 1.1.2 对比了解 1.2 RAID磁盘阵列介绍 1.3 RAID功能实现 1.4 RAID实现的方式 1.5 RAID级别详解 1.5.1 RAID -0 1.5.2 RAID -1 1.5.3 RAID -5 1.5.4 RAID -10&#xff08;RAID 10&#xff09; 1.6 阵列卡…

2024年最新通信安全员考试题库,随时在线刷题

46.劳动防护用品不同于一般的商品&#xff0c;直接涉及到劳动者的生命安全和身体健康&#xff0c;故生产经营单位为从业人员提供的劳动防护用品必须符合&#xff08; &#xff09;或行业标准。 A.地方标准 B.国家标准 C.消防标准 D.LA劳安认证 答案:B 47.矿山、金属冶炼、…

本地可以Run大模型吗?Llama3?安排!

➡️ 前言 本地可以跑大模型吗? ChatGPT发布之后&#xff0c;引起了AI领域剧烈震动&#xff0c;从2023年3月百度发布新一代大预言模型文心一言开始&#xff0c;大模型如雨后春笋般不断涌现&#xff0c;国内阿里巴巴的通义千问、华为的盘古大模型、科大讯飞的星火认知大模型、…

大学网页制作作品1

作品须知&#xff1a;1.该网页作品预计分为5个页面&#xff08;其中1个登录页面&#xff0c;1个首页主页面&#xff0c;3个分页面&#xff09;&#xff0c;如需要可自行删改增加页面。&#xff08;总共约800行html,1200行css,100行js&#xff09; 2.此网页源代码只用于学习和模…

面相对象程序设计

面相对象程序设计包含内容如下 局域网聊天程序设网页浏览器设计电子日历记事本的设计 以其中的一个的报告进行举例 1需求与总体设计 1 1.1需求分析 1 1.2总体设计方案 1 1.2&#xff0e;1系统功能分析以及功能表 1 1.3系统类图的关系以及表之间的联系 2 2详细设计 3 2.1 Manag…