MySQL视图

视图

1.视图概述

视图是由数据库中的一个表或多个表导出的虚拟表,方便用户对数据的操作。本节将详细讲解视图的概念及作用。

2.视图的概念

视图是一个虚拟表,是从数据库中一个或多个表中导出来的表,其内容由查询定义。同真实的表一样,视图包含一系列带有名称的列和行数据。但是,数据库中只存放了视图的定义,而并没有存放视图中的数据。这些数据存放在原来的表中。使用视图查询数据时,数据库系统会从原来的表中取出对应的数据。因此,视图中的数据是依赖于原来的表中的数据的。一旦表中的数据发生改变,显示在视图中的数据也会发生改变。
视图是存储在数据库中的查询的SQL语句,它主要出于两种原因:安全原因,视图可以隐藏一些数据,例如,员工信息表,可以用视图只显示姓名、工龄、地址,而不显示社会保险号和工资数等;另一个原因是可使复杂的查询易于理解和使用。

3.视图的作用

对其中所引用的基础表来说,视图的作用类似于筛选。定义视图的筛选可以来自当前或其他数据库的一个或多个表,或者其他视图。通过视图进行查询没有任何限制,通过它们进行数据修改时的限制也很少。下面将视图的作用归纳为如下几点。

1.简单性

看到的就是需要的。视图不仅可以简化用户对数据的理解,也可以简化他们的操作。那些被经常使用的查询可以被定义为视图,从而使得用户不必为以后的操作每次指定全部的条件。

2.安全性

视图的安全性可以防止未授权用户查看特定的行或列,使有权限用户只能看到表中特定行的方法如下。
(1)在表中增加一个标志用户名的列。
(2)建立视图,使用户只能看到标有自己用户名的行。
(3)把视图授权给其他用户。

3.逻辑数据独立性

视图可以使应用程序和数据库表在一定程度上独立。如果没有视图,程序一定是建立在表上的。有了视图之后,程序可以建立在视图之上,从而程序与数据库表被视图分割开来。视图可以在以下几个方面使程序与数据独立。
(1)如果应用建立在数据库表上,当数据库表发生变化时,可以在表上建

(1)如果应用建立在数据库表上,当数据库表发生变化时,可以在表上建立视图,通过视图屏蔽表的变化,从而使应用程序可以不动。
(2)如果应用建立在数据库表上,当应用发生变化时,可以在表上建立视图,通过视图屏蔽应用的变化,从而使数据库表不动。
(3)如果应用建立在视图上,当数据库表发生变化时,可以在表上修改视图,通过视图屏蔽表的变化,从而使应用程序可以不动。
(4)如果应用建立在视图上,当应用发生变化时,可以在表上修改视图,通过视图屏蔽应用的变化,从而使数据库可以不动。

4.创建视图

创建视图是指在已经存在的数据库表上建立视图,视图可以建立在一张表中,也可以建立在多张表中。本节主要讲解创建视图的方法。

1.查看创建视图的权限

创建视图需要具有CREATE VIEW的权限,同时应该具有查询涉及的列的SELECT权限。可以使用SELECT语句来查询这些权限信息,查询语法如下。

1
SELECT Selete_priv,Create_view_priv FROM mysql.user WHERE user='用户名';

(1)Selete_priv属性表示用户是否具有SELECT权限,Y表示拥有SELECT权限,N表示没有。
(2)Create_view_priv属性表示用户是否具有CREATE VIEW权限;mysql.user表示MySQL数据库下面的user表。
(3)“用户名”参数表示要查询是否拥有DROP权限的用户,该参数需要用单引号引起来。
【例1】 下面查询MySQL中root用户是否具有创建视图的权限,代码如下。

1
SELECT Select_priv,Create_view_priv FROM mysql.user WHERE user='root';
2.创建视图的步骤

MySQL中,创建视图是通过CREATE VIEW语句实现的,其语法如下。

1
2
3
4
5
6
CREATE [ALGORITHM={
UNDEFINED|MERGE|TEMPTABLE}]
VIEW 视图名[(属性清单)]
AS SELECT语句
[WITH [CASCADED|LOCAL] CHECK OPTION];
}

(1)ALGORITHM是可选参数,表示视图选择的算法;
(2)“视图名”参数表示要创建的视图名称;
(3)“属性清单”是可选参数,指定视图中各个属性的名词,默认情况下与SELECT语句中查询的属性相同;
(4)SELECT语句参数是一个完整的查询语句,表示从某个表中查出某些满足条件的记录,将这些记录导入视图中;
(5)WITH CHECK OPTION是可选参数,表示更新视图时要保证在该视图的权限范围之内。
【例2】在数据表tb_book中创建view1视图,视图命名为book_view1,并设置视图属性分别为a_sort、a_talk、a_books,代码如下。

1
CREATE VIEWbook_view1(a_sort,a_talk,a_books)AS SELECT sort,talk,booksFROM tb_book;
3.创建视图的注意事项

创建视图时需要注意以下几点。
(1)运行创建视图的语句需要用户具有创建视图(create view)的权限,若加了[or replace]时,还需要用户具有删除视图(drop view)的权限。
(2)SELECT语句不能包含FROM子句中的子查询。
(3)SELECT语句不能引用系统或用户变量。
(4)SELECT语句不能引用预处理语句参数。
(5)在存储子程序内,定义不能引用子程序参数或局部变量。
(6)在定义中引用的表或视图必须存在。但是,创建了视图后,能够舍弃定义引用的表或视图。要想检查视图定义是否存在这类问题,可使用CHECK TABLE语句。
(7)在定义中不能引用temporary表,不能创建temporary视图。
(8)在视图定义中命名的表必须已存在。
(9)不能将触发程序与视图关联在一起。
(10)在视图定义中允许使用order by,但是,如果从特定视图进行了选择,而该视图使用了具有自己order by的语句,它将被忽略。

5.视图操作

1.查看视图

查看视图是指查看数据库中已存在的视图。查看视图必须要有SHOW VIEW的权限。查看视图的方法主要包括DESCRIBE语句、SHOW TABLE STATUS语句、SHOW CREATE VIEW语句等。本节将主要介绍这几种查看视图的方法。
(1)DESCRIBE语句
DESCRIBE可以缩写成DESC,其语法格式如下。

1
DESCRIBE 视图名;

使用DESC语句查询book_view1视图中的结构
结果中显示了字段的名称(Field)、数据类型(Type)、是否为空(Null)、是否为主外键(Key)、默认值(Default)和额外信息(Extra)。
说明
如果只需了解视图中的各个字段的简单信息,可以使用DESCRIBE语句。DESCRIBE语句查看视图的方式与查看普通表的方式是相同的,结果显示的方式也相同。通常情况下,都是使用DESC代替DESCRIBE。
(2)SHOW TABLE STATUS语句
在MySQL中,可以使用SHOW TABLE STATUS语句查看视图的信息,其语法格式如下。
SHOW TABLE STATUS LIKE ‘视图名’;
(1)“LIKE”表示后面匹配的是字符串;
(2)“视图名”参数指要查看的视图名称,需要用单引号定义。
【例3】下面使用SHOW TABLE STATUS语句查看视图book_view1中的信息,代码如下。

1
SHOW TABLE STATUS LIKE 'book_view1';

从执行结果可以看出,存储引擎、数据长度等信息都显示为NULL,则说明视图为虚拟表,与普通数据表是有区别的。下面使用SHOW TABLE STATUS语句来查看tb_book表的信息。。
使用SHOW TABLE STATUS语句来查看tb_book表的信息
从上面的结果中可以看出,数据表的信息都已经显示出来了,这就是视图和普通数据表的区别。
(3)SHOW CREATE VIEW语句
在MySQL中,SHOW CREATE VIEW语句可以查看视图的详细定义,其语法格式如下。

1
SHOW CREATE VIEW 视图名;

【例4】 下面使用SHOW CREATE VIEW语句查看视图book_view1的信息,代码如下。

1
SHOW CREATE VIEW book_view1;

通过SHOW CREATE VIEW语句,可以查看视图的所有信息。

2.修改视图

修改视图是指修改数据库中已存在的表的定义。当基本表的某些字段发生改变时,可以通过修改视图来保持视图和基本表之间一致。MySQL中通过CREATE OR REPLACE VIEW语句和ALTER语句来修改视图。下面介绍这两种修改视图的方法。
1.CREATE OR REPLACE VIEW
在MySQL中,CREATE OR REPLACE VIEW语句可以用来修改视图。该语句的使用非常灵活。在视图已经存在的情况下,对视图进行修改;视图不存在时,可以创建视图。CREATE OR REPLACE VIEW语句的语法如下。

1
2
3
CREATE OR REPLACE [ALGORITHM={
UNDEFINED | MERGE | TEMPTABLE}]
VIEW 视图[(属性清单)]AS SELECT 语句[WITH [CASCADED | LOCAL] CHECK OPTION];

