当前位置: 首页 > news >正文

MySQL-存储过程/函数/触发器

文章目录

  • 什么是存储过程
  • 存储过程的优缺点
  • 存储过程的基本使用
    • 存储过程的创建
    • 存储过程的调用
    • 存储过程的删除
    • 存储过程的查看
    • delimiter命令
  • MySQL中的变量
    • 系统变量
    • 用户变量
    • 局部变量
    • 参数
  • if语句
  • case语句
  • while循环
  • repeat循环
  • loop循环
  • 游标cursor
  • 捕获异常并处理
  • 存储函数
  • 触发器
    • 触发器概述
    • NEW & OLD关键字
    • 触发器的使用

什么是存储过程

简单点说就是普通的SQL语句加上一些其他编程语言进行逻辑判断的一些成分, 比如循环, 函数, 这些, 但本质上是一种SQL语句的集合, 或者说叫做, 过程化SQL语言


存储过程可称为过程化SQL语言,是在普通SQL语句的基础上增加了编程语言的特点,把数据操作语句(DML)和查询语句(DQL)组织在过程化代码中,通过逻辑判断、循环等操作实现复杂计算的程序语言。换句话说,存储过程其实就是数据库内置的一种编程语言,这种编程语言也有自己的变量、if语句、循环语句等。在一个存储过程中可以将多条SQL语句以逻辑代码的方式将其串联起来,执行这个存储过程就是将这些SQL语句按照一定的逻辑去执行,所以一个存储过程也可以看做是一组为了完成特定功能的SQL 语句集。每一个存储过程都是一个数据库对象,就像table和view一样,存储在数据库当中,一次编译永久有效。并且每一个存储过程都有自己的名字。


主要作用 : 客户端程序通过存储过程的名字来调用存储过程。在数据量特别庞大的情况下利用存储过程能达到倍速的效率提升。

存储过程的优缺点

优点:速度快。 降低了应用服务器数据库服务器之间网络通讯的开销。尤其在数据量庞大的情况下效果显著。

缺点:移植性差。编写难度大。维护性差。 - 每一个数据库都有自己的存储过程的语法规则,这种语法规则不是通用的。一旦使用了存储过程,则数据库产品很难更换,例如:编写了mysql的存储过程,这段代码只能在mysql中运行,无法在oracle数据库中运行。 - 对于数据库存储过程这种语法来说,没有专业的IDE工具(集成开发环境),所以编码速度较低。自然维护的成本也会较高。

在实际开发中,存储过程还是很少使用的。只有在系统遇到了性能瓶颈,在进行优化的时候,对于大数量的应用来说,可以考虑使用一些。

存储过程的基本使用

存储过程的创建

下面展示的创建存储过程p1的流程

