第8步---MySQL的存储过程和触发器

news2024/11/25 1:39:46

第8步---MySQL的存储过程和触发器

 1.存储过程

5开始支持的

sql集,类似Java中的代码中的方法

实现对sql的封装和服用

有输入和输出

可以声明变量

可以实现一下复杂的控制语句

1.1入门案例

基本语法

 测试数据

-- 创建表的测试数据
create table dept(
	deptno int primary key,
  dname varchar(20),
	loc varchar(20)
);
insert into dept values(10, '教研部','北京'),
(20, '学工部','上海'),
(30, '销售部','广州'),
(40, '财务部','武汉');

create table emp(
	empno int primary key,
	ename varchar(20),
	job varchar(20),
	mgr int,
	hiredate date,
	sal numeric(8,2),
	comm numeric(8, 2),
	deptno int,
-- 	FOREIGN KEY (mgr) REFERENCES emp(empno),
	FOREIGN KEY (deptno) REFERENCES dept(deptno) ON DELETE SET NULL ON UPDATE CASCADE
);
insert into emp values
(1001, '甘宁', '文员', 1013, '2000-12-17', 8000.00, null, 20),
(1002, '黛绮丝', '销售员', 1006, '2001-02-20', 16000.00, 3000.00, 30),
(1003, '殷天正', '销售员', 1006, '2001-02-22', 12500.00, 5000.00, 30),
(1004, '刘备', '经理', 1009, '2001-4-02', 29750.00, null, 20),
(1005, '谢逊', '销售员', 1006, '2001-9-28', 12500.00, 14000.00, 30),
(1006, '关羽', '经理', 1009, '2001-05-01', 28500.00, null, 30),
(1007, '张飞', '经理', 1009, '2001-09-01', 24500.00, null, 10),
(1008, '诸葛亮', '分析师', 1004, '2007-04-19', 30000.00, null, 20),
(1009, '曾阿牛', '董事长', null, '2001-11-17', 50000.00, null, 10),
(1010, '韦一笑', '销售员', 1006, '2001-09-08', 15000.00, 0.00, 30),
(1011, '周泰', '文员', 1008, '2007-05-23', 11000.00, null, 20),
(1012, '程普', '文员', 1006, '2001-12-03', 9500.00, null, 30),
(1013, '庞统', '分析师', 1004, '2001-12-03', 30000.00, null, 20),
(1014, '黄盖', '文员', 1007, '2002-01-23', 13000.00, null, 10);

create table salgrade(
	grade int primary key,
	losal int,
	hisal int
);
insert into salgrade values
(1, 7000, 12000),
(2, 12010, 14000),
(3, 14010, 20000),
(4, 20010, 30000),
(5, 30010, 99990);

存储过程创建

-- =============================存储过程==================
-- 创建存储过程
delimiter $$
CREATE PROCEDURE  proc01()
BEGIN
SELECT empno,ename FROM emp;
END $$
delimiter ;

-- 调用存储过程
call proc01();

 

 1.2局部变量

用户自定在beigin和end中是有效的

基本语法

DECLARE 变量名称 数据类型 DEFAULT '默认值';
DECLARE var_name01 VARCHAR(20) DEFAULT '默认值';

set方式赋值

-- 用户变量
delimiter $$
CREATE PROCEDURE  proc02()
BEGIN
DECLARE var_name01 VARCHAR(20) DEFAULT '默认值';
SET var_name01='张三';
SELECT var_name01;
END $$
delimiter ;

-- 调用存储过程
call proc02();

 insert into的方式赋值

-- 采用insert into的方式赋值
delimiter $$
CREATE PROCEDURE  proc03()
BEGIN
DECLARE var_name01 VARCHAR(20) DEFAULT '默认值';
SELECT ename into var_name01 FROM emp WHERE empno='1001';
SELECT var_name01;

END $$
delimiter ;

-- 调用存储过程
call proc03();

 注意只能是一行的数据,要是多行的话就会出现错误了,要是那样的话就会出现错误.

 

1.3会话变量

当连接的时候一直有效的变量