2.ALTER
ALTER VIEW语句改变了视图的定义,包括被索引视图,但不影响所依赖的存储过程或触发器。该语句与CREATE VIEW语句有着同样的限制,如果删除并重建了一个视图,就必须重新为它分配权限。
ALTER VIEW语句的语法如下。

1
alter view [algorithm={merge | temptable | undefined} ]view view_name [(column_list)] as select_statement[with[cascaded | local] check option]

(1)algorithm:该参数已经在创建视图中做了介绍,这里不再赘述。
(2)view_name:视图的名称。
(3)select_statement: SQL语句用于限定视图。
注意
在创建视图时,在使用了WITH CHECK OPTION, WITH ENCRYPTION,WITH SCHEMABING或VIEW_METADATA选项时,如果想保留这些选项提供的功能,必须在ALTER VIEW语句中将它们包括进去。

3.更新视图

对视图的更新其实就是对表的更新,更新视图是指通过视图来插入(INSERT)、更新(UPDATE)和删除(DELETE)表中的数据。因为视图是一个虚拟表,其中没有数据。通过视图更新时,都是转换到基本表来更新。更新视图时,只能更新权限范围内的数据,超出了范围,就不能更新。本节讲解更新视图的方法和更新视图的限制。
1.更新视图
2.更新视图的限制
并不是所有的视图都可以更新,以下几种情况是不能更新视图的。
(1)视图中包含COUNT()、SUM()、MAX()和MIN()等函数。例如:
CREATE VIEW book_view1(a_sort,a_book)AS SELECT sort,books, COUNT(name) FROM tb_book;

(2)视图中包含UNION、UNION ALL、DISTINCT、GROUP BY和HAVIG等关键字。例如:
CREATE VIEW book_view1(a_sort,a_book)AS SELECT sort,books, FROM tb_book GROUP BY id;
(3)常量视图。例如:
CREATE VIEW book_view1AS SELECT ‘Aric’ as a_book;
(4)视图中的SELECT中包含子查询。例如:
CREATE VIEW book_view1(a_sort)AS SELECT (SELECT name FROM tb_book);
(5)由不可更新的视图导出的视图。例如:
CREATE VIEW book_view1AS SELECT * FROM book_view2;
(6)创建视图时,ALGORITHM为TEMPTABLE类型。例如:
CREATE ALGORITHM=TEMPTABLEVIEW book_view1AS SELECT * FROM tb_book;
(7)视图对应的表上存在没有默认值的列,而且该列没有包含在视图里。例如,表中包含的name字段没有默认值,但是视图中不包括该字段,那么这个视图是不能更新的。因为,在更新视图时,这个没有默认值的记录将没有值插入,也没有NULL值插入。数据库系统是不会允许这样的情况出现的,其会阻止这个视图更新。
上面的几种情况其实就是一种情况,即视图的数据和基本表的数据不一样了。
注意
视图中虽然可以更新数据,但是有很多的限制。一般情况下,最好将视图作为查询数据的虚拟表,而不要通过视图更新数据。因为,使用视图更新数据时,如果没有全面考虑在视图中更新数据的限制,可能会造成数据更新失败。

4.删除视图

删除视图是指删除数据库中已存在的视图。删除视图时,只能删除视图的定义,不会删除数据。MySQL中,使用DROP VIEW语句来删除视图。但是,用户必须拥有DROP权限。本节将介绍删除视图的方法。
DROP VIEW语句的语法如下。

1
DROP VIEW IF EXISTS <视图名> [RESTRICT | CASCADE]

(1)IF EXISTS参数指判断视图是否存在,如果存在则执行,不存在则不执行。
(2)“视图名”列表参数表示要删除的视图的名称和列表,各个视图名称之间用逗号隔开。
该语句从数据字典中删除指定的视图定义;如果该视图导出了其他视图,则使用CASCADE级联删除,或者先显式删除导出的视图,再删除该视图;删除基表时,由该基表导出的所有视图定义都必须显式删除。
【例5】下面删除前面实例中一直使用的book_view1视图,执行语句如下。

1
DROP VIEW IF EXISTS book_view1;

执行结果显示删除成功。下面验证一下视图是否真正被删除,执行SHOW CREATE VIEW语句查看。

结果显示,视图book_view1已经不存在了,说明DROP VIEW语句删除视图成功。

6.小结

本章对MySQL数据库的视图的含义和作用进行了详细讲解,并且讲解了创建视图、修改视图和删除视图的方法。创建视图和修改视图是本章的重点内容,并且需要在计算机上实际操作。读者在创建视图和修改视图后,一定要查看视图的结构,以确保创建和修改的操作正确。更新视图是本章的一个难点,因为实际中存在一些造成视图不能更新的因素,希望可以在练习中认真分析。

huang2024-4-15-2024-4-21周报

本周学习大纲

1.MySQL学习

2.Java笔记整理

3.日周笔记

本周学习日历

日期 学习内容 其他
星期一 视图概述 \
星期二 Java笔记 \
星期三 创建视图 \
星期四 c题目 \
星期五 \ 日周笔记
星期六 Java笔记 \
星期日 视图操作 \

本周学习内容及收获

1.MySQL笔记

https://snail0220.github.io/2024/04/21/MySQL%E8%A7%86%E5%9B%BE/

2.Java笔记

https://snail0220.github.io/2024/04/08/java/

3.日周笔记

image-20240421122925872

4.C题目

image-20240421123049515

总结

本周的学习一如既往地缓慢且进行着,本周除了Java笔记的整理和MySQL的学,还进行了C语言第五单元的刷题。总体而言,本周的学习较为充足,对Java基础的认识也越来越完善,学完全部,再进行笔记整理,确实可以获得更多的知识。

下周学习

1.mysql学习

2.Java笔记整理

3.日周笔记

MySQL索引

索引

1.索引概述

1.1 MySQL索引概述

​ 索引是一种将数据库中单列或者多列的值进行排序的结构。应用索引,可以大幅度提高查询的速度。
​ 用户通过索引查询数据,不但可以提高查询速度,也可以降低服务器的负载。用户查询数据时,系统可以不必遍历数据表中的所有记录,而是查询索引列。一般过程的数据查询是通过遍历全部数据,并寻找数据库中的匹配记录而实现的。与一般形式的查询相比,索引就像一本书的目录。而当用户通过目录查找书中内容时,就好比用户通过目录查询某章节的某个知识点。这样就为用户在查找内容过程中,缩短大量时间,帮助用户有效地提高查找速度。所以,使用索引可以有效地提高数据库系统的整体性能。
​ 应用MySQL数据库时,并非用户在查询数据的时候,总需要应用索引来优化查询。凡事都有双面性,使用索引可以提高检索数据的速度,对于依赖关系的子表和父表之间的联合查询时,可以提高查询速度,并且可以提高整体的系统性能。但是,创建索引和维护需要耗费时间,并且该耗费时间与数据量的大小成正比;另外,索引需要占用物理空间,给数据的维护造成很多麻烦。
​ 整体来说,索引可以提高查询的速度,但是会影响用户操作数据库的插入操作。因为,向有索引的表中插入记录时,数据库系统会按照索引进行排序。所以,用户可以将索引删除后,插入数据,当数据插入操作完成后,用户可以重新创建索引。

​ 说明:
​ 不同的存储引擎定义每个表的最大索引数和最大索引长度。所有存储引擎对每个表至少支持16个索引。总索引长度至少为256字节。有些存储引擎支持更多的索引数和更大的索引长度。索引有两种存储类型,包括B树(BTREE)索引和哈希(HASH)索引。其中,B树为系统默认索引方法。

1.2 MySQL索引分类

​ MySQL的索引包括普通索引、唯一性索引、全文索引、单列索引、多列索引和空间索引等。

1.普通索引

​ 普通索引,即不应用任何限制条件的索引,该索引可以在任何数据类型中创建。字段本身的约束条件可以判断其值是否为空或唯一。创建该类型索引后,用户在查询时,便可以通过索引进行查询。在某数据表的某一字段中,建立普通索引后。用户需要查询数据时,只需根据该索引进行查询即可。

2.唯一性索引

​ 使用UNIQUE参数可以设置唯一索引。创建该索引时,索引的值必须唯一,通过唯一索引,用户可以快速定位某条记录,主键是一种特殊唯一索引。

3.全文索引

​ 使用FULLTEXT参数可以设置索引为全文索引。全文索引只能创建在CHAR、VARCHAR或者TEXT类型的字段上。查询数据量较大的字符串类型的字段时,使用全文索引可以提高查询速度。例如,查询带有文章回复内容的字段,可以应用全文索引方式。需要注意的是,在默认情况下,应用全文搜索大小写不敏感。如果索引的列使用二进制排序后,可以执行大小写敏感的全文索引。

4.单列索引