/* 下面展示一下创建一个最简单的存储过程 */
# 如果存在这个存储过程就删除
drop procedure if exists p1;
# 创建一个存储过程
create procedure p1(#这里将来可以写参数)
begin # 执行逻辑在这里写
end; 

存储过程的调用

调用上面创建的存储过程p1

# 调用一下存储过程
call p1();

存储过程的删除

删除上面创建的存储过程p1

# 删除一下存储过程
drop procedure if exists p1;

存储过程的查看

在navicat中我们的存储过程都归入到了fx(函数内部)
在这里插入图片描述

查看创建存储过程的语句
类似于查看建表语句

# 展示一下建表的SQL(用dept举例)
show create table dept;
# 展示一下创建存储过程的SQL
show create procedure p1;

在这里插入图片描述
第一列的Procedure是存储过程的名字, 第三列的Create Procedure是创建存储过程的语句

还有一种方法是通过系统表information_schema.ROUTINES查看存储过程的详细信息
首先我们展示一下这个表的结构(特别复杂, 不是所有的数据都是我们需要的, 我们只需要以下几种)

  • SPECIFIC_NAME:存储过程的具体名称,包括该存储过程的名字,参数列表(类似方法签名)。
  • ROUTINE_SCHEMA:存储过程所在的数据库名称。
  • ROUTINE_NAME:存储过程的名称(只是一个名字)。
  • ROUTINE_TYPE:PROCEDURE表示是一个存储过程,FUNCTION表示是一个函数。
  • ROUTINE_DEFINITION:存储过程的定义语句。
  • CREATED:存储过程的创建时间。
  • LAST_ALTERED:存储过程的最后修改时间。
  • DATA_TYPE:存储过程的返回值类型、参数类型等。

下面我们模拟一下查询以下p1这个存储过程的上面的几个数据(忽略了routine_definition)
在这里插入图片描述

delimiter命令

简单点说这个命令的作用就是修改MySQL中的定界符 ;, MySQL中默认的是使用分号 ; 作为SQL语句的结尾, 但是如果在dos命令行窗口中创建存储过程的话, 中途操作使用分号会导致失败, 所以需要修改定界符(Navicat中不需要)
下面简单展示一下即可

# 把定界符修改为 //
delimiter //

在这里插入图片描述
在这里插入图片描述
可以观察到此时只有输入 // SQL才可以正常结束执行

MySQL中的变量

MySQL中的变量包括系统变量, 用户变量, 局部变量

系统变量

MySQL 系统变量是指在 MySQL 服务器运行时控制其行为的参数。这些变量可以被设置为特定的值来改变服务器的默认设置,以满足不同的需求。


MySQL 系统变量可以具有全局(global)或会话(session)作用域。

  • 全局作用域 : 对所有连接和所有数据库都适用
  • 会话作用域 : 只对当前连接和当前数据库适用

查看系统变量

# 基础语法
-- 1. 查出所有的系统变量
show [global|session] variables;
-- 2. 模糊的知道某一个系统变量的名称(模糊查询)
show [global|session] variables like '[模糊的内容]';
-- 3. 查询一个确切的系统变量的名称
select @@[global|session].[变量名称];

注意, 当没有global/session的时候, 默认的就是session
下面展示简单展示一下全局系统变量, 测试一下模糊查询当前的字符集是什么

/* 查看系统变量 */
# 1. 查询所有的全局系统变量
show global variables;
# 2. 模糊查询一下当前的系统字符集
show global variables like '%character%';
# 3. 确切的查询一下character_set_client(客户端的字符集)
select @@global.character_set_client;

下面展示简单展示一下会话系统变量, 测试一下模糊查询当前的字符集是什么


/* 查看系统变量 */
# 1. 查询所有的会话系统变量
show session variables;
# 2. 模糊查询一下当前的会话字符集
show session variables like '%character%';
# 3. 确切的查询一下character_set_client(客户端的字符集)
select @@session.character_set_client;

更改系统变量
基础语法

set [global|session] 变量名 =;set @@[global|session] 变量名 =;

比如我们之前就用过这个方法修改过隔离级别, 下面我们演示一下

/* 更改系统变量 */
# 1. 模糊查询一下隔离级别
show session variables like '%transaction%';
# 2. 把当前会话的隔离级别改为 read committed;
set session transaction_isolation = 'read-committed';

执行结果
在这里插入图片描述
在这里插入图片描述


无论是全局设置还是会话设置, 当mysql服务重启之后, 当前的配置都会失效, 但是我们可以通过修改my.ini这个配置文件来达到永久修改的目的(my.ini是MySQL数据库默认的系统级配置文件,默认是不存在的,需要新建,并参考一些资料进行配置。)windows系统是my.inilinux系统是my.cnfmy.ini文件通常放在mysql安装的根目录下
关于my.ini
我们之前简单的说过这个问题, 其实这就是配置文件
在这里插入图片描述

用户变量

用户自定义的变量, 只在当前会话有效, 所有的用户变量都以@开头, 而且所有的用户变量都不需要声明可以直接赋值使用, 如果不给用户变量赋值直接查询的话会查出来Null

/* 演示一下用户变量 */
# 给用户变量赋值
set @temp_val := 100;
set @temp_val1 := 'ddd';
select sal into @temp_val2 from emp where ename = 'smith';
# 查询一下用户变量
select @temp_val, @temp_val1, @temp_val2;

在这里插入图片描述
注意:mysql中变量不需要声明。直接赋值就行。如果没有声明变量,直接读取该变量,返回null

局部变量

在存储的过程中可以使用局部变量, 使用declare进行声明, 在begin和end之间有效, 注意, 在进行传参的时候, 传入的参数, 本质上也是一种局部变量

声明局部变量

# default后面是默认值
declare 变量名 数据类型 [default ...];

这里注意一下, 关于declare的位置目前来说我们还不确定具体的情况, 所以所有的declare都在存储过程的最前面声明


变量的赋值

set 变量名 :=;
select 字段名 into 变量 from 表名...;

下面简单演示一下局部变量的使用流程

/* 测试一下局部变量的使用 */
drop procedure if exists p1;create procedure p1()
begin# 声明局部变量declare i int default 1;declare j varchar(10);declare m decimal(10, 2) default 0.00;declare n datetime;# 给局部变量赋值set i := 10;set j := 'ttt';set m := 1.23;set n := '2024-10-23 20:52:22';# 查询一下局部变量select i, j, m, n;
end; call p1();

在这里插入图片描述

参数

存储过程的参数包括三种形式

  • in : 入参(未指定时, 默认是in)
  • out : 出参(类似返回值)
  • inout : 既是入参又是出参(类似Java中的引用)
    定义在存储过程的()里面
    注意一点的是, out, 或者是inout传入/接收的就是用户变量
create procedure p2(out sum int)
begin...
end;call p2(@sum);

if语句

没什么可说的, 是个编程语言就有, 算非常基础的语法点了

# 基础语法格式
if 条件 then ...
else if 条件 then ...
else if 条件 then ...
else if 条件 then ...
else if 条件 then ...
else ...
end if;

案例:员工月薪sal,超过10000的属于“高收入”,6000到10000的属于“中收入”,少于6000的属于“低收入”。
下面的存储过程可以完成这一需求

# 删除一下这个存储过程
drop procedure if exists p2;# 创建存储过程
create procedure p2(in sal int, out grade varchar(20))
begin if sal > 10000 thenset grade := '高收入';elseif sal between 6000 and 10000 then set grade := '中收入';else set grade := '低收入';end if;
end;# 调用存储过程(查一下 'smith' 的工资)
select sal into @sal from emp where ename = 'smith';
call p2(@sal, @grade);# 展示工资水平
select @grade;

在这里插入图片描述

case语句

有点类似switch-case语句
基础语法

# 语法1
casewhen1 then ...when2 then ...when3 then ...when4 then ...else ...
end case;# 语法2
case when 条件1 then ...when 条件2 then ...when 条件3 then ...when 条件4 then ...else ...
end case;

取一个最经典的例子, 根据不同月份, 输出季节
3 4 5月份春季。6 7 8月份夏季。9 10 11月份秋季。12 1 2 冬季。其他非法

/* 测试一下case语句 */
# 删除一下存储过程
drop procedure if exists p3;# 创建一下存储过程
create procedure p3(in month int, out season varchar(10))
begin case monthwhen 3 then set season := '春季';when 4 then set season := '春季';when 5 then set season := '春季';when 6 then set season := '夏季';when 7 then set season := '夏季';when 8 then set season := '夏季';when 9 then set season := '秋季';when 10 then set season := '秋季';when 11 then set season := '秋季';when 12 then set season := '冬季';when 1 then set season := '冬季';when 2 then set season := '冬季';else set season := '无效输入';end case;
end; # 调用存储过程, 展示结果
call p3(12, @season);
select @season;/* 测试一下case语句 */
# 删除一下存储过程
drop procedure if exists p3;# 创建一下存储过程
create procedure p3(in month int, out season varchar(10))
begin case when month in (3,4,5) then set season := '春季';when month in (6,7,8) then set season := '夏季';when month in (9,10,11) then set season := '秋季';when month in (12,1,2) then set season := '冬季';else set season := '无效输入';end case;
end; # 调用存储过程, 展示结果
call p3(12, @season);
select @season;

在这里插入图片描述

while循环

基础语法

while 循环条件 do循环体;
end while

求1 ~ n 范围内的偶数和


/* 测试一下while循环 */
# 删除一下存储过程
drop procedure if exists p4;# 创建一下存储过程
create procedure p4(in n int, out sum int)
begin declare i int default 1;set sum := 0;while i <= n doif i % 2 = 0 then set sum := sum + i;end if;set i := i + 1;end while;
end; # 调用一下存储过程
call p4(100, @sum);
select @sum;

repeat循环

基础语法

repeat循环体;until 条件
end repeat;

注意:条件成立时结束循环

案例:传入一个数字n,计算1~n中所有偶数的和。

create procedure mypro(in n int, out sum int)
begin set sum := 0;repeat if n % 2 = 0 then set sum := sum + n;end if;set n := n - 1;until n <= 0end repeat;
end;call mypro(10, @sum);
select @sum;

loop循环

# 基础语法
循环名称 : loop循环体leave 循环名称;iterate 循环名称;
end loop;

这个循环没有限制的话就是一个十循环, 所以要加上leave语句(相当于break语句跳出循环), iterate语句(相当于continue)进行调控

案例 : 打印 1, 2, 4, 5

/* 测试一下loop循环 */
drop procedure if exists p5;create procedure p5()
begindeclare i int default 0;myloop : loop set i := i + 1;	if i = 3 theniterate myloop; end if;if i = 6 thenleave myloop;end if;	select i;	end loop;
end; call p5();

游标cursor

游标(cursor) 可以理解为一个指向结果集中某条记录的指针, 允许程序逐一访问结果集中的每条记录, 并对其进行逐行的操作和处理.
使用游标时,需要在存储过程或函数中定义一个游标变量,并通过 DECLARE 语句进行声明和初始化。然后,使用 OPEN 语句打开游标,使用 FETCH 语句逐行获取游标指向的记录,并进行处理。最后,使用 CLOSE 语句关闭游标,释放相关资源。游标可以大大地提高数据库查询的灵活性和效率。


使用游标的步骤

  • 声明游标 : DECLARE 游标名称 CURSOR FOR DQL查询语句
  • 打开游标 : OPEN 游标名称
  • 操作游标 : FETCH 游标名称 INTO [变量1,变量2…]
  • 关闭游标 : CLOSE 游标名称

需求 : 从dept表中查询部门编号和部门名称, 创建一张新表new_dept, 把查询到的结果插入到新表当中
实现功能代码如下


/* 展示一下游标cursor的使用 */
# 删除存储过程
drop procedure if exists p6;# 创建存储过程
create procedure p6()
begin-- 声明一下局部变量declare no int;declare name varchar(20);-- 声明游标declare d_cursor cursor for select deptno, dname from dept;-- 创建一张新表create table new_dept(dno int primary key, dname varchar(20));-- 打开游标open d_cursor;-- 操作游标while true dofetch d_cursor into no, name;insert into new_dept(dno, dname) values (no, name);end while;-- 关闭游标close d_cursor;
end; # 调用存储过程
call p6();# 展示执行结果
select * from new_dept;

这里需要注意的是 : 关于declare声明一定要在所有的程序之前完成(目前的已知理解)
执行结果是正确的, 但是需要注意的是, 这里有一个异常信息
在这里插入图片描述
在这里插入图片描述
可以看到, 虽然操作成功了, 但是出来了一个异常信息, 因为我们while循环的条件是true, fetch的时候会出现元素不足的情况, 如何处理需要我们下面说的异常处理…

注意:声明局部变量和声明游标有顺序要求,局部变量的声明需要在游标声明之前完成。

捕获异常并处理

类似于Java中的异常处理机制, SQL中也有类似的方法, 就是将异常进行contiue(类似try-catch捕获), exit(类似throws上抛)

语法格式 :

DECLARE handler_name HANDLER FOR condition_value action_statement;

这里的DECLARE是声明的意思, handler_name代表你的处理态度(continue/exit), HANDLER FOR就是一个关键字, condition_value的填写看我们下面的解释, action_statement是你的处理方式

  • handler_name 表示异常处理程序的名称,重要取值包括:
    1. CONTINUE:发生异常后,程序不会终止,会正常执行后续的过程。(捕捉)
    2. EXIT:发生异常后,终止存储过程的执行。(上抛)
  • condition_value 是指捕获的异常,重要取值包括:
    1. SQLSTATE sqlstate_value,例如:SQLSTATE ‘02000’
    2. SQLWARNING,代表所有01开头的SQLSTATE
    3. NOT FOUND,代表所有02开头的SQLSTATE
    4. SQLEXCEPTION,代表除了01和02开头的所有SQLSTATE
  • action_statement 是指异常发生时执行的语句,例如:CLOSE cursor_name

注意 : 关于conditon_value具体应该填那个, 建议上网查一查, 因为这个并不是严格对应的, 比如上面的1329号异常就可以用NOT FOUND 或者是 SQLSTATE '02000'都是可以的

下面我们处理一下之前出现的那个异常

/* 展示一下游标cursor的使用 */
# 删除存储过程
drop procedure if exists p6;# 创建存储过程
create procedure p6()
begin-- 声明一下局部变量declare no int;declare name varchar(20);-- 声明游标declare d_cursor cursor for select deptno, dname from dept;-- 处理一下之前出现的那个异常1329declare exit handler for NOT FOUND close d_cursor;# 下面这种处理方式也是可以的declare exit handler for SQLSTATE '02000' close d_cursor;-- 创建一张新表drop table if exists new_dept;create table new_dept(dno int primary key, dname varchar(20));-- 打开游标open d_cursor;-- 操作游标while true dofetch d_cursor into no, name;insert into new_dept(dno, dname) values (no, name);end while;-- 关闭游标close d_cursor;
end; # 调用存储过程
call p6();# 展示执行结果
select * from new_dept;

在这里插入图片描述
这样就不会出现异常了

存储函数

存储函数 : 带返回值的存储过程, 参数只允许是in(但不能显示的写in), 没有out, 也没有inout
基础语法

CREATE FUNCTION 函数名称(参数列表) RETURNS 返回值类型 [函数特征]
BEGIN-- 函数体RETURN ...;
END;

关于函数的特征, 其实就是一种MySQL的一种优化策略, 通常有下面三种

  • deterministic : 用这个特征标记的函数为确定性函数, 确定性函数指的就是对同一个入参, 只会对应相同的返回结果, 也就是一对一, 不会出现同一个函数传入相同的参数结果不一样的情况, 所以MySQL底层就可以根据这一特点对该函数进行优化, 对于一个传入的参数的返回结果, MySQL底层会进行缓存, 当下次再次传入这个参数的时候, 就直接访问之前缓存的结果, 从而提高性能
  • no sql : 用该特征标记的函数执行过程中不会查询数据库, 如果确定没有查询语句建议使用, 告诉MySQL优化器不需要考虑使用查询缓存和优化器缓存来优化这个函数, 这样就可以避免不必要的查询消耗产生, 从而提高性能
  • reads sql data : 这个就跟上面的no sql恰好相反, 用该特征标记该函数会进行查询操作,告诉 MySQL 优化器这个函数需要查询数据库的数据,可以使用查询缓存来缓存结果,从而提高查询性能;同时 MySQL 还会针对该函数的查询进行优化器缓存处理。
  • 一个函数具有多个特征的时候一起写就可以了

下面用这个存储函数来测试一个最简单的例子, 计算 1~n 之间的所有偶数和(特征用deteministicno sql)

/* 测试一下存储函数 */
# 删除存储函数
drop function if exists sum_odd;# 创建存储函数
create function sum_odd(n int) returns int deterministic no sql
begindeclare sum int default 0;while n > 0 doif n % 2 = 0 then set sum := sum + n;end if;set n := n - 1;end while;return sum;
end;# 调用函数的时候不用call关键字
set @res := sum_odd(100);# 查询返回结果
select @res;

在这里插入图片描述

触发器

触发器概述

MySQL中触发器是一种数据库对象, 它是和表相关联的特殊的程序, 它可以在特定的数据操作, 例如插入(INSERT), 更新(UPDATE), 删除(DELETE) 这些DML语句操作时触发并自动执行. MySQL中的触发器机制可以使数据库开发人员能够在数据的不同状态之间维护一致性和完整性, 并且可以为特定的数据库表自动执行操作


触发器的作用主要有以下几个方面:

  1. 强制实施业务规则:触发器可以帮助确保数据表中的业务规则得到强制执行,例如检查插入或更新的数据是否符合某些规则。
  2. 数据审计:触发器可以声明在执行数据修改时自动记日志或审计数据变化的操作,使数据对数据库管理员和 SQL 审计人员更易于追踪和审计。
  3. 执行特定业务操作:触发器可以自动执行特定的业务操作,例如计算数据行的总数、计算平均值或总和等。

MySQL 触发器分为两种类型: BEFOREAFTER。BEFORE 触发器在执行 INSERT、UPDATE、DELETE 语句之前执行,而 AFTER 触发器在执行 INSERTUPDATEDELETE 语句之后执行。

创建触发器的语法如下

CREATE TRIGGER trigger_name
BEFORE/AFTER INSERT/UPDATE/DELETE ON table_name FOR EACH ROW
BEGIN-- 触发器执行逻辑
END;
  • trigger_name : 触发器名称
  • BEFORE/AFTER : 触发器的类型, 可以是before或者是after
  • INSERT/UPDATE/DELETE : 触发器监控的DML调用类型
  • table_name : 触发器绑定的表名
  • FOR EACH ROW : 表示触发器在每行受到DML影响之后都会执行

需要注意的是,触发器是一种高级的数据库功能,只有在必要的情况下才应该使用,例如在需要实施强制性业务规则时。过多的触发器和复杂的触发器逻辑可能会影响查询性能和扩展性。


NEW & OLD关键字

在 MySQL 触发器中,NEW 和 OLD 是两个特殊的关键字,用于引用在触发器中受到修改的行的新值和旧值。具体而言:

  • NEW:在触发 INSERT 或 UPDATE 操作期间,NEW 用于引用将要插入或更新到表中的新行的值。
  • OLD:在触发 UPDATE 或 DELETE 操作期间,OLD 用于引用更新或删除之前在表中的旧行的值。

通俗的讲,NEW 是指触发器执行的操作所要插入或更新到当前行中的新数据;而 OLD 则是指当前行在触发器执行前原本的数据。

在MySQL 触发器中,NEW 和 OLD 使用方法是相似的。在触发器中,可以像引用表的其他列一样引用 NEW 和 OLD。例如,可以使用 OLD.column_name 从旧行中引用列值,也可以使用 NEW.column_name 从新行中引用列值。

示例:

假设有一个名为 my_table 的表,其中包含一个名为 quantity 的列。当在该表上执行 UPDATE 操作时,以下触发器会将旧值 OLD.quantity 累加到新值 NEW.quantity 中:

CREATE TRIGGER my_trigger
BEFORE UPDATE ON my_table
FOR EACH ROW
BEGIN
SET NEW.quantity = NEW.quantity + OLD.quantity;
END;

在此触发器中,OLD.quantity 引用原始行的 quantity 值(旧值),而 NEW.quantity 引用更新行的 quantity 值(新值)。在触发器执行期间,数据行的 quantity 值将设置为旧值加上新值


触发器的使用

简单测试一个update的触发器, 当对某一个列进行修改的时候, 我们添加一个日志记录

/* 测试一下触发器 */
drop table if EXISTS person;-- 人员信息表
create table person(id int primary key auto_increment,name varchar(255),sal int
);-- update_person 人员更新日志表
drop table if EXISTS update_person_log;
create table update_person_log(id int,old_name varchar(255),new_name varchar(255),old_sal int,new_sal int,update_time datetime,update_info varchar(255),foreign key (id) references person(id) 
);-- 插入几条测试数据
insert into person(name, sal) values ('a', 100), ('b', 200), ('c', 300);-- 添加一个触发器对象
create trigger test_update_per after update on person for each row 
begininsert into update_person_log values (old.id, old.name, new.name, old.sal, new.sal, now(), concat('名字从', old.name, '更新为', new.name, '; 薪资从', old.sal, '更新为', new.sal));
end; -- 更新一条数据看看
update person set name = 'aa', sal = 150 where name = 'a';-- 查看一下日志表
select * from update_person_log;

执行结果如下
在这里插入图片描述

相关文章:

MySQL-存储过程/函数/触发器

文章目录 什么是存储过程存储过程的优缺点存储过程的基本使用存储过程的创建存储过程的调用存储过程的删除存储过程的查看delimiter命令 MySQL中的变量系统变量用户变量局部变量参数 if语句case语句while循环repeat循环loop循环游标cursor捕获异常并处理存储函数触发器触发器概…...

前端页面样式没效果?没应用上?

当我们在开发项目时会有很多个页面、相同的标签&#xff0c;也有可能有相同的class值。样式设置的多了&#xff0c;分不清哪个是当前应用的。我们可以使用网页的开发者工具。 在我们开发的网页中按下f12或&#xff1a; 在打开的工具中我们可以使用元素选择器&#xff0c;单击我…...

05.MyISAM主键和二级索引树

...

Mac apache配置cgi环境-修改httpd.conf文件、启动apache

Mac自带Apache&#xff0c;配置CGI&#xff0c;分以下几步&#xff1a; 找到httpd.conf。打开终端&#xff0c;编辑以下几处&#xff0c;去掉#或补充内容。在这个路径下写一个测试文件.py格式的&#xff0c;/Library/WebServer/CGI-Executables&#xff0c;注意第一行的python…...

多厂商的实现不同vlan间通信

Cisco单臂路由 Cisco路由器配置 -交换机配置 -pc配置 华三的单臂路由 -路由器配置 -华三的接口默认是打开的 -pc配置及ping的结果 -注意不要忘记配置默认网关 Cisco-SVI -交换机的配置 -创建vlan -> 设置物理接口对应的Acess或Trunk -> 进入vlan接口&#xff0c;打开接…...

sh与bash的区别

sh与bash的区别 结论&#xff1a;对于一般开发者&#xff0c;没有区别&#xff1b;对于要使脚本兼容较老系统&#xff0c;或者兼容其他shell&#xff08;如ksh&#xff0c;dash&#xff09;&#xff0c;那么意义可能很重大&#xff0c;要确保自己代码没有bash扩展的特性。 区…...

D48【python 接口自动化学习】- python基础之类

day48 练习&#xff1a;开发自动咖啡&#xff08;上&#xff09; 学习日期&#xff1a;20241025 学习目标&#xff1a;类 -- 62 小试牛刀&#xff1a;如何开发自动咖啡机&#xff1f;&#xff08;上&#xff09; 学习笔记&#xff1a; 案例解析 定义类 定义属性和方法 clas…...

PostgreSQL(WINDOWS)下载、安装、简单使用

下载 PostgreSQL: Downloads PostgreSQL: Windows installers EDB: Open-Source, Enterprise Postgres Database Management 安装 注意密码要方便自己使用&#xff0c;不能忘记。 打开pgAdmin&#xff0c;输入密码 新建数据库 打开命令工具 新建表...

Git的初次使用

一、下载git 找淘宝的镜像去下载比较快 点击这里 二、配置git 1.打开git命令框 2.设置配置 git config --global user.name "你的用名"git config --global user.email "你的邮箱qq.com" 3.制作本地仓库 新建一个文件夹即可&#xff0c;然后在文件夹…...

rocketmq服务的docker启动和配置

rocketmq的默认启动参数占用的内存实在是太大了&#xff0c;小于8G的电脑无法启动&#xff0c;docker中的开发环境又不可能用这么大&#xff0c;通用的该法是改sh文件 修改文件如下 runbroker.sh 默认8G JAVA_OPT"${JAVA_OPT} -server -Xms${Xms} -Xmx${Xmx} -Xmn${Xmn…...

BLE和经典蓝牙相比,有什么优缺点

蓝牙低功耗&#xff08;Bluetooth Low Energy&#xff0c;简称 BLE&#xff09;和经典蓝牙&#xff08;Bluetooth Classic&#xff0c;即 BR/EDR&#xff0c;Basic Rate/Enhanced Data Rate&#xff09;是蓝牙技术的两种主要模式。两者都有各自的优缺点&#xff0c;具体如下&am…...

ECharts图表图例知识点小结

ECharts 图表图例简述 一、知识点 1. 作用&#xff1a; - 用于标识图表中的不同系列&#xff0c;帮助用户理解图表所展示的数据内容。 2. 位置&#xff1a; - 可以通过配置项设置图例的位置&#xff0c;如 top 、 bottom 、 left 、 right 等。 3. 显示状态控制&#xff1a…...

LabVIEW非接触式模态参数识别系统开发

基于LabVIEW的模态参数识别系统采用非接触式声学方法&#xff0c;结合LabVIEW软件和高精度硬件&#xff0c;实现机械结构模态参数的快速准确识别。降低了模态分析技术门槛&#xff0c;提高测试效率和准确性。 项目背景与意义: 传统的模态分析方法&#xff0c;如锤击法&#x…...

厨艺爱好者的在线家园:基于Spring Boot的实现

1 绪论 1.1 研究背景 现在大家正处于互联网加的时代&#xff0c;这个时代它就是一个信息内容无比丰富&#xff0c;信息处理与管理变得越加高效的网络化的时代&#xff0c;这个时代让大家的生活不仅变得更加地便利化&#xff0c;也让时间变得更加地宝贵化&#xff0c;因为每天的…...

PostgreSQL使用clickhouse_fdw访问ClickHouse

Postgres postgres版本&#xff1a;16&#xff08;测试可用&#xff09;docker 安装 插件安装 clickhouse_fdw: https://github.com/ildus/clickhouse_fdw 安装命令 git clone gitgithub.com:ildus/clickhouse_fdw.git cd clickhouse_fdw mkdir build && cd build…...

docker 单节点arm架构服务器安装zookeeper、kafka并测试通信

kafka、zookeeper常用镜像介绍 kafka和zookeeper常见的镜像有以下三个&#xff1a;wurstmeister/zookeeper、kafka、confluentinc/cp-zookeeper、cp-kafka 和 bitnami/zookeeper、kafka。 wurstmeister/xxx: 由wurstmeister团队维护&#xff0c;提供的镜像适用于开发和测试环…...

AnaTraf | 全面掌握网络健康状态:全流量的分布式网络性能监测系统

AnaTraf 网络性能监控系统NPM | 全流量回溯分析 | 网络故障排除工具AnaTraf网络流量分析仪是一款基于全流量&#xff0c;能够实时监控网络流量和历史流量回溯分析的网络性能监控与诊断系统&#xff08;NPMD&#xff09;。通过对网络各个关键节点的监测&#xff0c;收集网络性能…...

单片机入门教程

单片机入门教程 单片机是一种将中央处理器&#xff08;CPU&#xff09;、存储器、输入输出接口等集成在一个芯片上的微型计算机系统。本教程将带你从零开始学习如何使用一款常见的单片机——ATmega328P&#xff0c;并编写简单的控制程序。 1. 单片机简介 1.1 什么是单片机&a…...

三维管线管网建模工具MagicPipe3D V3.5.3

经纬管网建模系统MagicPipe3D&#xff0c;本地离线参数化构建地下管网三维模型&#xff08;包括管道、接头、附属设施等&#xff09;&#xff0c;输出标准3DTiles、Obj模型等格式&#xff0c;支持Cesium、Unreal、Unity、Osg等引擎加载进行三维可视化、语义查询、专题分析&…...

(二十三)、k8s(minikube) 部署mysql

文章目录 1、安装1.1、环境1.2、workbench 崩溃问题1.1、deployment.yaml 文件1.2、运行1.3、启动隧道&#xff0c;从宿主机直接访问 k8s 中的mysql 2、完整卸载 mysql&#xff08;pod/deployment/service/pvc&#xff09; 1、安装 1.1、环境 docker 部署 minikube,minikube …...

FFMPEG+Qt 实时显示本机USB摄像头1080p画面以及同步录制mp4视频

FFMPEGQt 实时显示本机USB摄像头1080p画面以及同步录制mp4视频 文章目录 FFMPEGQt 实时显示本机USB摄像头1080p画面以及同步录制mp4视频1、前言1.1 目标1.2 一些说明 2、效果3、代码3.1 思路3.2 工程目录3.3 核心代码 4、全部代码获取 1、前言 本文通过FFMPEG(7.0.2)与Qt(5.13.…...

微信小程序中关闭默认的 `navigationBar`,并使用自定义的 `nav-bar` 组件

要在微信小程序中关闭默认的 navigationBar&#xff0c;并使用自定义的 nav-bar 组件&#xff0c;你可以按照以下步骤操作&#xff1a; 1. 关闭默认的 navigationBar 在你的页面的配置文件 *.json 中设置 navigationBar 为 false。你需要在页面的 JSON 配置文件中添加以下代码…...

FPGA 小鸟避障游戏

FPGA实现效果&#xff1a; FPGA 小鸟避障游戏 FPGA&#xff08;Field Programmable Gate Array&#xff09;即现场可编程门阵列&#xff0c;是一种可以编程的数字逻辑器件。基于FPGA的小鸟避障游戏是一种结合了硬件加速和算法优化来运行的实时交互游戏。这种游戏一般利用FPGA的…...

Claude Financial Data Analyst:基于Claude的金融数据分析工具!免费开源!

大家好&#xff0c;我是木易&#xff0c;一个持续关注AI领域的互联网技术产品经理&#xff0c;国内Top2本科&#xff0c;美国Top10 CS研究生&#xff0c;MBA。我坚信AI是普通人变强的“外挂”&#xff0c;专注于分享AI全维度知识&#xff0c;包括但不限于AI科普&#xff0c;AI工…...

django5入门【03】新建一个hello界面

文章目录 1、前提条件⭐2、操作步骤总结3、实际操作示例 1、前提条件⭐ 将上一节创建的 Django 项目导入到 PyCharm 中。 2、操作步骤总结 &#xff08;1&#xff09;在 HelloDjango/HelloDjango 目录下&#xff0c;新建一个 views.py 文件。 &#xff08;2&#xff09;在 H…...

【Unity】Unity中调用手机的震动功能 包括安卓和IOS

直接上代码 #if UNITY_IOS[DllImport("__Internal")]private static extern void EX_C_CallVibrateE(int eID); #endif public static void CallVibrate(int eID){ #if UNITY_EDITOR#elif UNITY_ANDROIDlong miSec 30;if(eID 1520){miSec 60;}//通过报名获取ja…...

【软件工程】软件工程入门

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;软件开发必练内功_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 1. 前…...

命名空间std, using namespace std

命名空间std&#xff0c;using namespace std 在标准C以前&#xff0c;都是用#include<iostream.h>这样的写法的&#xff0c;因为要包含进来的头文件名就是iostream.h。标准C引入了名字空间的概念&#xff0c;并把iostream等标准库中的东东封装到了std名字空间中&#x…...

人工智能:未来生活与工作的变革者

随着人工智能&#xff08;AI&#xff09;技术的迅猛发展&#xff0c;越来越多的领域开始受益于AI的强大功能。从医疗、企业管理到日常生活&#xff0c;人工智能正在改变我们的世界。本文将深入探讨人工智能技术的应用前景&#xff0c;并分析它如何从根本上改变我们的生活和工作…...

SEO基础:什么是LSI关键词?【百度SEO优化专家】

SEO基础&#xff1a;什么是LSI关键词&#xff1f; 大家好&#xff0c;我是林汉文&#xff08;百度SEO优化专家&#xff09;&#xff0c;在SEO&#xff08;搜索引擎优化&#xff09;中&#xff0c;LSI关键词是一个重要的概念&#xff0c;有助于提升网页的相关性和内容质量。那么…...

企业网站搭建步骤/网络营销软件大全

我的Dock用的是plank&#xff0c;很简单很好用。为什么不用Docky还有其他什么玩意儿呢&#xff1f;plank很简单很好用&#xff0c;资源占用很少&#xff0c;可以智能隐藏&#xff0c;you nearly cant feel it but you know its right there, supporting your work correctly.大…...

网站哪家做的比较好/2022年搜索引擎优化指南

最近挺多童鞋问我如何配置Spring Cloud xxx组件的重试。本篇进行一个总结。 Spring Cloud中的重试机制应该说是比较混乱的&#xff0c;不同的版本有一定区别&#xff0c;实现也不大一样&#xff0c;好在Spring Cloud Camden之后已经基本稳定下来&#xff0c;Dalston中又进行了一…...

手机网站自助建设/网站建设有多少公司

oracle分类排序/排行可以通过聚合函数rank() 和 dense_rank() 来实现。 rank() 和 dense_rank() &#xff1a; --两种排名方式(分区和不分区):使用和不使用partition --两种计算方式(连续&#xff0c;不连续)&#xff0c;对应函数&#xff1a;dense_rank,rank dense_rank与ran…...

政府网站建设经验/百度打广告怎么收费

目录 前言 Docker的简介 1&#xff0c;什么是补充&#xff1f; 2&#xff0c;普遍从哪里来的&#xff1f; 监督管理命令 1&#xff0c;搜索平均值 2&#xff0c;下载总计 3&#xff0c;查看概况 4&#xff0c;为补充添加标签 5&#xff0c;删除总计 6&#xff0c;存…...

电脑做试卷的网站/google play谷歌商店

2019独角兽企业重金招聘Python工程师标准>>> 有时需要限制对Tomcat Web应用的访问&#xff0c;如只有指定的主机或IP地址可以访问指定的应用。这样一来&#xff0c;就只有那些指定的客户端可以访问服务的内容。本实例将介绍如何在Tomcat下制定主机访问。 Tomcat提供…...

山石网站超市/ui设计公司

我有一个场景,当我点击按钮时,我想要弹出AlertDialog. AlertDialog是一个自定义警报对话框,因为它具有自定义Listview.我使用以下代码分配AlertDialog OnClick按钮top.setOnClickListener(new OnClickListener() {Context mcontext;Overridepublic void onClick(View arg0) {//…...