HNU-数据库系统-实验2-数据库安全性/完整性定义与检查

news2024/11/15 20:04:36

数据库系统 课程实验2
数据库安全性/完整性定义与检查

计科210X 甘晴void 202108010XXX
在这里插入图片描述

目录

文章目录

  • 数据库系统 课程实验2<br>数据库安全性/完整性定义与检查
    • 实验目的
    • 实验环境
    • 实验内容
      • 2.1数据库安全性
      • 2.1.1 自主存取控制实验
        • 1)实验内容与要求
        • 2)实验重难点
        • 3)实验过程
          • ①预先准备
          • ②创建两个部门经理用户并授予创建用户的权限
          • ③给予部门经理用户其他权限
          • ★激活角色
          • ④使用部门经理创建员工用户
          • ⑤验证员工用户权限
          • ⑥收回员工查看的权限,并验证
      • 2.1.2 审计实验
        • 1)实验内容与要求
        • 2)实验重难点
        • 3)实验过程
          • ①首先查看审计配置情况:
          • ②开启日志
          • ③验证审计
          • ④关闭日志
      • 2.2数据库完整性
      • 2.2.1 实体完整性实验
        • 1)实验内容与要求
        • 2)实验重难点
        • 3)实验过程
          • ①创建新数据库HNUT2
          • ②创建表时定义完整性并验证
          • ③创建表之后定义并验证
          • ④删除实体完整性并验证
      • 2.2.2 参照完整性实验
        • 1)实验内容与要求
        • 2)实验重难点
        • 3)实验过程
          • ①创建表时定义参照完整性+验证
          • ②创建表后定义参照完整性
          • ③定义参照完整性的违约处理
          • ④删除参照完整性
      • 2.2.3 用户自定义完整性实验
        • 1)实验内容与要求
        • 2)实验重难点
        • 3)实验过程
          • ①建立完整性约束
          • ②验证完整性约束
          • ③删除完整性约束并验证
      • 2.3 触发器实验
        • 1)实验内容与要求
        • 2)实验重难点
        • 3)示例
          • ①创建触发器(以BEFORE为例)
          • ★mysql关于触发器的语法区别
          • ②验证触发器(以BEFORE为例)
          • ③验证触发器执行顺序
          • ④删除触发器
    • 实验感悟

实验目的

1)熟悉通过 SQL 对数据库进行安全性控制的方法,其中包括自主存取控制实验和审计实验。

2)熟悉通过 SQL 对数据库进行完整性控制的方法,其中包括实体完整性、参照完整性、用户自定义完整性。

3)熟悉并掌握数据库触发器的设计和使用方法。

实验环境

DBMS:8.0.33 MySQL Community Server - GPL

可视化:Navicat Premium 16.1.6

命令行:Navicat自带命令列

命令行:由Microsoft商店提供的windows终端(version=1.18.2822.0)启动的windows powershell命令行(这个主要是在安全性实验中登录FINANCE用户和U1用户时使用,Navicat自带命令行默认以root登录,不方便这样操作)

实验内容

2.1数据库安全性

2.1.1 自主存取控制实验

1)实验内容与要求

定义用户、角色,分配权限给用户、角色,回收权限,以相应的用户名登录数据库验证权限分配是否正确。选择一个应用场景,使用自主存取控制机制设计权限分配。可以采用两种方案:

方案一:采用 SYSTEM 超级用户登录数据库,完成所有权限分配工作,然后用相应用户名登陆数据库以验证权限分配正确性;

方案二:采用 SYSTEM 用户登陆数据库创建两个部门经理用户,并分配相应的权限,然后分别用两个经理用户名登陆数据库,创建相应部门的 USER, ROLE,并分配相应权限。验证权限分配之前,请备份好数据库;针对不同用户所具有的权限,分别设计相应的 SQL语句加以验证。

【注意】这两种方式是参考文档提供给我们的,不一定需要照抄方案。

我准备采用自己的方案来进行操作。

2)实验重难点

定义角色,分配权限和回收权限,实现权限的再分配与回收。

3)实验过程

我们实验题目提供的示例。过程如下

①预先准备