​ 顾名思义,单列索引即只对应一个字段的索引。其可以包括上述叙述的3种索引方式。应用该索引的条件只需要保证该索引值对应一个字段即可。

5.多列索引

​ 多列索引是在表的多个字段上创建一个索引。该索引指向创建时对应的多个字段,用户可以通过这几个字段进行查询。要想应用该索引,用户必须使用这些字段中的第一个字段。

6.空间索引

​ 使用SPATIAL参数可以设置索引为空间索引。空间索引只能建立在空间数据类型上,这样可以提高系统获取空间数据的效率。MySQL中只有MyISAM存储引擎支持空间检索,而且索引的字段不能为空值。

2. 创建索引

​ 创建索引是指在某个表中至少一列中建立索引,以便提高数据库性能。其中,建立索引可以提高表的访问速度。本节通过几种不同的方式创建索引。其中包括在建立数据库时创建索引、在已经建立的数据表中创建索引和修改数据表结构创建索引。

2.1 在建立数据表时创建索引

​ 在建立数据表时可以直接创建索引,这种方式比较直接,且方便、易用。在建立数据表时创建索引的基本语法结构如下。

1
2
3
4
5
6
7
8
create table table_name(
属性名 数据类型[约束条件],
属性名 数据类型[约束条件]
...
属性名 数据类型
[UNIQUE | FULLTEXT | SPATIAL ] INDEX }KEY
[别名]( 属性名1 [(长度)] [ASC | DESC])
);

​ 其中,属性名后的属性值,其含义如下。
(1)UNIQUE:可选项,表明索引为唯一性索引。
(2)FULLTEXT:可选项,表明索引为全文搜索。
(3)SPATIAL:可选项,表明索引为空间索引。
​ INDEX和KEY参数用于指定字段索引,用户在选择时,只需要选择其中的一种即可;另外别名为可选项,其作用是给创建的索引取新名称;别名的参数如下。
(1)属性名1:指索引对应的字段名称,该字段必须被预先定义。
(2)长度:可选项,指索引的长度,必须是字符串类型才可以使用。
(3)ASC/DESC:可选项,ASC表示升序排列,DESC参数表示降序排列。

1.普通索引创建

​ 创建普通索引,即不添加UNIQUE、FULLTEXT等任何参数。

​ 下面创建表名为score的数据表,并在该表的id字段上建立索引,其主要代码如下:

1
2
3
4
5
6
7
8
create table score(
id int(11) auto_increment primary key not null,
name varchar(50) not null,
math int(5) not null,
english int(5) not null,
chinese int(5) not null,
index(id)
);

​ 在命令提示符中使用SHOW CREATE TABLE语句查看该表的结构,在命令提示符中输入的代码如下。

1
show create table score;
2.创建唯一性索引

​ 创建唯一性索引与创建一般索引的语法结构大体相同,但是在创建唯一索引的时候,需要使用UNIQUE参数进行约束。
​ 创建一个表名为address的数据表,并指定该表的id字段上建立唯一索引,其代码如下所示。

1
2
3
4
5
6
create table address(
id int(11) auto_increment primary key not null,
name varchar(50),
address varchar(200),
UNIQUE INDEX address(id ASC)
);

​ 说明
​ 虽然添加唯一索引可以约束字段的唯一性,但是有时候并不能提高用户查找速度,即不能实现优化查询目的。所以,读者在使用过程中需要根据实际情况来选择唯一索引。

3.创建全文索引

​ 与创建普通索引和唯一索引不同,全文索引的创建只能作用在CHAR、VARCHAR、TEXT类型的字段上。创建全文索引需要使用FULLTEXT参数进行约束。
​  创建一个名称为cards的数据表,并在该表的number字段上创建全文索引,其代码如下。

1
2
3
4
5
create table cards(
id int(11) auto_increment primary key not null,
name varchar(50),number bigint(11),
info varchar(50),
FULLTEXT KEY cards_info(info)) engine=MyISAM;

​ 在命令提示符中应用SHOW CREATE TABLE语句查看表结构,其代码如下。

1
SHOW CREATE TABLE cards;
    说明
    只有MyISAM类型的数据表支持FULLTEXT全文索引,InnoDB或其他类型的数据表不支持全文索引。当用户在建立全文索引的时候,返回“ERROR 1283 (HY000): Column 'number' cannot be part of FULLTEXT index”的错误,则说明用户操作的当前数据表不支持全文索引,即不为MyISAM类型的数据表。
4.创建单列索引

​ 创建单列索引,即在数据表的单个字段上创建索引。创建该类型索引不需要引入约束参数,用户在建立时只需指定单列字段名,即可创建单列索引。
例11.4 创建名称为telephone的数据表,并指定在tel字段上建立名称为tel_num的单列索引,其代码如下。

1
2
3
4
5
6
create table telephone(
id int(11) primary key auto_increment not null,
name varchar(50) not null,
tel varchar(50) not null,
index tel_num(tel(20))
);

​ 运行上述代码后,应用SHOW CREATE TABLE语句查看表的结构。
​ 说明
​ 数据表中的字段长度为50,而创建的索引的字段长度为20,这样做的目的是为了提高查询效率,优化查询速度。

5.创建多列索引

​ 与创建单列索引相仿,创建多列索引即指定表的多个字段即可实现。
例11.5 创建名称为information的数据表,并指定name和sex为多列索引,其代码如下。

1
2
3
4
5
6
7
create table information(
id int(11) auto_increment primary key not null,
name varchar(50) not null,
sex varchar(5) not null,
birthday varchar(50) not null,
INDEX info(name,sex)
);

​ 应用SHOW CREATE TABLE语句查看创建多列的数据表结构。
​ 需要注意的是,在多列索引中,只有查询条件中使用了这些字段中的第一个字段(即上面示例中的name字段)时,索引才会被使用。
​ 说明
​ 触发多列索引的条件是用户必须使用索引的第一字段,如果没有用到第一字段,则索引不起任何作用,用户想要优化查询速度,可以应用该类索引形式。

6.创建空间索引

​ 创建空间索引时,需要设置SPATIAL参数。同样,必须说明的是,只有MyISAM类型表支持该类型索引。而且,索引字段必须有非空约束。
​  创建一个名称为list的数据表,并创建一个名为listinfo的空间索引,其代码如下。

1
2
3
4
5
create table list(
id int(11) primary key auto_increment not null,
goods geometry not null,
SPATIAL INDEX listinfo(goods)
)engine=MyISAM;

​ 运行上述代码,创建成功后,在命令提示符中应用SHOW CREATE TABLE语句查看表的结构。
​ 说明
​ 空间类型除了上述示例中提到的GEOMETRY类型外,还包括如POINT、LINESTRING、POLYGON等类型。这些空间数据类型在平常的操作中很少被用到。

2.2 在已建立的数据表中创建索引

​ 在MySQL中,不但可以在用户创建数据表时创建索引,用户也可以直接在已经创建的表中,在已经存在的一个或几个字段上创建索引。其基本的命令结构如下所示。

1
2
CREATE [UNIQUE | FULLTEXT |SPATIAL ] INDEX index_name
ON table_name(属性 [(length)] [ ASC | DESC]);

​ 命令的参数说明如下:
(1)index_name为索引名称,该参数作用是给用户创建的索引赋予新的名称。
(2)table_name为表名,即指定创建索引的表名称。
(3)可选参数,指定索引类型,包括UNIQUE(唯一索引)、FULLTEXT(全文索引)、SPATIAL(空间索引)。
(4)属性参数,指定索引对应的字段名称。该字段必须已经预存在用户想要操作的数据表中,如果该数据表中不存在用户指定的字段,则系统会提示异常。
(5)length为可选参数,用于指定索引长度。
(6)ASC和DESC参数,指定数据表的排序顺序。
与建立数据表时创建索引相同,在已建立的数据表中创建索引同样包含6种索引方式。

1.创建普通索引

​  首先,应用SHOW CREATE TABLE语句查看studentinfo表的结构。
​ 然后,在该表中创建名称为stu_info的普通索引,在命令提示符中输入如下命令。

1
create INDEX stu_info ON studentinfo(sid);

​ 输入上述命令后,应用SHOW CREATE TABLE语句查看该数据表的结构。

2.创建唯一索引

​ 在已经存在的数据表中建立唯一索引的命令如下。

1
CREATE UNIQUE INDEX 索引名 ON 数据表名称(字段名称);

​ 其中,UNIQUE是用来设置索引唯一性的参数,该表中的字段名称既可以存在唯一性约束,也可以不存在唯一性约束。

3.创建全文索引

在MySQL中,为已经存在的数据表创建全文索引的命令如下。

1
CREATE FULLTEXT INDEX 索引名 ON 数据表名称(字段名称);

​ 其中,FULLTEXT用来设置索引为全文索引。操作的数据表类型必须为MyISAM类型。字段类型必须为VARCHAR、CHAR、TEXT等类型。

4.创建单列索引