-- 会话变量
DROP PROCEDURE proc05;
delimiter $$
CREATE PROCEDURE  proc05()
BEGIN
set @var_name='张伞';
SELECT @var_name;
END $$
delimiter ;

-- 调用存储过程
call proc05();
SELECT @var_name;

 

 会话变量不仅可以在函数中可以进行使用,也是可以在函数外边进行使用的.

 

1.4系统变量

my.ini中可以存储一些系统变化.

会话变量是建立连接的时候初始化的.

所有的系统变量都会有一份会话变量的拷贝的变量.

全局会影响到整个mysql,但是会话的话只能影响到当前的会话

系统变量


-- 查看全部的全局变量
SHOW GLOBAL VARIABLES;

-- 查看某一个
SELECT @@global.auto_increment_increment  ;



-- 修改全局变量的值
SELECT @@global.sort_buffer_size  ;

set GLOBAL sort_buffer_size =262144;
set @@GLOBAL sort_buffer_size =262144;


会话变量

只需要将global改成session就可以了

-- 查看全部的会话变量
SHOW SESSION VARIABLES;

-- 查看某一个
SELECT @@SESSION.auto_increment_increment  ;



-- 修改会话变量的值
SELECT @@SESSION.sort_buffer_size  ;

set SESSION sort_buffer_size =262145;

1.5in关键字

此处的in关键字是输入参数的含义不是子查询的关键字

可以给存储过程的方法进行传递参数

仅仅在函数的内部进行使用的

-- 传入员工编号查看员工的信息
DROP PROCEDURE IF EXISTS proc07;
delimiter $$
CREATE PROCEDURE proc07(IN param_eno INT)
BEGIN

SELECT * FROM emp WHERE empno=param_eno;

END $$
delimiter ;



CALL proc07(1002);

 

-- 传入部门名和薪资,查询指定部门并且薪资大于指定值的员工信息
DROP PROCEDURE IF EXISTS proc08;
delimiter $$
CREATE PROCEDURE proc08 (IN param_dname VARCHAR(20),IN param_salary DOUBLE)-- 传入部门名喝薪资,查询指定部门并且薪资大于指定值的员工信息(IN param_eno INT)
BEGIN

SELECT * FROM dept d  JOIN  emp e ON  d.deptno=e.deptno  and  d.dname= param_dname and  e.sal>param_salary ;

END $$
delimiter ;



CALL proc08('销售部',20000);

1.6out关键字

将里面值传出去

-- ======OUT关键字
-- 传入员工的编号返回员工的名字
DROP PROCEDURE IF EXISTS proc09;
delimiter $$
CREATE PROCEDURE proc09 (IN param_eno INT ,OUT out_name VARCHAR(20))
-- 传入部门名喝薪资,查询指定部门并且薪资大于指定值的员工信息(IN param_eno INT)
BEGIN

SELECT ename into out_name FROM emp  WHERE empno =param_eno ;
END $$
delimiter ;



CALL proc09(1002,@o_name);

SELECT @o_name;

 再查看一下员工的薪资

DROP PROCEDURE IF EXISTS proc09;
delimiter $$
CREATE PROCEDURE proc09 (IN param_eno INT ,OUT out_name VARCHAR(20),OUT out_salary DECIMAL(7,2))
-- 传入部门名喝薪资,查询指定部门并且薪资大于指定值的员工信息(IN param_eno INT)
BEGIN
SELECT ename ,sal INTO out_name ,out_salary FROM emp  WHERE empno =param_eno ;
END $$
delimiter ;

CALL proc09(1002,@o_name,@o_salary);

SELECT @o_name,@o_salary;



 

1.7inout关键字

可以传入也可以传出

-- 以10倍的输出
DROP PROCEDURE IF EXISTS proc10;
delimiter $$
CREATE PROCEDURE proc10 (INOUT param_eno INT )
BEGIN
SET param_eno=param_eno*10;
END $$
delimiter ;

SET @nox=5;
CALL proc10(@nox);

SELECT  @nox;



 