创建数据库 TEST_COMPANY,包含 salary 工资表、employee 员工表。

根据题目提供的参考示例

在这里插入图片描述

构建好数据库和相应的数据集

在这里插入图片描述

整体思路:

使用 SYSTEM 超级用户登录数据库创建两个部门经理用户,分配相应权限,然后使用经理用户名登录数据库创建相应部门的 USER、ROLE,分配相应权限。

  • 创建用户财务部经理FINANCE和人事部经理HR
  • 用户FINANCE管理工资表,拥有查询、删除、修改工资的权限
  • 用户HR管理员工表,拥有删除员工、添加员工、更新员工信息的权限
②创建两个部门经理用户并授予创建用户的权限

先创建两个用户并给与他们创建用户的权限。

mysql> CREATE USER 'FINANCE'@'%' IDENTIFIED BY '111111';
Query OK, 0 rows affected (0.01 sec)

mysql> GRANT CREATE USER ON *.* TO 'FINANCE'@'%';
Query OK, 0 rows affected (0.01 sec)

mysql> CREATE USER 'HR'@'%' IDENTIFIED BY '222222';
Query OK, 0 rows affected (0.00 sec)

mysql> GRANT CREATE USER ON *.* TO 'HR'@'%';
Query OK, 0 rows affected (0.00 sec)

此时这两个用户只有创建用户的权限,如果它们想查看表,甚至访问数据库都会报错。

mysql> USE TEST_COMPANY
ERROR 1044 (42000): Access denied for user 'FINANCE'@'%' to database 'test_company'
③给予部门经理用户其他权限

Ⅰ 给予两位部门经理用户更新相应表的权限。创建两个角色,然后给这两个角色分别赋予其对应的权限,并将角色权限给用户,同时加上 with grant option 选项,方便其用户赋予员工查询权限。然后将这两个角色赋予部门经理。

CREATE ROLE FIN_ROLE;
GRANT SELECT,DELETE,UPDATE,INSERT ON TABLE SALARY TO FIN_ROLE WITH GRANT OPTION;
GRANT FIN_ROLE TO FINANCE WITH ADMIN OPTION;

CREATE ROLE HR_ROLE;
GRANT SELECT,DELETE,UPDATE,INSERT ON TABLE EMPLOYEE TO HR_ROLE;
GRANT HR_ROLE TO HR WITH ADMIN OPTION;

Ⅱ 这样子仍然会出现问题,两位部门进入数据库还会受到阻拦,即使使用navicat可视化查看其权限,仍然显示不具备该权限。

经杨老师提醒,问题在于GRANT XXX ON TABLE时,具体的TABLE并没有指定该表所在的数据库,因此是失败的。我们需要在授权的同时指定其表所在的数据库,如TEST_COMPANY.SALARY。

Ⅲ 结果仍然发现ROLE上被赋予的权限并没有到达FINANCE上,说明这可能不是主要的问题。

★经过刘lq同学提醒,这个主要问题在于mysql与课本内容的一个区别:激活角色。

★激活角色

一个角色被创造出来并被赋予用户之后,事实上用户并没有立刻获得这个“角色”的权限,因为该角色并没有被激活。只有角色被激活,该用户才能够成功“扮演”这个角色。其实这也是为了提升安全性。

使用

SELECT CURRENT_ROLE();

可以查看当前已经被激活的角色。

有两种激活角色的方法:

#非永久激活
set default role all to FINANCE@'%';

#永久激活
SET global activate_all_roles_on_login=ON;
#由于mysql默认禁止了角色自动激活,我们修改这个系统变量可以将其调整为允许角色自动激活,从此一劳永逸解决这个问题。

我们可以采取第一种方式

在这里插入图片描述

然后退出该命令行,以FINANCE的身份进入mysql数据库(这里我使用win提供的shell终端进行操作)
在这里插入图片描述

现在可以发现该部门经理FINANCE获得了该角色。

Ⅳ 接下来重新对该角色进行授权,授权会自动转交到FINANCE上。

GRANT FIN_ROLE TO FINANCE WITH ADMIN OPTION;