​ 与建立数据表时创建单列索引相同,用户可以设置单列索引。其命令结构如下。

1
ALTER TABLE 表名 ADD  INDEX 索引名称(字段名称(长度));

​ 同样,用户可以设置字段名称长度,以便优化查询速度,提高执行效率。

5.添加多列索引

​ 添加多列索引与建立单列索引类似。其主要命令结构如下。

1
ALTER TABLE 表名 ADD  INDEX 索引名称(字段名称1,字段名称2,…);

​ 使用ALTER修改数据表结构同样可以添加多列索引。与建立数据表时创建多列索引相同,当创建多列索引时,用户必须使用第一字段作为查询条件,否则索引不能生效。

6.添加空间索引

​ 添加空间索引,用户需要应用SPATIAL参数作为约束条件。其命令结构如下。

1
ALTER TABLE 表名 ADD  SPATIAL INDEX 索引名称(字段名称);

​ 其中,SPATIAL用来设置索引为空间索引。用户要操作的数据表类型必须为MyISAM类型,并且字段名称必须存在非空约束,否则将不能正常创建空间索引。

3. 删除索引

​ 在MySQL中,创建索引后,如果用户不再需要该索引,则可以删除指定表的索引。因为这些已经被建立且不常使用的索引,一方面可能会占用系统资源,另一方面也可能导致更新速度下降,这极大地影响了数据表的性能。所以,在用户不需要该表的索引时,可以手动删除指定索引。其中,删除索引可以通过DROP语句来实现。其基本的命令如下。

1
DROP INDEX index_name ON table_name;

​ 其中,参数index_name是用户需要删除的索引名称,参数table_name指定数据表名称,下面应用示例向读者展示如何删除数据表中已经存在的索引。打开MySQL后,应用SHOW CREATE TABLE语句查看数据表的索引,
在用户顺利删除索引后,为确定该索引是否已被删除,用户可以再次应用SHOW CREATE TABLE语句来查看数据表结构。
  本实例将使用DROP语句从数据表中删除不再需要的索引。
​ 使用DROP语句删除workinfo表的唯一性索引index_id,具体代码如下。

1
DROP INDEX index_id ON workinfo;

4.小结

​ 本章对MySQL数据库的索引的基础知识、创建索引、删除索引进行了详细讲解,创建索引的内容是本章的重点。读者应该重点掌握创建索引的3种方法,分别为创建表的时候创建索引、使用CREATE INDEX语句来创建索引和使用ALTER TABLE语句来创建索引。

huang2024-4-8-2024-4-14周报

本周学习大纲

1.mysql学习

2.整理Java笔记

3.日周笔记

本周学习日历

日期 学习内容 其他
星期一 索引概述 \
星期二 创建索引 \
星期三 java笔记整理 \
星期四 删除索引 \
星期五 \ 日周笔记
星期六 \ \
星期日 java笔记整理 \

本周学习内容及收获

1.MySQL笔记

https://snail0220.github.io/2024/04/14/MySQL%E7%B4%A2%E5%BC%95/

2.Java整理成果

https://snail0220.github.io/2024/04/08/java/

3.日周笔记

image-20240414155445149

总结

本周的学习进度正常,但是由于本周在准备大创及互联网+项目的内容准备,导致周六没有学习相关内容和日周笔记的质量下降,希望在下周可以补回。

下周学习

1.MySQL继续学习

2.Java整理

3.日周笔记

4.题目

Java语言的基础

image-20240408213857363

第1章 Java语言基础

1.1 Java主类结构

Java语言是面向对象的程序设计语言,Java程序的基本组成单元是类,类体中又包括属性和方法两部分。每一个应用程序都必须包含一个main()方法,含有main()方法的类称为主类。下面通过程序来介绍Java主类结构。

【例1.1】创建主类并调动其主方法,实现在控制台上输出“你好Java”

1
2
3
4
5
6
7
8
9
package Number;
public class Frist{
static String s1 = "你好"
public static void main(String[] args){
String s2 = "Java";
System.out.println(s1);
System.out.println(s2);
}
}

注意

代码中的所有标点符号都是英文字符。不要在中文输入法状态下输入标点符号,如双引号和分号,否则会导致编译错误。

文件名必须和类名Frist相同,即Frist.java。还要区分大小写,Java是区分大小写的。

1.包声明

一个Java应用程序是由若干个类组成的。在例1.1中就是一个类名为Frist的类,语句package Number为声明该类所在的包,package为包的关键字。

2.声明成员变量和局部变量

通常将类的属性称为类的全局变量(成员变量),将方法中的属性称为局部变量。全局变量声明在类体中,局部变量声明在方法体中,全局变量和局部变量都有各自的应用范围。在例1.1中,s1是成员变量,s2是局部变量。

3.编写主方法

main()方法是类体中的主方法。该方法从“{”开始,至”}”结束。public、static和void分别是main()方法的权限修饰符、静态修饰符和返回值修饰符,Java程序中的main()方法必须声明为public static void。String[] args是一个字符串类型的数组,它是main()方法的参数。main()方法是程序开始执行的位置。

4.导入API类库

在Java语言中可以通过import关键字导入相关的类。在JDK的API中(应用程序接口)提供了130多个包,如java.awt、java.io等。可以通过JDK的API文档来查看这些包中的类,把握类的继承结构、类的应用、成员变量表、构造方法表等,并对每个变量的使用目的进行了解,API文档是程序开发人员不可或缺的工具。

误区警示

Java语言是严格区分大小写的。例如,不能将关键字class等同于Class.

1.2 基本数据类型

在Java中有8种基本数据类型来存储数值、字符和布尔值,如图所示。

image-20240409220719993

1.2.1 整数类型

整数类型简称整型,用来存储整数数值,即没有小数部分的数值。可以是正数,也可以是负数。整型数据根据它所占内存大小的不同,可分为byte、short、int和long 4种类型。它们具有不同的取值范围。

数据类型 内存空间(8位等于1字节) 取值范围
byte 8位 -128~127
short 16位 -32768~32767
int 32位 -2147483648~2147483647
long 64位 -9223372036854775808~9223372036854775807

下面分别对这4种整型数据类型进行介绍。

1.int型

1
2
3
4
int x;                        //定义int型变量x
int x,y; //同时定义int型变量x,y
int x = 10,y = -5; //同时定义int型变量x,y并赋予初值
int x = 5+23; //定义int型变量x,并赋予公式(5+23)计算结果的初值

int变量在内存中占4字节,也就是32位bit,在计算机中bit是由0和1来表示的,所以int型值5在计算机中是这样显示的:00000000 00000000 00000000 00000101

int型是Java整数值的默认数据类型。当对多个尚未定义数据类型的整数做运算时,运算的结果将默认为int类型。例如,下面这行代码:

​ System.out.println(15+20); // 输出35

等同于如下代码:

1
2
3
4
int a = 15;
int b = 20;
int c = a+b;
System.out.println(c); //输出35

2.byte型

byte型的定义方式与int相同。定义byte类型变量,代码如下:

1
2
3
byte a;
byte a,b,c;
byte a = 19,b = -45;

3.short型

short型的定义方式与int相同。定义short类型变量,代码如下:

1
2
3
4
short s;
short s,t,r;
short s = 1000,t = -19;
short s = 20000/10;

4.long型

由于long型的取值范围比int型大,且属于高精度数据类型,所以在赋值时要和int型作出区分,需要在整数后加L和l。定义long类型变量,代码如下:

1
2
3
4
long number;
long number,rum;
long number = 12345678l,rum = -987654321L;
long number = 123456789L*987654321L;

注意

整数在Java程序中有3种表示形式,分别为十进制、八进制和十六进制:

(1)十进制:十进制如120、0、-127

(2)八进制:0123(转化为十进制为83),八进制必须为0开头

(3)十六进制:0x23(转化为十进制为37)、0Xb01e(转化为十进制为45086),十六进制必须为0X或0x开头。

1.2.2 浮点类型

浮点类型简称浮点型,用来存储含有小数部分的数值。Java语言中浮点类型分为单精度浮点类型(float)和双精度浮点类型(double),它们具有不同的取值范围,如表所示。

数据类型 内存空间(8位等于1字节) 取值范围
float 32位 1.4E-45~3.4028235E38
double 64位 4.9E-324~1.7976931348623157E308

在默认情况下小数都被看做double型,若想使用float型小数,则需要在小数后面添加F或f。另外,可以使用后缀d或D来明确表明这是一个double类型数据,但加不加d或D并没有硬性规定,系统会认为是double类型数据,进而出错。定义浮点类型变量,代码如下:

1
2
3
float f1 = 13.23f;
double d1 = 4562.12d;
double d2 = 45678.1564;

误区警示

浮点值属于近似值,在系统中运算后的结果可能与实际有偏差。

【例1.2】根据身高体重计算BMI指数