-- 传入员工名字,拼接部门号,传入薪资,求出年薪
DROP PROCEDURE IF EXISTS proc11;
delimiter $$
CREATE PROCEDURE proc11 (INOUT in_ename VARCHAR(20) ,INOUT sal DOUBLE )
BEGIN
SELECT CONCAT_WS('-',deptno,ename) INTO in_ename  FROM emp WHERE emp.ename=in_ename;
SET sal=sal*12;
END $$
delimiter ;

set @e='周瑜',@s=1000;

CALL proc11(@e,@s);

SELECT @e,@s;

 

 

1.8存储过程流程控制语句

-- 传入员工名字,拼接部门号,传入薪资,求出年薪
DROP PROCEDURE IF EXISTS proc11;
delimiter $$
CREATE PROCEDURE proc11 (INOUT in_ename VARCHAR(20) ,INOUT sal DOUBLE )
BEGIN
SELECT CONCAT_WS('-',deptno,ename) INTO in_ename  FROM emp WHERE emp.ename=in_ename;
SET sal=sal*12;
END $$
delimiter ;

set @e='周瑜',@s=1000;

CALL proc11(@e,@s);

SELECT @e,@s;


-- 流程判断
-- 利用流程控制语句
DROP PROCEDURE IF EXISTS proc11;
delimiter $$
CREATE PROCEDURE proc11(IN socre INT)
BEGIN
IF socre<60 THEN
	SELECT '不及格';
ELSEIF socre>=60 AND socre <80 THEN
SELECT '及格';
 
ELSEIF socre>=80 AND socre <=100 THEN
 SELECT '优秀';
ELSE
	SELECT '天才';
END IF;
END $$
delimiter ;

CALL proc11(75);

-- 输入员工的名字,判断工资的情况
DROP PROCEDURE IF EXISTS proc12;
delimiter $$
CREATE PROCEDURE proc12(IN in_ename VARCHAR(20))
BEGIN
DECLARE in_salary DECIMAL(7,2); -- 定义一个薪资
SELECT sal into in_salary FROM emp WHERE ename=in_ename; -- 将指定员工的薪资查询出来
-- 下面进行薪资的判断
IF in_salary<10000 THEN
	SELECT '1万元以下';
ELSEIF 	in_salary<20000  THEN
	SELECT '2万元以下,1万元以上';
ELSE
	SELECT '2万元以上';
END IF;

END $$
delimiter ;

CALL proc12('张飞');

CALL proc12('甘宁');

1.9分支语句

case在存储过程中的使用

和if差不多,类似Java中的switch。

语法格式有两种

其中一种是数值的匹配,还有一种是单纯的进行表达式的判断的结构的。

 

-- =======case分支语句============================
DROP PROCEDURE IF EXISTS proc13;
delimiter $$
CREATE PROCEDURE proc13(IN pay_type int)
BEGIN
CASE pay_type
	WHEN  1 THEN
		SELECT '支付宝';
	WHEN  2 THEN
		SELECT '微信支付';
	ELSE
		SELECT '未知支付方式';
END CASE;
END $$
delimiter ;

call proc13(1);

采用第二种语法格式实现的

DROP PROCEDURE IF EXISTS proc14;
delimiter $$
CREATE PROCEDURE proc14(IN pay_type int)
BEGIN
CASE 
	WHEN  pay_type=1  THEN
		SELECT '支付宝';
	WHEN  pay_type=2 THEN
		SELECT '微信支付';
	ELSE
		SELECT '未知支付方式';
END CASE;
END $$
delimiter ;

call proc14(1);

 

1.10循环语句

MySQL中的循环的方式

MySQL中的循环的方式

while
repeat
loop
循环跳出
leave 类似break,跳出当前的循环
iterate 和continue,结束本次循环

1.11while循环

语法格式

 创建下面的表