现在该部门经理再请求进入数据库,就不会受到阻拦了。

mysql> use test_company
Database changed
mysql>

Ⅴ 但是这还是有点烦,不能一劳永逸解决问题,所以采用修改系统变量永久激活角色自动激活的功能。

SET global activate_all_roles_on_login=ON;

之后应该就不会再遇到这种问题了。

④使用部门经理创建员工用户

在 FINANCE 财务部经理下创建员工用户,给与查询权限:

CREATE USER U1 IDENTIFIED BY "111111";
GRANT SELECT ON TABLE SALARY TO U1;

这创建了一个员工U1,并有SELECT权限。

接下来进行验证。

⑤验证员工用户权限

验证如下:

重新开启另一个终端,使用用户U1登录

use test_company;
select * from salary;
INSERT INTO SALARY VALUES('甘晴',3000);

运行截图如下:

在这里插入图片描述

可以看到用户 U1 仅有查询权限,不具有修改权限。完全符合预期。

⑥收回员工查看的权限,并验证

使用FINANCE登录sql并收回员工U1的权限

REVOKE SELECT ON SALARY FROM U1;

收回权限后,使用U1登录sql试图查询工资,被拒绝。

如下:
在这里插入图片描述

2.1.2 审计实验

1)实验内容与要求

掌握数据库审计的设置和管理方法,以便监控数据库操作,维护数据库安全。打开数据库审计开关,以具有审计权限的用户登录数据库,设置审计权限,然后以普通用户登录数据库,执行相应的 SQL 语句,验证审计设置是否有效,最后再以具有审计权限的用户登录数据库,查看是否存在相应的审计信息。

2)实验重难点

合理的设置各种审计信息,一方面,为了保护系统重要的敏感数据,需要系统地设置各种审计信息,不能留有漏洞,以便随时监督系统使用情况,一旦出现问题,也便于追查;另一方面,审计信息设置过多,会严重影响数据库的使用性能,因此需要合理设置。

3)实验过程

MySQL不支持语句级审计,只能对所有的SQL使用进行日志记录。

①首先查看审计配置情况:
show variables like '%general_log%';

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

可以看到当前日志的状态(默认是关闭的),以及日志的名称与保存地址(这里没有显示路径,花了点时间查找)

在首次未打开审计之前,文件夹内是没有该log文件的。

路径在E:\MySQL\MySQL Server 8.0\Data\LAPTOP-S8GDLRKI.log
(这个跟自己安装mysql时的地址有关)

②开启日志
SET GLOBAL GENERAL_LOG=ON;

使用该命令打开审计之后,文件夹内可以找到该log文件。

在这里插入图片描述

③验证审计

以没有审计权限的用户进行操作,以上一个实验的部门经理FINANCE为例。先验证该用户并没有有审计的权限,然后进行SELECT操作。

在这里插入图片描述

然后我们打开log文件查看。

在这里插入图片描述

发现该用户的操作确实被记录下来了。

需要指出的是,不同数据库对审计的支持都存在不同。这里只是把审计当作了一个概念,即记录下用户操作的这样一个动作。因此,在这里我们实际上是用日志这个具体的文件去实现了审计这个概念。实际上审计还有其他插件可以支持。

但可以料想得到的是,如果所有操作都被记录下来,那么这个日志文件会变得越来越大,这也是需要考虑的,究竟哪些步骤需要被记录,谁的操作需要被记录,都值得思考,而不是记录下所有的操作。

④关闭日志

为了防止占太多空间,我选择暂时关闭日志。

SET GLOBAL GENERAL_LOG=OFF;

2.2数据库完整性

以下实验将不用TEST_COMPANY表。

2.2.1 实体完整性实验

1)实验内容与要求

定义实体完整性,删除实体完整性。能够写出两种方式定义实体完整性的 SQL 语句:创建表时定义实体完整性、创建表后定义实体完整性。设计SQL 语句验证完整性约束是否起作用。

2)实验重难点

创建表时定义实体完整性,有多个候选码时实体完整性的定义。

3)实验过程
①创建新数据库HNUT2
CREATE DATABASE HNUT2;
②创建表时定义完整性并验证