创建BMLexponent类,声明double型变量height来记录身高,单位为米;声明int型变量weight记录体重,单位为千克;根据BMI = 体重/(身高*身高)计算BMI指数。实例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class BMIexponent{
public static void main(String[] args){
double height = 1.72; //身高变量,单位:米
int weight = 70; //体重变量,单位:千克
double exponent = weight/(height*height); //BMI计算公式
System.out.println("您的身高为:"+height);
System.out.println("您的体重为:"+weight);
System.out.println("您的BMI指数为:"+exponent);
System.out.println("您的体重属于:");
if(exponent<18.5){ //判断BMI指数是否小于18.5
System.out.println("体重过轻");
}
if(exponent>=18.5 && exponent<24.9){ //判断BMI指数是否在18.5到24.9之间
System.out.println("正常范围");
}
if(exponent>=24.9 && exponent<29.9){ //判断BMI指数是否在24.9到29.9之间
System.out.println("体重过重")
}
if(exponent>=29.9){ //判断BMI指数是否大于29.9
System.out.println("肥胖")
}
}
}

运行结果如下

1
2
3
4
您的体重为:1.72
您的体重为:70
您的BMI指数为:23.661438615467823
您的体重属于:正常范围

1.2.3 字符类型

1.char型

字符类型(char)用于存储单个字符,占用16位(两个字节)的内存空间。在定义字符型变量时,要以单引号表示,如’s’表示一个字符。但是”s”则表示一个字符串,虽然只有一个字符,但由于使用双引号,它仍然表示字符串,而不是字符。

使用char关键字可定义字符变量,其语法如下:

1
char x = 'a';

由于字符a在Unicode表中的排序位置是97,因此允许将上面的语句写成:

1
char x = 97;

同C和C++语言一样,Java语言也可以把字符作为整数对待。由于Unicode编码采用无符号编码,可以存储65536个字符(0x0000~0xffff),所以Java中的字符几乎可以处理所有国家的语言文字。若想得到一个0~65536的数所代表的Unicode表中相应位置上的字符,也必须使用char型显式转换。

【例1.3】查看字符与Unicode码互转的结果

在项目中创建类Gess,编写如下代码,将Unicode表中某些位置上的字符以及一些字符在Unicode表中的位置在控制台上输出。

1
2
3
4
5
6
7
8
9
10
public class Gess{
public static void main(String[] args){
char word = 'd',word2 = '@';
int p = 23045,p2 = 45213;
System.out.println("d在Unicode表中的顺序位置是:"+(int)word);
System.out.println("@在Unicode表中的顺序位置是:"+(int)word2);
System.out.println("Unicode表中的第23045位是:"+(char)p);
System.out.println("Unicode表中的第45213位是:"+(char)p2);
}
}

运行结果如下:

1
2
3
4
d在Unicode表中的顺序位置是:100
@在Unicode表中的顺序位置是:64
Unicode表中的第23045位是:娅
Unicode表中的第45213位是:?

String类型为字符串类型,可以用来保存由多个字符组成的文本内容,其用法与字符类型相似,但文本内容需要用双引号标注。

2.转义字符

转义字符是一种特殊的字符变量,它以反斜杠”\“开头,后跟一个或多个字符。转义字符具有特定的含义,不同于字符原有的意义,故称”转义“。例如,printf函数的格式串中用到的”\n“就是一个转义字符,意思是”回车换行“。Java中的转义字符如图所示。

转义字符 含义 转义字符 含义
\ddd 1~3位八进制数据所表示的字符,如\123 \r 回车
\uxxxx 4位十六进制数据所表示的字符,如\u0052 \n 换行
\‘ 单引号字符 \b 退格
\\ 反斜杠字符 \f 换页
\t 垂直制表符,将光标已到下一个制表符的位置

将转义字符赋值给字符变量时,与字符常量值一样需要使用单引号。

【例1.4】输出‘\’字符和‘★’字符。

‘\’字符的转义字符为‘\\’,‘★’字符的Unicode码为2605,实例代码如下:

1
2
3
4
5
6
7
8
public class Demo{
public static void main(String[] args){
char c1 = '\\'; //
char char1 = '\u2605';
System.out.println(c1);
System.out.println(char1);
}
}

运行结果如下:

1
2
\

1.2.4 布尔类型

布尔类型又称逻辑类型,简称布尔型,通过关键字boolean来定义布尔类型变量。布尔类型只有true和false两个值,分别代表布尔逻辑中的“真”和“假”。布尔值不能与整数类型进行转换。布尔类型通常被用在流程控制中,作为判断条件。定义布尔类型变量,代码如下:

1
2
3
boolean b;                       //定义布尔型变量b
boolean b1,b2; //定义布尔值变量b1,b2
boolean b = true; //定义布尔值变量b,并赋给初值true

1.3 变量与常量

在程序执行过程中,其值不能被改变的量称为常量,其值能被改变的量称为变量。变量与常量的命名都必须使用合法的标识符。

1.3.1 标识符和关键字

1.标识符

标识符可以简单的理解为一个名字,是用来标识类名、变量名、方法名、数组名、文件名 的有效字符序列。

Java语言规定标识符由任意顺序的字母、下划线(_)、美元符号($)和数字组成,并且第一个字符不能是数字。标识符不能是Java中的关键字(保留字)。

在Java语言中,标识符中的字母是严格区分大小写的。Java语言使用Unicode标准字符集,最多可以标识65535个字符。

2.关键字

关键字又称保留字,是Java语言中已经被赋予特定意义的一些单词,不可以把这些单词作为标识符来使用。如图所示。

image-20240411222025653

1.3.2 声明变量

变量的使用是程序设计中一个十分重要的环节。声明变量就是要告诉编译器(compiler)这个变量的数据类型,这样编译器才知道需要配置多少空间给它,以及它能存放什么样的数据。在程序运行过程中,空间内的值是变化的,这个内存空间就称为变量。为了便于操作,给这个内存空间取个名字,称为变量名。变量的命名必须是合法的标识符。内存空间内的值就是变量值。在声明变量时可以是没有赋值,也可以是直接赋给初值。

例如,声明一个整数类型变量和声明一个字符类型变量,代码如下:

1
2
int age;                         //声明int型变量
char char1 = 'r'//声明char型变量并赋值

变量占用的内存空间:

image-20240411223445097

如图所知,由图3.2可知,系统的内存可大略分为3个区域,即系统(OS)区、程序(Program)区和数据(Data)区。当程序执行时,程序代码会加载到内存中的程序区,数据暂时存储在数据区中。假设上述两个变量定义在方法体中,则程序加载到程序区中。当执行此行程序代码时,会在数据区配置空间给出这两个变量。
对于变量的命名并不是随意的,应遵循以下几条规则:
 变量名必须是一个有效的标识符。
 变量名不可以使用Java中的关键字。
 变量名不能重复。
 应选择有意义的单词作为变量名。
说明
在Java语言中允许使用汉字或其他语言文字作为变量名,如“int年龄= 21”,在程序运行时不会出现错误,但建议读者尽量不要使用这些语言文字作为变量名。

1.3.3 声明常量

在程序运行过程中一直不会改变的量称为常量(constant),通常也被称为“final变量“。常量在整个程序中只能被赋值一次。在为所有的对象共享值时,常量是非常有用的。

在Java语言中声明一个常量,除了要指定数据类型,还需要通过final关键字进行限定。声明常量的标准语法如下:

1
final 数据类型 常量名称 [= 值]

当变量被final关键字修饰时,该变量就变成了常量,必须在定义时就设定它的初值,否则将会产生编译错误。

【例1.5】尝试给常量赋值,观察是否会发生错误。

​ 在项目中创建Part,在类体中创建变量age与变量PI。在主方法中分别将变量与常量赋值,通过输出信息可测试变量与常量的有效范围。

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Part{
static fianl double PI=3.14;
static int age=23;
public static void main(String[] ages){
final int number;
number = 1235;
age = 22;
number = 1236;
System.out.println("常量PI的值;"+PI);
System.out.println("赋值后number的值为:"+number);
System.out.println("int型变量age的值为:"+age);
}
}

运行结果如下:

1
2
3
Exception in thread"main"java.lang.Error:无法解析的编译问题:
final 局部变量 number 可能已经被赋过值
at Partmain(Part.java:10)

从这个结果可以看到,Part类运行后发生了错误,异常日志中记载Part类出现编译问题,此编译问题正是常量number被第二次赋值。

1.3.4 变量的有效范围

由于变量被定义出来后只是暂存在内存中,等到程序执行到某一个点,该变量会被释放掉,也就是说变量有它的生命周期。因此,变量的有效范围是指程序代码能够访问该变量的区域,若超出该区域,则在编译时会出现错误。在程序中,一般会根据变量的“有效范围”将变量分为“成员变量”和“局部变量”。

1.成员变量

在类体中所声明的变量被称为成员变量,成员变量在整个类中都有效。类的成员变量又可分为两种,即静态变量和实例变量。例如下面这段代码:

1
2
3
4
class Demo{
int x=45;
static int y=90;
}

其中,x为实例变量,y为静态变量(也称类变量)。如果在成员变量的类型称为静态变量。静态变量的有效范围可以跨类,甚至可达到整个应用程序之内。对于静态变量,除了能在声明它的类内存区,还能直接以“类名.静态变量”的方式在其他类内使用。

2.局部变量

在类的方法体中声明的变量(方法内部定义,“{”与“}”之间的代码中声明的变量)称为局部变量。局部变量只在当前代码块中有效,也就是只能在“{”与“}”之内使用。

在类的方法中声明的变量,包括方法的参数,都属于局部变量。局部变量只在当前定义的方法内有效,不能用于类的其他方法中。局部变量的生命周期取决于方法,当方法被调用时,Java虚拟机会为方法中的局部变量分配内存空间,当该方法的调用结束后,则会释放方法中的局部变量占用的内存空间,局部变量也将被销毁。

局部变量可与成员变量的名字相同,此时成员变量将被隐藏,即这个成员变量在此方法中暂时失效。

变量的有效范围如图所示

image-20240416212333425

【例1.6】把成员变量“排挤掉”的局部变量

在项目中创建类Vel分别定义名称相同的局部变量与成员变量,当名称相同时成员变量将被隐藏。

1
2
3
4
5
6
7
public class Val{
static int times = 3;
public static void main(String[] args){
int times = 4;
System.out.println("times的值为:"+times);
}
}

运行结果如下

1
times的值为:4

1.4 运算符

运算符是一些特殊的符号,主要用于数学函数、一些类型的赋值语句和逻辑比较方面。Java中提供了丰富的运算符,如赋值运算符、算数运算符、比较运算符等。

1.4.1 赋值运算符

赋值运算符以符号“=”表示,它是一个二元运算符(对两个操作数作处理),其功能是将右方操作数所含的值赋给左方的操作数。例如

1
int a = 100

该表达式是将100赋值给变量a。作坊的操作数必须是一个变量,而右边的操作数则可以是任何表达式,包括变量(如a、number)、常量(如123、‘book’)、有效的表达式(如45*12)。

由于赋值运算符”=”处理时会先取得右方表达式处理后的结果,因此一个表达式中若含有两个以上的”=”运算符,会从最右方的”=”开始处理。

【例1.7】使用赋值运算符同时为两个变量赋值

在项目中创建类Eval,在主方法中定义变量,使用赋值运算符为变量赋值。

1
2
3
4
5
6
7
8
9
public class Eval{
public static void main(String[] args){
int a,b,c;
a = 15;
c=b=a+4;
System.out.println("c的值为:"+c);
System.out.println("b的值为:"+b);
}
}

输入结果为:

1
2
c的值为:19
b的值为:19

说明

在Java中可以把赋值运算符连在一起使用。如:

x=y=z=5;

在这个语句中,变量x、y、z都得到同样的值5。但在实际开发中建议开发者分开赋值,这样可以让代码的层次更清晰。

1.4.2 算术运算符

Java中的算术运算符主要有+(加)、-(减)、*(乘)、/(除)、%(求余),它们都是二元运算符。Java中算术运算符的功能及使用方式,如图示。

image-20240416221427183

其中,”+”和”-“运算符还可以作为数值的正负符号,如+5、-7。

注意

在进行除法运算时,0不能做除数。例如,对于语句”int a = 5/0;”,系统会抛出ArithmeticException异常。

【例1.8】使用算术运算符模拟计算器

创建ArithmeticOperator类,让用户输入两个数字,分别用5种运算符对两个数字进行计算。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import java.util.Scanner;
public class ArithmeticOperator{
public static void main(String[] args){
Scanner sc = new Scanner(Systen.in);
System.out.println("请输入两个数字,用空格隔开(num1 num2):");
double num1 = sc.nextDouble();
double num2 = sc.nextDouble();
System.out.println("num1+num2的和为:"+(num1+num2));
System.out.println("num1-num2的差为:"+(num1-num2));
System.out.println("num1*num2的积为:"+(num1*num2));
System.out.println("num1/num2的商为:"+(num1/num2));
System.out.println("num1%num2的余数为:"+(num1%num2));
sc.close();
}
}

运行结果如下:

1
2
3
4
5
6
7
请输入两个数字:,用空格隔开(num1 num2):
23 15
num1+num2的和为:38.0
num1-num2的差为:8.0
num1*num2的积为:345.0
num1/num2的商为:1.533333333333333334
num1%num2的余数为:8.0

1.4.3 自增和自减运算符

自增、自减运算符是单目运算符,可以放在操作元之前,也可以放在操作元之后。操作元必须是一个整型或浮点型变量。自增、自减运算符的作用是使变量的值增1或减1。放在操作元前面的自增、自减运算符,会先将变量的值加1(减1),然后再使该变量参与表达式的运算。放在操作元后面的自增、自减运算符,会先使变量参与表达式的运算,然后再将该变量加1(减1)。例如:

1
2
++a(--a)       //表示在使用变量a之前,先使a的值加(减)1
a++(a--) //表示在使用变量a之后,使a的值加(减)1

粗略的分析,“++a”与“a++”的作用都相当于a=a+1。假设a=4,则:

1
b = ++a;             //先将a的值加1,然后赋值给b,此时a的值为5,b的值为5

再看另一个语法,同样假设a=4,则:

1
b = a++;             //先将a的值赋值给b,再将a的值变为5,此时a的值为5,b的值为4

1.4.4 比较运算符

比较运算符属于二次运算符,用于程序中的变量之间、变量和自变量之间以及其他类型的信息之间的比较。比较运算符的运算结果是boolean型。当运算符对应的关系成立时,运算结果为true,否则为false。所有比较运算符通常作为判断的依据用在条件语句中。比较运算符共有6个,如图所示:

image-20240417223404273

【1.9】使用不同的比较运算符判断两个整数的关系

在项目中创建类Compare,在主方法中创建整型变量,使用比较运算符对变量进行比较运算,并将运算后的结果输出。

1
2
3
4
5
6
7
8
9
10
11
12
public class Compare{
public static void main(String[] args){
int number1=4;
int number2=5;
System.out.println("number1>number2的返回值为:"+(number1>number2));
System.out.println("number1<number2的返回值为:"+(number1<number2));
System.out.println("number1==number2的返回值为:"+(number1==number2));
System.out.println("number1=number2的返回值为:"+(number1!=number2));
System.out.println("number1>=number2的返回值为:"+(number1>=number2));
System.out.println("number1<=number2的返回值为:"+(number1<=number2));
}
}

运行结果如下:

1
2
3
4
5
6
number1>number2的返回值为:false
number1<number2的返回值为:true
number1==number2的返回值为:false
number1!=number2的返回值为:true
number1>=number2的返回值为:false
number1<=number2的返回值为:true

1.4.5 逻辑运算符
返回类型为布尔型的表达式,如比较运算符,可以被组合在一起构成一个更复杂的表达式。这是通过逻辑运算符来实现的。逻辑运算符包括&(&&)(逻辑与)、||(逻辑或)、!(逻辑非)。逻辑运算符的操作元必须是boolean型数据。在逻辑运算符中,除了“!”是一次运算符,其他都是二次运算符。

运算符 含义 用法 结合方向
&&、& 逻辑与 op1&&op2 从左到右
|| 逻辑或 op1||op2 从左到右
! 逻辑非 !op 从右到左

结果为boolean型的变量或表达式可以通过逻辑运算符组合为逻辑表达式。

用逻辑运算符进行逻辑运算时,结果如下:

表达式1 表达式2 表达式1&&表达式2 表达式 1||表达式2 !表达式1
true true true true false
true false false true false
false false false false true
false true false true true

逻辑运算符”&&”与”&”都表示”逻辑与”,那么它们之间的区别在哪?从上表中可见,当两个表达式都为true时,”逻辑与”的结果才会是true。使用逻辑运算符”&”会判断两个表达式;而逻辑运算符”&&”则是针对boolean类型的类进行判断,当第一个表达式为false时则不去判断第二个表达式,直接输出结果,从而节省计算机判断的次数。通常将这种在逻辑表达式中从左端的表达式可推断出整个表达式的值的情况称为”短路”,而那些始终需要执行逻辑运算符两边的表达式才能推断出整个表达式的值的情况称为”非短路”。”&&”属于”短路”运算符,而”&”属于”非短路”运算符。

【例1.10】使用不同的比较运算符判断两个整数的关系。

在项目中创建类Cal,在主方法中创建3个整数,分别记录男生人数、女生人数和总人数,使用逻辑运算符来判断”男生人数大于女生人数并且总人数大于30人”和”男生人数大于女生人数或者总人数大于30人”这两种情况是否存在。