CREATE TABLE `t_user` (
  `uid` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
  `password` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
  PRIMARY KEY (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

循环插入line条数据

-- =================================循环语句============================
-- 循环插入line条数据
DROP PROCEDURE IF EXISTS proc15;
delimiter $$
CREATE PROCEDURE proc15( IN line INT )
BEGIN
DECLARE i INT DEFAULT 1;
WHILE i<=line DO
	INSERT INTO t_user(name,password) VALUES (CONCAT('张',i),'123456');
	SET i=i+1;
END WHILE;
END $$
delimiter ;

call proc15(5);

 加入对应的循环控制的操作

-- 加上基本的流程控制语句

DROP PROCEDURE IF EXISTS proc15;
delimiter $$
CREATE PROCEDURE proc15( IN line INT )
BEGIN
DECLARE i INT DEFAULT 1;
label:WHILE i<=line DO
	INSERT INTO t_user(name,password) VALUES (CONCAT('张',i),'123456');
	IF i=5 THEN
		LEAVE label;
	end IF;
	SET i=i+1;
END WHILE label;
END $$
delimiter ;

call proc15(5);

 要是解决这个死循环的操作的话可以把+1的操作放在前面进行操作。这样就不吹出现死循环的操作了。

1.12repeat循环操作

-- repeat的操作
DROP PROCEDURE IF EXISTS proc16;
delimiter $$
CREATE PROCEDURE proc16( IN line INT )
BEGIN
DECLARE i INT DEFAULT 10;
label:REPEAT
	INSERT INTO t_user(name,password) VALUES (CONCAT('张',i),'123456');
	SET i=i+1;
	UNTIL i>=line -- 跳出循环的操作
END REPEAT label;

END $$
delimiter ;

call proc16(15);

上面的操作会插入5条数据。

1.13loop循环


-- loop操作
DROP PROCEDURE IF EXISTS proc17;
delimiter $$
CREATE PROCEDURE proc17( IN line INT )
BEGIN
DECLARE i INT DEFAULT 1;
label:LOOP
	INSERT INTO t_user(name,password) VALUES (CONCAT('赵',i),'123456');
	SET i=i+1;
	if i>line
	THEN 
	LEAVE label;
	END IF;
	-- 跳出循环的操作
END LOOP label;

END $$
delimiter ;

call proc17(5);

1.14游标

存储查询结果,对查询的结果进行额外的处理的,是相当于多行的数据的,不是单行的数据的。

下面不是完整的操作

  • 下面的操作只能获取一行的数据

OPEN my_cursor;

-- 获取数据 执行一次获取一行的数据
FETCH my_cursor into  var_empno,var_empname,var_sal;
SELECT var_empno,var_empname,var_sal;

-- 关闭游标
CLOSE my_cursor;

可以采用循环的操作实现游标数据的读取的操作

-- ===================游标操作====================
-- 输入部门名查询这个部门的员工的详细的信息
DROP PROCEDURE IF EXISTS proc18;
delimiter $$
CREATE PROCEDURE proc18( IN in_name VARCHAR(50) )
BEGIN

-- 局部变量
DECLARE var_empno int;
DECLARE var_empname VARCHAR(50);
DECLARE var_sal DECIMAL(7,2);

-- 声明游标
DECLARE my_cursor CURSOR FOR 
SELECT empno,ename,sal
FROM  emp e JOIN dept d ON d.deptno=e.deptno and  d.dname=in_name;

-- 打开游标
OPEN my_cursor;
label:LOOP

-- 获取数据 执行一次获取一行的数据
FETCH my_cursor into  var_empno,var_empname,var_sal;
SELECT var_empno,var_empname,var_sal;

END LOOP label;


-- 关闭游标
CLOSE my_cursor;

END $$ ;
delimiter ;

call proc18('销售部');





上面的代码是存在问题的,虽然可以实现展示全部的数据但是展示的全部的数据是有问题的,有些数据并不是我们想要展示的。存在错误。

1.15句柄操作

解决读取到最后一行数据的操作

其实就是类似一种异常操作的处理

有三种执行的方式

  • 继续执行

  • 停止执行

  • 不执行

出现错误有错误码。错误的名字等信息。

-- ===================游标操作====================
-- 输入部门名查询这个部门的员工的详细的信息
DROP PROCEDURE IF EXISTS proc18;
delimiter $$
CREATE PROCEDURE proc18( IN in_name VARCHAR(50) )
BEGIN

-- 局部变量
DECLARE var_empno int;
DECLARE var_empname VARCHAR(50);
DECLARE var_sal DECIMAL(7,2);

-- 声明游标
DECLARE my_cursor CURSOR FOR 
SELECT empno,ename,sal
FROM  emp e JOIN dept d ON d.deptno=e.deptno and  d.dname=in_name;

-- 打开游标
OPEN my_cursor;
label:LOOP

-- 获取数据 执行一次获取一行的数据
FETCH my_cursor into  var_empno,var_empname,var_sal;
SELECT var_empno,var_empname,var_sal;

END LOOP label;


-- 关闭游标
CLOSE my_cursor;

END $$ ;
delimiter ;

call proc18('销售部');



-- 句柄操作
DROP PROCEDURE IF EXISTS proc18;
delimiter $$
CREATE PROCEDURE proc18( IN in_name VARCHAR(50) )
BEGIN

-- 局部变量
DECLARE var_empno int;
DECLARE var_empname VARCHAR(50);
DECLARE var_sal DECIMAL(7,2);
DECLARE flag INT DEFAULT 1; -- 定义一个标志


-- 声明游标
DECLARE my_cursor CURSOR FOR 
SELECT empno,ename,sal
FROM  emp e JOIN dept d ON d.deptno=e.deptno and  d.dname=in_name;

-- 定义异常的处理的方式
-- 出现问题了该怎么做,是继续进行执行还是终止exit,还是undo不支持
-- 触发的条件
-- 异常出现之后执行什么东西 设置flag的值 到时候不进行执行


DECLARE CONTINUE HANDLER FOR 1329  SET flag=0;

-- 打开游标
OPEN my_cursor;
label:LOOP

-- 获取数据 执行一次获取一行的数据
FETCH my_cursor into  var_empno,var_empname,var_sal;

-- 判断flag 是0的话不进行执行
IF flag =1 THEN
 SELECT var_empno,var_empname,var_sal;
 ELSE
 LEAVE label;

END IF;

END LOOP label;


-- 关闭游标
CLOSE my_cursor;

END $$ ;
delimiter ;

call proc18('销售部');



1329是一个错误代码找不到的错误的代码。当找不到数据的时候就进行捕获了,走我们原先定义号的操作。

1.16总结

特点:

  • 代码复用

  • 比正常写代码的时候是快的

变量的范围有好几种

  • 局部:select into

  • 全局:@@变量名称

  • 用户:@变量名称

会话变量直接进行select就可以创建。

系统变量可以设置在本地的my.ini文件中。

分支语句

  • 两种语法格式

循环

  • while

  • repeat+until

  • loop:本身是一个死循环,需要借助if设置条件

1.17创建存储函数

需要先执行set GLOBAL log_bin_trust_function_creators=true;

不然会出现安全认证的错误不能成功的执行我们的函数不然话没法执行成功的。

-- 允许创建函数权限信任
set GLOBAL log_bin_trust_function_creators=true;

-- 创建存储函数
DROP FUNCTION IF EXISTS test;

delimiter $$ 
CREATE FUNCTION test() RETURNS int 
BEGIN

DECLARE cnt INT DEFAULT 0;
	SELECT count(*) INTO cnt  FROM emp;
RETURN cnt;
END $$

delimiter ;

SELECT test();

下面执行实际的表的操作

-- 传入员工的名称返回员工的名字
DROP FUNCTION IF EXISTS test;

delimiter $$ 
CREATE FUNCTION test(in_no int ) RETURNS VARCHAR(50) 
BEGIN

DECLARE out_name  VARCHAR(50) ;
	SELECT ename INTO out_name  FROM emp WHERE empno=in_no;
RETURN out_name;
END $$

delimiter ;

SELECT test('1001');

 和存储过程的操作是类似的,但是是基于select查询的操作进行执行的不是call执行的。

 2.触发器

实际上是表之间关系的一种操作

是自动执行的操作,只有增删改查的操作才会记录对应的日志的信息。

只能支持行的数据触发,只有行中的数据变化才能触发触发器

2.1基本操作

什么条件触发

什么时候触发

触发频率

定义在表上还是定义附属在表 上

-- ====================触发器===================================
-- 创建触发器

CREATE TRIGGER  触发器名称 BEFORE |AFTER 触发事件
ON 表名 for each ROW
BEGIN
执行语句列表
END

创建测试的表

CREATE TABLE `s_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
  `password` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

CREATE TABLE `user_log` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `time` datetime DEFAULT NULL,
  `log_text` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;

-- 创建好两张测试的表
DROP TRIGGER IF EXISTS tri_1;
CREATE TRIGGER  tri_1 
AFTER INSERT
ON s_user
FOR EACH ROW
BEGIN
INSERT INTO user_log VALUES(NULL,NOW(),'添加新用户') ;
END;


INSERT INTO `pz`.`s_user` (`id`, `name`, `password`) VALUES (1, '张伞', '123456');



 

-- 当数据被修改的时候也是会记录对应的修改的信息
DROP TRIGGER IF EXISTS tri_2;
CREATE TRIGGER  tri_2 
BEFORE UPDATE
ON s_user
FOR EACH ROW
BEGIN
INSERT INTO user_log VALUES(NULL,NOW(),'有用户被修改') ;
END;

UPDATE `pz`.`s_user` SET `name` = '李四', `password` = '123456' WHERE `id` = 1;

 

 

2.2NEW和OLD

是触发器的两个关键字记录的是修改前和修改后的用户的数据的信息

 

  • 插入的时候只能获取new的数据

  • 修改可以获取old和new的数据

  • delete可以获取old的数据

获取的时候直接

  • old.列名

  • new.列名

-- 记录修改前和修改后的数据
DROP TRIGGER IF EXISTS tri_1;
CREATE TRIGGER  tri_1 
AFTER INSERT
ON s_user
FOR EACH ROW
BEGIN
INSERT INTO user_log VALUES(NULL,NOW(),CONCAT_WS('-','添加新用户','用户名',new.name,'密码',new.password)) ;
END;

INSERT INTO `pz`.`s_user` (`id`, `name`, `password`) VALUES (NULL, '张伞', '123456');

 

-- 记录修改前和修改后的数据
-- 自增的数据也是可以获取的
DROP TRIGGER IF EXISTS tri_1;
CREATE TRIGGER  tri_1 
AFTER INSERT
ON s_user
FOR EACH ROW
BEGIN
INSERT INTO user_log VALUES(NULL,NOW(),CONCAT_WS('-','添加新用户','账号',new.id,'用户名',new.name,'密码',new.password)) ;
END;

INSERT INTO `pz`.`s_user` (`id`, `name`, `password`) VALUES (NULL, '张伞', '123456');



-- 修改后的数据

DROP TRIGGER IF EXISTS tri_1;
CREATE TRIGGER  tri_1 
BEFORE UPDATE
ON s_user
FOR EACH ROW
BEGIN
INSERT INTO user_log VALUES(NULL,NOW(),CONCAT_WS('-','修改前用户','账号',old.id,'用户名',old.name,'密码',old.password)) ;
INSERT INTO user_log VALUES(NULL,NOW(),CONCAT_WS('-','修改后用户','账号',new.id,'用户名',new.name,'密码',new.password)) ;
END;


UPDATE `pz`.`s_user` SET `name` = '李四修改', `password` = '12345678' WHERE `id` = 1;

 

 

 

DROP TRIGGER IF EXISTS tri_1;
CREATE TRIGGER  tri_1 
AFTER DELETE
ON s_user
FOR EACH ROW
BEGIN
INSERT INTO user_log VALUES(NULL,NOW(),CONCAT_WS('-','删除前用户','账号',old.id,'用户名',old.name,'密码',old.password)) ;
END;

DELETE FROM s_user WHERE `id` = 1;

 

 

 

2.3其他操作

-- 查看触发器
SHOW TRIGGERS;

-- 删除触发器
DROP TRIGGER IF EXISTS tri_1;

 

2.4注意事项

不能对本表的数据进行增删改的操作,避免递归

消耗资源

可以转换成后台的代码,转化成代码的操作

维护是困难的。

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

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

相关文章

jstack(Stack Trace for Java)Java堆栈跟踪工具

jstack&#xff08;Stack Trace for Java&#xff09;Java堆栈跟踪工具 jstack&#xff08;Stack Trace for Java&#xff09;命令用于生成虚拟机当前时刻的线程快照&#xff08;一般称为threaddump或者javacore文件&#xff09;。 线程快照就是当前虚拟机内每一条线程正在执…

Linux:iptables SNAT与DNAT

目录 一、SNAT 1.1 SNAT原理与应用 1.2 SNAT转换前提条件 1.3 SNAT工作原理 1.4 SNAT实例 二、DNAT 2.1DNAT原理与应用 2.2 DNAT转换前提条件 2.2实例 一、SNAT 1.1 SNAT原理与应用 SNAT 应用环境:局域网主机共享单个公网IP地址接入Internet (私有IP不能在Internet中正…

JAVAEE免费工程师教程之springboot综合案例

day04_springboot综合案例 用户管理 查询用户 查询所有用户执行流程 编写UserMapper接口 public interface UserMapper {// 查询所有用户List<UserInfo> findAllUsers(); }编写UserService public interface UserService extends UserDetailsService {/*** 查询所有…

(2023,UniversalFakeDetect)跨生成模型泛化的通用假图像检测器

Towards Universal Fake Image Detectors that Generalize Across Generative Models 公众号&#xff1a;EDPJ 目录 0. 摘要 1. 简介 2. 相关工作 3. 基础 3.1 问题设置 3.2 分析为什么先前的工作无法泛化 4. 方法 5. 实验 5.1 研究生成模型 5.2 真假分类基线 5.3 …

三重奏的和谐:如何完美对齐公司、部门与个人目标

引言 在企业的运营和管理中&#xff0c;目标的设定与对齐是至关重要的。它不仅决定了公司的方向和愿景&#xff0c;还影响到每一个部门和团队成员的工作内容和效果。如何确保公司目标、部门目标和团队个人目标之间的完美对齐&#xff0c;是每一个管理者都需要面对的挑战。 目…

HCIP学习--STP

在交换机上的线路冗余会产生的问题 昨天讲到了一个冗余的概念&#xff0c;下面就这个冗余引出来的问题来记录今天的内容 线路的冗余对于路由器来岁意味择可以选择更多的路线&#xff0c;但是对于交换机来说可不是啥好事情 比如下图假设A下面有一台设备要发送一个广播&#x…

第二讲:BeanFactory的实现

BeanFactory的实现 1. 环境准备2. 初始化DefaultListableBeanFactory3. 手动注册BeanDefinition4. 手动添加后置处理器5. 获取被依赖注入的Bean对象6. 让所有的单例bean初始化时加载7. 总结 Spring 的发展历史较为悠久&#xff0c;因此很多资料还在讲解它较旧的实现&#xff0c…

ROS与STM32通信(二)-pyserial

文章目录 下位机上位机自定义msg消息发布订阅 ROS与STM32通信一般分为两种&#xff0c; STM32上运行ros节点实现通信使用普通的串口库进行通信&#xff0c;然后以话题方式发布 第一种方式具体实现过程可参考上篇文章ROS与STM32通信-rosserial&#xff0c;上述文章中的收发频率…

一例Vague病毒的分析

这是一例通过U盘传播的文件夹病毒&#xff0c;有收集用户文件的行为&#xff0c;但是&#xff0c;没有回传和远控行为&#xff0c;有点奇怪&#xff0c;其中的字符串进行了加密。 样本比较简单&#xff0c;使用IDA很容易就看明白了。 根据匹配到威胁情报&#xff0c;有叫Vague蠕…

阿里云服务器和轻量云服务器对比有什么区别?

阿里云轻量应用服务器和云服务器ECS有什么区别&#xff1f;ECS是专业级云服务器&#xff0c;轻量应用服务器是轻量级服务器&#xff0c;轻量服务器使用门槛更低&#xff0c;适合个人开发者或中小企业新手使用&#xff0c;可视化运维&#xff0c;云服务器ECS适合集群类、高可用、…

初识SD绘画

最近sd绘画可谓是火的一塌糊涂&#xff0c;AI的绘画能力是真强大。废话不多说&#xff0c;直入主题。 1&#xff0c;sd的本地安装大体有2种&#xff0c;一种是官网安装&#xff0c;一种是秋叶大神的整合包。我安装的是秋叶大神的包&#xff0c;里面的插件和模型都有了&#xf…

Personalize Segment Anything Model with One Shot【论文翻译】

​ 论文基础信息如下 https://arxiv.org/pdf/2305.03048.pdfhttps://github.com/ZrrSkywalker/Personalize-SAM Abstract 通过大数据预训练驱动&#xff0c;分段任意模型&#xff08;Segment Anything Model&#xff0c;SAM&#xff09;已被证明是一个强大且可提示的框架&am…

嵌入式通信底层逻辑演变 SWIRE/UART/I2C/SPI

文章目录 一、概念1.0、计算机通讯框架OSI 7层模型1.1、根据数据排布传输方式---并行通信 / 串行通信1.2、根据数据传输方向与时间关系分类----单工通信/半双工通信/全双工通1.3、半双工通信的 应答与流控机制----如I2C&#xff0c;通过开漏线与特性 实现1.4、根据收发方时间基…

【C++入门到精通】C++入门 —— 容器适配器、stack和queue(STL)

阅读导航 前言stack1. stack概念2. stack特点3. stack使用 queue1. queue概念2. queue特点3. queue使用 容器适配器1. 什么是适配器2. STL标准库中stack和queue的底层结构3. STL标准库中对于stack和queue的模拟实现⭕stack的模拟实现⭕stack的模拟实现 总结温馨提示 前言 文章…

单链表-Java实现

目录 概念 什么是链表&#xff1f; 为什么链表的头节点不能动&#xff0c;或者不能操作&#xff1f; 链表和数组的区别是什么&#xff1f; 实现 节点 单链表 末尾添加 遍历 按编号添加&#xff1a; 修改节点 删除 面试题 求单链表的长度 求单链表倒数第K个节点 …

Qt关于hex转double,或者QByteArray转double

正常的00 ae 02 33这种类型的hex数据类型可以直接通过以下代码进行转换 double QDataConversion::hexToDouble(QByteArray p_buf) {double retValue 0;if(p_buf.size()>4){QString str1 byteArrayToHexStr(p_buf.mid(0,1));QString str2 byteArrayToHexStr(p_buf.mid(1,…

更安全,更高效的自学网络安全与黑客技术

学习网络安全&#xff08;黑客技术&#xff09; 网络安全是&#xff1a;黑客技术是&#xff1a;网络安全与黑客技术的关系&#xff1a;自学网络安全学习的误区和陷阱&#xff1a;学习网络安全前期需要准备...学习网络安全中期大致步骤&#xff1a;学习网络安全推荐的学习资料&a…

【电子通识】什么是异常分析中的A-B-A方法

工作有了一定的经验之后&#xff0c;在做问题分析的时候&#xff0c;经常会听到别人说把这个部品&#xff08;芯片/模块&#xff09;拿去ABA一下&#xff0c;看看跟谁走。那么对于新人来说是否就会问一个问题&#xff1a;什么是ABA呢&#xff1f; A-B-A 交换是一种简单直接的交…

华为OD七日集训第1期 - 按算法分类,由易到难,循序渐进,玩转OD(文末送书)

目录 一、适合人群二、本期训练时间三、如何参加四、7日集训第一期 ~ 华为OD初体验五、精心挑选21道高频100分经典题目&#xff0c;作为入门。第1天、逻辑分析第2天、字符串处理第3天、数据结构第4天、双指针第5天、递归回溯第6天、二分查找第7天、贪心算法 && 二叉树 …

【双指针】经典数组双指针题LeetCode

文章目录 27. 移除元素 简单283. 移动零 简单&#x1f525;167. 两数之和 II - 输入有序数组 中等11. 盛最多水的容器 中等&#x1f525;15. 三数之和 中等&#xff08;N数之和&#xff09;中等&#x1f525;42. 接雨水 困难 &#x1f525;26. 删除有序数组中的重复项 简单5. 最…