创建一个学生表,属性包括:学号、姓名、性别、年龄、所在班级,其中学号、

(姓名,所在班级)为候选码,此处设计后者作为候选码,均不允许为空值,性别

只能是男或女,年龄设置小于 25。

Student(sno,name,sex,age,class_num),其中(name,class_num)

做为主码。

CREATE TABLE student(
	Sno CHAR(9) UNIQUE NOT NULL,
    Sname CHAR(20) ,
    Ssex CHAR(2) CHECK(Ssex = '男' OR Ssex = '女'),
    Ssage SMALLINT CHECK(Ssage < 25),
	Sclass CHAR(10),
    PRIMARY KEY(Sname,Sclass)
);

验证完整性约束是否生效:插入一条学生记录,设置年龄为 26:会因为年龄不符合小于 25 的限制而插入失败。

INSERT INTO STUDENT VALUES('202108010','甘晴void','男',26,'CS2');

因为不符合完整性约束,插入的数据被拒绝。

在这里插入图片描述

③创建表之后定义并验证
CREATE TABLE Course(	
	Cno CHAR(9),
	Cname CHAR(20),
    Cpno CHAR(9),
    Ctype CHAR(5),
    Cdept CHAR(20),
    Chours SMALLINT,
    Ccredit SMALLINT
);	
ALTER TABLE Course
ADD CONSTRAINT C1 PRIMARY KEY(Cno);
ALTER TABLE Course
ADD CONSTRAINT C2 CHECK(Cno like "GE%");

创建表之后定义完整性,限制课程号只能是类似"GE%"形式的。

验证完整性约束是否生效:插入2条课程记录,期中一条不合法,一条合法。

INSERT INTO  COURSE VALUES('SGE001234','数据库系统','计算机系统','专业核心','计算机科学系',40,3);

INSERT INTO  COURSE VALUES('GE001234','数据库系统','计算机系统','专业核心','计算机科学系',40,3);

验证截图如下,符合预期。

在这里插入图片描述

④删除实体完整性并验证

如果我们此时把限制课程号只能是类似"GE%"形式的这个实体完整性C2给删去。使用如下指令

ALTER TABLE COURSE DROP CONSTRAINT C2;

再次插入这条本来非法的记录。

INSERT INTO  COURSE VALUES('SGE001234','数据库系统','计算机系统','专业核心','计算机科学系',40,3);

截图如下:
在这里插入图片描述

2.2.2 参照完整性实验

1)实验内容与要求

定义参照完整性,定义参照完整性的违约处理,删除参照完整性。写出两种方式定义参照完整性的 SQL 语句:创建表时定义参照完整性、创建表后定义参照完整性。

2)实验重难点

创建表时定义参照完整性,参照完整性的违约处理定义。

3)实验过程
①创建表时定义参照完整性+验证

创建一个班级表,属性包括姓名,学号,成绩,其中学号作为主码,姓名作为

student 表的外码。

CREATE TABLE Class(	
	Sname CHAR(10),
    Sno CHAR(9) PRIMARY KEY,
    Sgrade SMALLINT,
    FOREIGN KEY(Sname) REFERENCES STUDENT(SNAME)
);	

验证:

先往STUDENT表中成功加入一个学生。

INSERT INTO STUDENT VALUES('202108010','甘晴void','男',20,'CS2');

然后分别试图向Class表中加入一个不合法的学生和一个合法的学生。

INSERT INTO CLASS VALUES('甘晴wolf','202108010',100);
INSERT INTO CLASS VALUES('甘晴void','202108010',100);

截图如下:

在这里插入图片描述

可见不合法的记录因为不满足外键要求而被拒绝。

②创建表后定义参照完整性
CREATE TABLE Class(	
	Sname CHAR(10),
    Sno CHAR(9) PRIMARY KEY,
    Sgrade SMALLINT
);	
ALTER TABLE CLASS 
ADD CONSTRAINT C3 FOREIGN KEY(Sname) REFERENCES STUDENT(SNAME);

验证同上,结果符合预期。

③定义参照完整性的违约处理

删除 student 表中内容时级联删除 class 表中相应内容。