1
2
3
4
5
6
7
8
9
10
11
public class Cal{
public static void main(String[] args){
int boys = 15;
int girls = 17;
int total = boys+girls;
boolean result1 = ((boys>girls)&&(total>30));
boolean result2 = ((boys>girls)||(total>30));
System.out.println("男生人数大于女生人数并且总人数大于30人:"+result1);
System.out.println("男生人数大于女生人数或者总人数大于30人:"+result2);
}
}

运行结果如下:

1
2
男生人数大于女生人数并且总人数大于30人:false
男生人数大于女生人数或者总人数大于30人:true

1.4.6 位运算符

位运算符除”按位与”或”按位或”运算符外,其他只能用于处理整数的操作数,包括byte、short、char、int和long等数据类型。位运算是完全针对位方面的操作。整型数据在内存中以二进制的形式表示,如int型变量7的二进制表示00000000 00000000 00000000 00000111。

左边最高位是符号位,最高位是0表示正数,若为1则表示负数。负数采用补码表示,如-8的二进制表示为11111111 11111111 11111111 11111000。这样就可以对整型数据进行按位计算。

1.”按位与”运算

“按位与”运算的运算符为”&”,为双目运算符。”按位与”运算的运算法则是:如果两个整型数据a、b对应为都是1,则结果位才是1,否则为0。如果两个操作数的精度不同,则结果的精度与精度高的操作数相同,如图所示。

image-20240421220509545

2.”按位或”运算

“按位或”运算的运算符为”|”,为双目运算符。”按位或”运算的运算法则是:如果两个操作数对应位都是0,则结果位才是0,否则为1。如果两个操作数的精度不同,则结果的精度与精度高的操作数相同,如图所示:

image-20240421220948162

3.”按位取反”运算

“按位取反”运算也称”按位非”运算,运算符”~”,为单目运算符。”按位取反”就是将操作数二进制中的1修改为0,0修改为1,如图所示:

image-20240421221418802

4.”按位异或”运算

“按位异或”运算的运算符是”^”,为双目运算符。”按位异或”运算的运算法则是:当两个操作数的二进制表示相同(同时为0或同时为1)时,结果为0,否则为1。若两个操作数的精度不同,则结果的精度与精度高的操作数相同,如图所示:

image-20240421222139538

5.移位操作

除了上述运算符,还可以对数据按二进制位进行移位操作。Java中的移位运算符有以下3种:

1
2
3
<<:左移
>>:右移
>>>:无符号右移

左移就是将运算符左边的操作数的二进制数据,按照运算符右边操作数指定的位数向左移动,右边移空的部分补0。右移则复杂一些。当使用”>>”符号时,如果最高位是0,右移空的位就填入0;如果最高位是1,右移空的位就填入1,如图所示:

image-20240421223021025

Java还提供了无符号右移”>>>”,无论最高位是0还是1,左移被移空的高位都填入0。

技巧

移位可以实现整数除以或乘以2ⁿ的效果。例如,y<<2与y*4的结果相同;y>>1的结果与y/2的结果相同。总之,一个数左移n位,就是将这个数乘以2ⁿ;一个数右移n位,就是将这个数除以2ⁿ。

1.4.7 三元运算符

三元运算符的使用格式为

1
条件式 ? 值1 :值2

三元运算符的运算规则为:若条件式的值为true,则整个表达式取值1,否则取值2。例如:

1
boolean b = 20 < 45 ? true : false; 

上述程序表达式”20<45”的运算结果返回为真,那么boolean型变量b取值为true。相反,如果表达式的运算结果返回为假,则boolean型变量b取值为false。

三元运算符等价于if…else语句,例如上述代码等价于:

1
2
3
4
5
boolean a;
if(20<45)
a = true;
else
a = false;

1.4.8 运算符优先级

Java中的表达式就是使用运算符连接起来的符合Java规则的式子。运算符的优先级决定了表达式中运算执行的先后顺序。通常,优先级由高到低的顺序依次是:

  • 增量和减量运算

  • 算数运算

  • 比较运算

  • 逻辑运算

  • 赋值运算

    如果两个运算有相同的优先级,那么左边的表达式要比右边的表达式先被处理。表中显示了在Java中众多运算符特定的优先级。

image-20240422232038407

技巧:

在编写程序时尽量使用圆括号来指定运算次序,以免产生错误的运算顺序。

1.5 数据类型转换

类型转换是将一个值从一种类型更改为另一种类型的过程。例如,可以将String类型的数据”457”转换为数值型,也可以将任意类型的数据转换为String类型。

如果从低精度数据类型向高精度数据类型转换,则永远不会溢出,并且总是成功的;而把高精度数据类型向低精度数据类型转换时,则会有信息丢失,有可能失败。

数据类型转换有两种方式,即隐式转换与显示转换。

1.5.1 隐式类型转换

从低级类型向高级类型的转换,系统将自动执行,程序员无须进行任何操作。这种类型的转换称为隐式转换。下列基本数据类型会涉及数据转换,不包括逻辑类型和字符类型。这些类型按精度从低到高排列的顺序为:byte<short<int<long<float<double。

例如,可以将int型变量直接赋值给float型变量,此时int型变量将隐式转换成float型变量。代码如下:

1
2
int x = 50;
float y = x;

隐式转换也要遵循一定的规则,来解决在什么情况下将哪种类型的数据转换成另一种类型的数据。下列规则:

操作数1的数据类型 操作数2的数据类型 转换后的数据类型
byte、short、char int int
byte、short、char、int long long
byte、short、char、int、long float float
byte、short、char、int、long、float double double

【例1.11】使用隐式转换提升数值的精度

在项目中创建类Conver,在主方法中创建不同数值型的变量,实现将各项变量隐式转换。

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Conver{
public static void main(String[] args){
byte mybyte = 127;
int myint = 150;
float myfloat = 452.12f;
char mychar = 10;
double mydouble = 45.46546
System.out.println("byte型与float型数据进行运算结果为:"+(mybyte+myfloat));
System.out.println("byte型与int型数据进行运算结果为:"+(mybyte+myint));
System.out.println("byte型与char型数据进行运算结果为:"+(mybyte+mychar));
System.out.prontln("double型与char型数据进行运算结果为:"+(mydouble+mychar));
}
}

运行结果如下:

1
2
3
4
byte型与float型数据进行运算结果为:579.12
byte型与int型数据进行运算结果为:19050
byte型与char型数据进行运算结果为:12
double型与char型数据进行运算结果为:55.46546

1.5.2 显示类型转换

当把高精度的变量的赋值给低精度的变量时,必须使用显示类型转换运算(又称强制类型转换)。语法如下:

1
(类型名)要转换的值

例如,将高精度数字转换为低精度数字。代码如下:

1
2
3
int a = (int)45.23;
long y =(long)456.6F;
int b = (int)'d';

执行显示类型转换时,可能会导致精度损失。除boolean类型外,其他基本类型都能以显示类型转换的方法实现转换。

误区警示

当把整数赋值给byte、short、int、long型变量时,不可以超出这些变量的取值范围,否则必须进行强制类型转换。例如:

1
byte b = (byte)129;

1.6 代码注释与编码规范

在程序代码中适当地添加注释,可以提高程序的可读性和可维护性。

1.6.1 代码注释

通过在程序代码中添加注释提高程序的可读性。注释中包含了程序的信息,可以帮助程序员更好地阅读和理解程序。在Java源程序文件的任意位置都可以添加注释语句。注释的文字Java编译器不进行编译,所有代码中的注释文字对程序不产生任何影响。Java语言提供三种添加注释的方法,分别为单行注释、多行注释和文档注释。

1.单行注释

“//“为单行注释标记,从符号”//“开始直到换行为止的所有内容均作为注释而被编译器忽略。语法如下:

1
//注释内容

例如,以下代码为声明的int型变量添加注释:

1
int age;               //定义int型变量,用于保存年龄信息

2.多行注释

注释的内容可以换行,代码如下

1
2
3
4
5
/*
注释内容1
注释内容2
...
*/

注意

(1)在多行注释中可嵌套单行注释。例如:

1
2
3
/*
程序名称:Hello world //开发时间:2024-4-25
*/

(2)多行注释中不可以嵌套多行注释,以下代码是错误的:

1
2
3
4
/*
程序名称:Hello world
/*开发时间:2024-4-25;*/
*/

3.文档注释