一般的违约处理都是拒绝执行。教材指出,若想让系统采取其他策略,必须在创建参照表的时候显式地加以说明。

CREATE TABLE Class(	
	Sname CHAR(10),
    Sno CHAR(9) PRIMARY KEY,
    Sgrade SMALLINT,
    FOREIGN KEY(Sname) REFERENCES STUDENT(SNAME)
    	ON UPDATE CASCADE
		ON DELETE CASCADE
);	

验证外键在delete上的级联是否生效:

在被参考表STUDENT表插入一条合法学生数据,然后子在参考表插入该学生的成绩信息。

INSERT INTO STUDENT VALUES('202108010','甘晴void','男',20,'CS2');
INSERT INTO CLASS VALUES('甘晴void','202108010',100);

在这里插入图片描述

接着在STUDENT表删除该学生信息,查看CLASS表是否随之发生变化。

DELETE FROM STUDENT WHERE SNAME='甘晴void';

SQL 语句进行验证违约处理是否生效。

在这里插入图片描述

④删除参照完整性

删除参照完整性

ALTER TABLE Course DROP CONSTRAINT C3;

2.2.3 用户自定义完整性实验

1)实验内容与要求

针对具体应用语义,选择 NULL/NOT NULL、DEFAULT,UNIQUE、CHECK 等,定义属性上的约束条件。

2)实验重难点

NULL/NOT NULL, DEFAULT,CHECK。

3)实验过程
①建立完整性约束

创建 source 课程记录表,属性包括学号,姓名,成绩,性别,所在小组,其中学号不能为空且唯一,姓名不能为空,成绩可以为空(期末考之后才会有成绩),性别不能为空,组号限制在 1-10,其中学号为主码。自行设计创建表之后定义完整性约束。

#在定义表时进行完整性约束
CREATE TABLE SOURCE(
	SNO CHAR(9) UNIQUE NOT NULL,
	SNAME CHAR(10) NOT NULL,
	SGRADE SMALLINT,
    SSEX CHAR(2) NOT NULL CHECK(SSEX = '男' OR SSEX = '女'),
	SGROUP SMALLINT CHECK(SGROUP>=1 AND SGROUP<=10),
	PRIMARY KEY(SNO));
	
#在定义表后进行完整性约束补充
#(列级完整性约束非check子句无法表后定义)
CREATE TABLE SOURCE(
	SNO CHAR(9) UNIQUE NOT NULL,
	SNAME CHAR(10) NOT NULL,
	SGRADE SMALLINT,
    SSEX CHAR(2) NOT NULL,
	SGROUP SMALLINT,
	PRIMARY KEY(SNO));
	
ALTER TABLE SOURCE ADD CONSTRAINT C1 CHECK(SSEX = '男' OR SSEX = '女');
ALTER TABLE SOURCE ADD CONSTRAINT C2 CHECK(SGROUP>=1 AND SGROUP<=10);
②验证完整性约束

设计 SQL 语句验证完整性约束:插入时姓名为空会因为违反了完整性约束而无法插入。

INSERT INTO SOURCE VALUES('202108010',NULL,100,'男',2);

运行截图如下:

在这里插入图片描述

③删除完整性约束并验证

试图插入一组不合法的请求(不符合完整性约束C2)

INSERT INTO SOURCE VALUES('202108010','甘晴void',100,'男',22);

删除完整性约束C2

ALTER TABLE SOURCE DROP CONSTRAINT C2;

再次试图插入该请求

运行截图如下:

在这里插入图片描述

在删除该完整性约束之后,该请求能被正常插入了。

2.3 触发器实验

1)实验内容与要求

掌握数据库触发器的设计与使用方法,定义 BEFORE 触发器和 AFTER 触发器,能够理解不同类型触发器的作用和执行原理,验证触发器的有效性。

2)实验重难点

利用触发器实现较为复杂的用户自定义完整性。

3)示例
①创建触发器(以BEFORE为例)

以 before 触发器为例,定义一个 teacher_salary 教师工资表,属性包括 name、job、salary,均不可为空,其中 name 作为主码。

CREATE TABLE TEACHER_SALARY(
	NAME CHAR(10) PRIMARY KEY,
	JOB CHAR(20) NOT NULL,
	SALARY SMALLINT NOT NULL);

Before 触发器定义如下:教授工资不得低于 5000,若低于则自动更改为 5000。

CREATE TRIGGER TS_T
BEFORE INSERT ON TEACHER_SALARY
FOR EACH ROW
BEGIN
    IF NEW.JOB = '教授' AND NEW.SALARY < 5000 THEN
        SET NEW.SALARY = 5000;
    END IF;
END;
★mysql关于触发器的语法区别

特别注意,mysql关于触发器的的语法与教材的不太一致,主要体现在如下:

  • 不需要使用REFERENCING NEW AS NEWTURPLE,而是直接使用NEW来指代新表
  • mysql触发器支持UPDATE,INSERT,DELETE的触发,但不支持它们的逻辑结合,例如UPDATE OR INSERT这样是不可以的,这个跟教材上有一定区别。
  • 赋值语句使用SET而不是:=符号
  • 删除触发器时直接DROP TRIGGER <触发器名>,不需要添加ON <表名>
②验证触发器(以BEFORE为例)

验证如下:

#插入一条数据
INSERT INTO TEACHER_SALARY VALUES('甘晴void','教授',2000);

这条数据的salary是2000,这是不合规的,触发器会自动将它修改为5000.

运行截图如下:

在这里插入图片描述

③验证触发器执行顺序

触发器的执行是由触发事件激活,执行顺序如下:

  • 执行该表上的 before 触发器,
  • 激活触发器上 sql 语句,
  • 执行表上 after 触发器,

对于表上多个 before 触发器,保持谁先创建谁执行原则,也有的是按照触发器名字的排序执行(这个应该就是不同数据库决定的了)

验证触发器的执行顺序可以这样进行:

  • 我们分别创建BEFORE和AFTER触发器
  • 每个触发器触发的时候就在另一个表中存一条记录
  • 我们新建一个表TS_U来存触发器的这种记录

具体过程如下:

#先删除上面那个触发器,

#新建一个表TS_U
CREATE TABLE TS_U(
    NAME CHAR(10),
    JOB CHAR(20),
    SALARY SMALLINT,
    TAG CHAR(10)	#这个TAG我是用来标记记录的产生顺序
);

#创建BEFORE触发器
CREATE TRIGGER TS_T1
BEFORE INSERT ON TEACHER_SALARY
FOR EACH ROW
BEGIN
	IF (NEW.JOB = '教授') AND (NEW.SALARY<5000) THEN
	INSERT INTO TS_U VALUES(NEW.NAME,NEW.JOB,NEW.SALARY,'BEFORE');
	END IF;
END;

#创建AFTER触发器
CREATE TRIGGER TS_T2
AFTER INSERT ON TEACHER_SALARY
FOR EACH ROW
BEGIN
	IF (NEW.JOB = '教授') AND (NEW.SALARY<5000) THEN
	INSERT INTO TS_U VALUES(NEW.NAME,NEW.JOB,NEW.SALARY,'AFTER');
	END IF;
END;

#插入一条数据
INSERT INTO TEACHER_SALARY VALUES('甘晴wolf','教授',3000);

验证截图如下:

在这里插入图片描述

我们排除顺序的影响,交换BEFORE触发器和AFTER触发器的定义顺序,再试一次。结果如下:

在这里插入图片描述

可以发现仍然没有变化,说明的确是BEFORE触发器在AFTER触发器之前执行。

④删除触发器

注意与书上的语法区别,不需要指明所在表。

DROP TRIGGER TS_T1;

实验感悟

实践和理论还是有很大的差别的,特别是数据库的实验。先不说书上的一般范式和mysql数据库自己的“方言”的区别,仅仅是把一样的行为搬到数据库中就有可能产生好多好多的问题,比如mysql触发器的定义就不一样,从格式到作用范围都有差异。再比如说mysql的激活角色,这是很难想到的,这也是教材和mysql实际的一个很大的区别。如果不经过同学的提醒,我可能一直会卡在这里。作为一个初学者,跟着书本上做,就是做不出预期的效果,然后就会以为这是bug,心态非常崩,而且找不到错误的原因,会非常沮丧和气恼。从这里我有一个感悟就是,做实验的时候还是不能仅仅看书,得先研究mysql提供的手册,遇到问题别先怀疑是bug,先查手册。