“/** /“为文档注释标记。符号”/**”与”/“之间的内容均为文档注释内容。当文档注释出现在声明(如类的声明、类的成员变量的声明、类的成员方法的声明等)之前时,会被javadoc文档工具读取作为javadoc文档内容。除注释标记不同外,文档注释的格式与多行注释的格式相同。

说明

程序中,注释要占程序代码总量的20%~50%。

第2章 流程控制

image-20240425223329771

2.1 复合语句

Java语言的复合语句是以整个块区为单位的语句,所以又称块语句。复合语句有开括号”{“开始,闭括号”}”结束。

2.2 条件语句

条件语句可根据不同的条件执行不同的语句。条件语句包括if条件语句与Switch多分支语句。

mysql多表查询

MySQL的多表查询是一种强大的功能,它允许我们同时从多个表中获取数据。以下是一些关于如何进行多表查询的详细说明:

基本概念

在MySQL中,多表查询通常通过JOIN操作符来实现。JOIN操作符可以连接两个或更多的表,并选择出满足特定条件的记录。

JOIN操作符

JOIN操作符有多种类型,包括INNER JOIN, LEFT JOIN, RIGHT JOIN和FULL JOIN。每种JOIN类型都有其特定的用途:

  1. INNER JOIN: 返回两个表中匹配的记录。如果任一表中没有匹配的记录,则不会出现在结果集中。

  2. LEFT JOIN: 返回左边表的所有记录,以及右边表中匹配的记录。如果右边表中没有匹配的记录,则结果集中的相应字段将被设置为NULL。

  3. RIGHT JOIN: 与LEFT JOIN相反,它返回右边表的所有记录,以及左边表中匹配的记录。

  4. FULL JOIN: 返回左边表和右边表中的所有记录,但是当两边表都没有匹配的记录时,会抛出一个错误。

示例

假设我们有三个表:students, courses和grades。我们需要找出所有选修了课程的学生。我们可以使用INNER JOIN来实现这个目标:

1
2
SELECT students.name, 
courses.course_name FROM students INNER JOIN courses ON students.student_id = courses.student_id;

在这个例子中,students表和courses表通过student_id字段进行了关联。我们选择了students表中的name字段和courses表中的course_name字段。

注意事项

在进行多表查询时,需要注意以下几点:

确保要连接的表之间存在关联关系。如果没有这样的关系,那么JOIN操作可能会导致错误的结果或者根本无法执行。

注意JOIN操作对性能的影响。如果处理的表非常大,那么JOIN操作可能会非常慢。在这种情况下,可能需要考虑优化查询或者数据库设计。

在某些情况下,可以使用子查询代替JOIN操作。子查询可以在一个查询内部执行另一个查询,并且可以处理更复杂的逻辑。

MySQL事务

MySQL事务是一种用于维护数据库完整性的机制,它保证了数据库操作的原子性、一致性、隔离性和持久性(ACID属性)。在MySQL中,只有使用了InnoDB存储引擎的数据库或表才支持事务。以下是关于MySQL事务的详细笔记:

ACID属性

1.原子性(Atomicity):事务中的所有操作要么全部执行成功,要么全部失败回滚,不会只执行其中的一部分操作。

2.一致性(Consistency):事务执行前后,数据库的状态必须保持一致。

3.隔离性(Isolation):并发执行的多个事务之间互不干扰,一个事务的中间状态对其他事务是不可见的。

4.持久性(Durability):一旦事务提交,其对数据库的修改就是永久性的。

事务控制语句

MySQL提供了以下四个事务控制语句:

  1. BEGIN:表示一个事务的开始。

  2. COMMIT:表示一个事务的提交,将修改保存到数据库中。

  3. ROLLBACK:表示一个事务的回滚,撤销对数据库的修改。

  4. SAVEPOINT:表示设置一个保存点,可以在后续的操作中使用ROLLBACK TO语句来回滚到指定的保存点。

事务的使用示例

以下是一个使用事务的示例代码:

1
2
START TRANSACTION; 
-- 执行多条SQL语句 COMMIT; # 如果需要回滚,可以使用ROLLBACK;

在实际应用中,事务可以用于保证一系列数据库操作的完整性和一致性。例如,在一个转账的场景中,事务可以保证从一个账户扣款和向另一个账户存款这两个操作要么都成功,要么都不做,从而避免了只做了其中一部分操作导致的错误。

需要注意的是,虽然事务可以提高数据库操作的可靠性,但同时也可能影响数据库的性能。因此,在实际使用中需要权衡事务带来的好处和可能的性能开销。

huang2024-4-1-2024-4-7周报

本周学习大纲

1.MySQL

2.笔记

3.题目

本周学习日历

日历 学习内容 其他
星期一 多表统计1 \
星期二 多表统计2 \
星期三 函数 \
星期四 \ \
星期五 事务1 日周笔记
星期六 事务2 \
星期天 \ \

本周学习内容及收获

1.MySQL

多表查询

https://snail0220.github.io/2024/04/07/%E5%A4%9A%E8%A1%A8%E6%9F%A5%E8%AF%A22/

事务

https://snail0220.github.io/2024/04/07/%E4%BA%8B%E5%8A%A1/

函数

https://snail0220.github.io/2024/03/24/MySQL--%E5%87%BD%E6%95%B0/

2.日周笔记

image-20240407204756701

总结

本周的学习把之前的多表查询详细学了下,题目方面没有做到。本周的学习有点草率,没有认真学习的,希望下周可以投入学习中。

下周学习

1.MySQL

2.题目

3.日周笔记

多表查询

1.基础

在MySQL中,多表查询是一种强大的功能,它允许你在一次查询中联合多个表,并从中获取所需的数据。以下是一些关于MySQL多表查询的基础知识:

(1) 多表查询的基本语法

多表查询的基本语法是SELECT * FROM 表1, 表2。这里的*代表选择所有的列,可以根据需要替换成具体的列名。表1和表2是想要联接的表名。例如,如果想同时从students表和classes表中查询数据,可以这样写:

1
SELECT * FROM students, classes; 

这个查询会返回students表和classes表的“乘积”,也就是说,students表的每一行都会与classes表的每一行进行配对,形成一个二维表 。

(2) 多表查询的注意事项

在使用多表查询时,你需要特别注意的一点是,由于结果是两个表的行数乘积,因此可能会得到大量的数据。比如,如果你的两个表各有100行记录,那么进行笛卡尔查询将会返回10000条记录。因此,在进行多表查询时,你应该尽可能地使用WHERE条件来限制查询的范围 。

(3)多表查询的高级用法

除了基本的笛卡尔查询,MySQL还提供了其他几种高级的多表查询方法,如INNER JOIN、LEFT JOIN、RIGHT JOIN和FULL JOIN。这些方法可以帮助你更有效地从多个表中获取数据。例如,如果你想查询students表中所有学生的名字和他们的班级,你可以使用INNER JOIN:

1
SELECT students.name,classes.classroom FROM students INNER JOIN classes ON students.class_id = classes.class_id; 

在这个查询中,ON关键字后面的是连接条件,也就是students表中的class_id列和classes表中的class_id列相等。通过这种方式,你可以精确地从多个表中获取你想要的数据 。

约束

MySQL约束是一种强制性的规则,它用于维护数据库的完整性 。这些约束保证了数据的准确性、一致性和可靠性。常用的几种约束及其作用如下

1.主键约束(PRIMARY KEY)

主键约束用于标识表中的每一行记录。每个表都只能有一个主键,且主键的值必须是唯一的,且不能为空。当你在创建表时,你可以通过PRIMARY KEY关键字来声明一个列作为主键。

例如:

1
2
3
4
CREATA TABLE users(
id INT PRIMARY LEY,
username VARCHAR(255)
);

在这个例子中,id列被设置为PRIMARY KEY,这意味着它是主键,其值必须是唯一的,且不能为空。

2.非空主键(NOT NULL)

非空约束确保了列中的每个值都不能为空。当你在创建表时,你可以通过NOT NULL关键字来声明一个列作为非空列。

例如:

1
2
3
4
5
CREATE TABLE users(
id INT PRIMARY KEY,
username VARCHAR(255)
NOT NULL
);

在这个例子中,username列被设置为NOT NULL,这意味着它的值不能为空。

3.唯一约束(UNIQUE)

唯一约束确保了一个列或列组合中的每个值都是唯一的。这意味着在一个表中,这个列或列组合的值不能重复。当你在创建表时,你可以通过UNIQUE关键字来声明一个列或列组合作为唯一列。

例如:

1
2
3
4
5
6
CREATE TABLE users(
id INT PRIMARY KEY,
username VARCHAR(255)
UNIQUE,
email VARCHAR(255)
);

在这个例子中,username列被设置为UNIQUE,这意味着它在表中必须是唯一的。而email列没有被设置为UNIQUE,所以它的值可以在表中重复。

4.外键约束(FOREIGN KEY)

外键约束用于维持两个表之间的关联性。当你在创建表时,你可以通过FOREIGN KEY关键字来声明一个列作为外键。

例如:

1
2
3
4
CREATE TABLE orders(
order_id INT PRIMARY KEY,
product_id INT FOREIGN KEY REFERENCES products(product_id)
);

在这个例子中,product_id列被设置为FOREIGN KEY,这意味着它的值必须存在于products表的product_id列中。如果product_id列的某个值不存在于products表的product_id列中用,那么MySQL将会抛出一个错误。