可惜的是这一周的实验和作业太多了,还有期中考试等,以至于我没有足够的实践对mysql手册进行足够深入的了解。希望以后在项目实战(OceanBase数据库项目)中对数据库系统进行更多的研究。

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

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

相关文章

verilog语法进阶-分布式ram原语

概述 官方提供的原语 RAM16X1S_1 #(.INIT(16h0000) // Initial contents of RAM) RAM16X1S_1_inst (.O(O), // RAM output.A0(A0), // RAM address[0] input.A1(A1), // RAM address[1] input.A2(A2), // RAM address[2] input.A3(A3), // RAM address[3…

数据结构-迷宫问题

文章目录 1、题目描述2、题目分析3、代码实现 1、题目描述 题目链接&#xff1a;迷宫问题 、 注意不能斜着走&#xff01; 2、题目分析 &#xff08;1&#xff09;0为可以走&#xff0c;1不能走且只有唯一一条通路 &#xff08;2&#xff09;我们可以通过判断上下左右来确定…

基于ssm电子资源管理系统源码和论文

idea 数据库mysql5.7 数据库链接工具&#xff1a;navcat,小海豚等 环境&#xff1a; jdk8 tomcat8.5 基于ssm电子资源管理系统源码和论文758 摘要 随着互联网技术的高速发展&#xff0c;人们生活的各方面都受到互联网技术的影响。现在人们可以通过互联网技术就能实现不出家门…

微信公众号怎样使用文章模版?怎样建立文章模版 公众号模版示例 如何使用

打开我们的微信公众平台并登陆&#xff0c;找到我们的管理->素材管理 如图所示 2 在新建图文素材的右边有三个点&#xff0c;我们把鼠标移动到此处并点击 我们会看到新建分享图文和管理图文模版 选中并点击管理图文模版 如图所示 3 我们会看到如下界面 如图所示 4 …

【C++入门到精通】 线程库 | thread类 C++11 [ C++入门 ]

阅读导航 引言一、thread类的简单介绍二、线程函数详细介绍1. start() 函数&#xff08;1&#xff09;头文件&#xff08;2&#xff09;函数原型 2. join() 函数&#xff08;1&#xff09;头文件&#xff08;2&#xff09;函数原型 3. detach() 函数&#xff08;1&#xff09;头…

列表优先于数组

在Java中&#xff0c;列表&#xff08;List&#xff09;通常优于数组&#xff0c;因为列表提供了更灵活的操作和动态调整大小的能力。下面是一个例子&#xff0c;展示了为什么在某些情况下使用列表比数组更好&#xff1a; import java.util.ArrayList; import java.util.List;…

交友网站的设计与实现(源码+数据库+论文+开题报告+说明文档)

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

1125矩阵乘法(C语言)

一&#xff1a;题目 二&#xff1a;思路分析 1.对于学习过线性代数的人来说&#xff0c;对应公式十分熟悉&#xff0c;而对于没接触过线性代数的人来说&#xff0c;我们地一步要做的是从题目所给的公式中找规律 2.这个题目&#xff0c;给了我们三个变量n&#xff0c;m&#xf…

图扑物联 | WEB组态可视化软件

什么是组态&#xff1f; 组态的概念来自于20世纪70年代中期出现的第一代集散控制系统&#xff08;Distributed Control System&#xff09;&#xff0c;可理解为“配置”、“设置”等&#xff0c;是指通过人机开发界面&#xff0c;用类似“搭积木”的简单方式来搭建软件功能&a…

运营微信视频号要注意哪些问题?

视频号运营的5个雷点你别踩! 今天和你说的视频号运营的5大雷点 你踩过没? 这5点虽然和野花似的 但也不能踩哦 雷点1:违规行为 雷点2:抄袭剽窃 雷点3:没有明确目标受众 雷点4:短视频质量过低 雷点5:缺少社交互动 相信不管是视频号还是别的平台都通用哈

QML中Image动态显示图片内容

1.定义一个ColorImageProvider类 #ifndef COLORIMAGEPROVIDER_H #define COLORIMAGEPROVIDER_H#include <QObject> #include <QImage> #include <QQuickImageProvider>#include <QTimer>class ColorImageProvider :public QObject, public QQuickImag…

26.Java安卓程序设计-基于SSM框架Android的网店系统设计与实现

1. 引言 1.1 背景 介绍网店系统的背景&#xff0c;说明为什么设计这个系统以及系统的重要性。 1.2 研究目的 阐述设计基于SSM框架的Android网店系统的目标和意义。 2. 需求分析 2.1 行业背景 分析网店行业的特点和需求&#xff0c;以及目前市场上同类系统的不足之处。 …

docker consul 容器的自动发现与注册

consul相关知识 什么是注册与发现 服务注册与发现是微服务架构中不可或缺的重要组件。起初服务都是单节点的&#xff0c;不保障高可用性&#xff0c;也不考虑服务的压力承载&#xff0c;服务之间调用单纯的通过接口访问。直到后来出现了多个节点的分布式架构&#xff0c;起初的…

基于ssm果蔬经营平台系统源码和论文

首先,论文一开始便是清楚的论述了系统的研究内容。其次,剖析系统需求分析,弄明白“做什么”,分析包括业务分析和业务流程的分析以及用例分析,更进一步明确系统的需求。然后在明白了系统的需求基础上需要进一步地设计系统,主要包罗软件架构模式、整体功能模块、数据库设计。本项…

Pygame游戏实战九:跳跃小游戏

介绍模块 本游戏使用的是由Pycharm中的pygame模块来实现的&#xff0c;也可以在python中运行。通过Pygame制作一个类似与跳跃游戏&#xff0c;但在游戏中并没有进行跳跃&#xff0c;而是通过键盘进行控制。 最小开发框架 详情请看此文章&#xff1a;Pygame游戏模块介绍二&am…

在4*4的平面上计算2a1+1+1

0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 1 在4*4的平面上有2个点&#xff0c;保持2a1的结构&#xff0c;然后向剩余的14个格子里随机扔2个石子。 共有14*13/291种可能 1 - - - 2 - - - 3 - - 1 4 - - - 1 1 - 1 1 - - - - - - - 1 - - …

生产环境_Apache Spark技术大牛的实践:使用DataFrame API计算唯一值数量并展示技术(属性报告)

业务背景 给前端提供算法集成好的数据&#xff0c;对算法处理后的数据进行进一步删选展示 可以使用下面代码运行一下看看结果&#xff0c;听有趣的&#xff0c;我写的代码中计算了不同字段的值的数量&#xff0c;并生成了一个显示字符串来描述这些数据的分布情况然后使用"…

Druid-spring-boot-starter源码阅读-其余组件自动装配

前面我们看完了整个DruidDataSource初始化流程&#xff0c;但是其实Druid除了最核心的数据源之外&#xff0c;还有其他需要自动配置的&#xff0c;细心的人可能看到了&#xff0c;就是利用Import注解导入的四个类。 DruidFilterConfiguration public class DruidFilterConfigu…

【Leetcode】相同的树、对称二叉树、另一颗树的子树

相同的树 思路&#xff1a; 这个题目实际上可以分解为许多个相同的子问题&#xff0c;就是检查每一个子树是否相同&#xff0c;然后便可以利用递归的思想来解答。 代码&#xff1a; bool isSameTree(struct TreeNode* p, struct TreeNode* q) {if(pNULL&&qNULL)return…

C++核心编程思路(1):①程序的内存模型②引用的作用

文章目录 前言一、不同的存储类型变量&#xff0c;会被存储在什么区&#xff1f;①const修饰的局部变量放在栈区&#xff0c;全局变量放在只读数据区。②static修饰的全局和局部变量都放在静态区&#xff08;即数据区中的一个小区&#xff09; 二、栈区1.如果在函数A中定义了一…