1.1 数据库是干什么的?
数据库(Database)是按照数据结构来组织、存储和管理数据的仓库。
每个数据库都有一个或多个不同的 API 用于创建,访问,管理,搜索和复制所保存的数据。
我们也可以将数据存储在文件中,但是在文件中读写数据速度相对较慢。
所以,现在我们使用关系型数据库管理系统(RDBMS)来存储和管理大数据量。
所谓的关系型数据库,是建立在关系模型基础上的数据库,借助于集合代数等数学概念和方法来处理数据库中的数据。
RDBMS 即关系数据库管理系统(Relational Database Management System)的特点:
1.数据以表格的形式出现
2.每行为各种记录名称
3.每列为记录名称所对应的数据域
4.许多的行和列组成一张表单
5.若干的表单组成database
1.2 常见的数据库
关系型数据库:Oracle,MySQL,DB2(IBM),SQL Server(.net项目),PostgreSQL。。。。。
非关系型数据库(NOSql):Redis,Hbase,mogodb。。。。。。
2、数据库表的范式
关系型数据库都是使用数据表存储数据的。
为了更好的处理和存储数据,我们设定了数据表的设计方式,这个方式就是数据表的设计范式。“折中”。
2.1 范式
编号 | 姓名 | 学院专业 | 电话 |
---|---|---|---|
1 | 张三 | 计算机学院计算机科学与技术[112,3,3,3] | 123456789 |
2 | 李四 | 计算机学院计算机科学与技术 | 987654321 |
3 | 王五 | 计算机学院网络工程 | 654987321 |
上面的表中有学生的信息,但是学院专业这一栏是可以分割的。这一栏包含了两个信息。这样的表不满足第一范式。
第一范式:所谓第一范式(1NF)所有的域都应该是原子性的,即数据库表的每一列都是不可分割的原子数据项,而不能是集合,数组,记录等非原子数据项。即实体中的某个属性有多个值时,必须拆分为不同的属性。
简而言之,第一范式就是无重复的域。
编号 | 姓名 | 学院 | 专业 | 电话 |
---|---|---|---|---|
1 | 张三 | 计算机学院 | 计算机科学与技术 | 123456789 |
2 | 李四 | 计算机学院 | 计算机科学与技术 | 987654321 |
3 | 王五 | 计算机学院 | 网络工程 | 654987321 |
第二范式是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。
第二范式(2NF)要求数据库表中的每个实例或记录必须可以被唯一地区分。选取一个能区分每个实体的属性或属性组,作为实体的唯一标识。
不满足第二范式的:
姓名 | 学院 | 专业 | 电话 |
---|---|---|---|
张三 | 计算机学院 | 计算机科学与技术 | 123456789 |
李四 | 计算机学院 | 计算机科学与技术 | 987654321 |
王五 | 计算机学院 | 网络工程 | 654987321 |
张三 | 计算机学院 | 计算机科学与技术 | 654987321 |
有两个张三,无法区分
增加班级列,让姓名和班级作为主键:
班级 | 姓名 | 学院 | 专业 | 电话 |
---|---|---|---|---|
1 | 张三 | 计算机学院 | 计算机科学与技术 | 123456789 |
2 | 李四 | 计算机学院 | 计算机科学与技术 | 987654321 |
1 | 王五 | 计算机学院 | 网络工程 | 654987321 |
2 | 张三 | 计算机学院 | 计算机科学与技术 | 654987321 |
第三范式(3NF)要求一个关系中不包含已在其它关系已包含的非主关键字信息。
一张表只描述一件事。
上面的表就不满足第三方式,存在大量的学院信息和专业信息的重复现象。
将上面的表进行拆分。
学生表:
班级 | 姓名 | 电话 | 学院编号 | 专业编号 |
---|---|---|---|---|
1 | 张三 | 123456789 | 1 | 1 |
2 | 李四 | 987654321 | 2 | 3 |
1 | 王五 | 654987321 | 2 | 3 |
2 | 张三 | 6546321654 | 1 | 2 |
学院表:
学院编号 | 学院 |
---|---|
1 | 计算机学院 |
2 | 理学院 |
专业表:
专业编号 | 学院编号 | 专业 |
---|---|---|
1 | 1 | 计算机科学与技术 |
2 | 1 | 网络工程 |
3 | 2 | 应用化学 |
4 | 2 | 应用数学 |
面试题:什么是数据的三大范式?
答案:第一范式,第二范式和第三范式。
数据库一共有6个范式。
BC范式、第四范式、第五范式。
3、MySQL简介
3.1.什么是MySQL
与其他的大型数据库例如 Oracle、DB2、SQL Server等相比,MySQL [1] 自有它的不足之处,但是这丝毫也没有减少它受欢迎的程度。对于一般的个人使用者和中小型企业来说,MySQL提供的功能已经绰绰有余,而且由于 MySQL是开放源码软件,因此可以大大降低总体拥有成本。
Linux作为操作系统,Apache 或Nginx作为 Web 服务器,MySQL 作为数据库,JAVA/PHP/Perl/Python作为服务器端脚本解释器。由于这四个软件都是免费或开放源码软件(FLOSS),因此使用这种方式不用花一分钱(除开人工成本)就可以建立起一个稳定、免费的网站系统。
数据库是如何存储数据?
我们要将下面的学生信息存储到数据库:(就是存储在磁盘上)
所有的数据库都是将我们的数据按照自己的方式以文件的形式存储在磁盘
所有的关系型数据库,对于数据的增删改查,操作都是一样的。所以我们要学习的是对数据库操作的SQL语句。
3.2.MySQL的安装和连接
连接MySQL:
打开命令窗口
> mysql -uroot -p 回车 输入密码
当然我们也可以使用MySQL的一个连接工具:Navicat Premium
3.3MySQL中的数据的数据类型
数值类型
MySQL支持所有标准SQL数值数据类型。
这些类型包括严格数值数据类型(INTEGER、SMALLINT、DECIMAL和NUMERIC),以及近似数值数据类型(FLOAT、REAL和DOUBLE PRECISION)。
关键字INT是INTEGER的同义词,关键字DEC是DECIMAL的同义词。
BIT数据类型保存位字段值,并且支持MyISAM、MEMORY、InnoDB和BDB表。
作为SQL标准的扩展,MySQL也支持整数类型TINYINT、MEDIUMINT和BIGINT。下面的表显示了需要的每个整数类型的存储和范围。
类型 | 大小 | 范围(有符号) | 范围(无符号) | 用途 |
---|---|---|---|---|
TINYINT | 1 byte | (-128,127) | (0,255) | 小整数值 |
SMALLINT | 2 bytes | (-32 768,32 767) | (0,65 535) | 大整数值 |
MEDIUMINT | 3 bytes | (-8 388 608,8 388 607) | (0,16 777 215) | 大整数值 |
INT或INTEGER | 4 bytes | (-2 147 483 648,2 147 483 647) | (0,4 294 967 295) | 大整数值 |
BIGINT | 8 bytes | (-9,223,372,036,854,775,808,9 223 372 036 854 775 807) | (0,18 446 744 073 709 551 615) | 极大整数值 |
FLOAT | 4 bytes | (-3.402 823 466 E+38,-1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38) | 0,(1.175 494 351 E-38,3.402 823 466 E+38) | 单精度 浮点数值 |
DOUBLE | 8 bytes | (-1.797 693 134 862 315 7 E+308,-2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) | 0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) | 双精度 浮点数值 |
DECIMAL | 对DECIMAL(M,D) ,如果M>D,为M+2否则为D+2 | 依赖于M和D的值 | 依赖于M和D的值 | 小数值 |
日期和时间类型
表示时间值的日期和时间类型为DATETIME、DATE、TIMESTAMP、TIME和YEAR。
每个时间类型有一个有效值范围和一个"零"值,当指定不合法的MySQL不能表示的值时使用"零"值。
TIMESTAMP类型有专有的自动更新特性,将在后面描述。
类型 | 大小 ( bytes) | 范围 | 格式 | 用途 |
---|---|---|---|---|
DATE | 3 | 1000-01-01/9999-12-31 | YYYY-MM-DD | 日期值 |
TIME | 3 | '-838:59:59'/'838:59:59' | HH:MM:SS | 时间值或持续时间 |
YEAR | 1 | 1901/2155 | YYYY | 年份值 |
DATETIME | 8 | 1000-01-01 00:00:00/9999-12-31 23:59:59 | YYYY-MM-DD HH:MM:SS | 混合日期和时间值 |
TIMESTAMP | 4 | 1970-01-01 00:00:00/2038结束时间是第 2147483647 秒,北京时间 2038-1-19 11:14:07,格林尼治时间 2038年1月19日 凌晨 03:14:07 | YYYYMMDD HHMMSS | 混合日期和时间值,时间戳 |
字符串类型
字符串类型指CHAR、VARCHAR、BINARY、VARBINARY、BLOB、TEXT、ENUM和SET。该节描述了这些类型如何工作以及如何在查询中使用这些类型。
类型 | 大小 | 用途 |
---|---|---|
CHAR | 0-255 bytes | 定长字符串 |
VARCHAR | 0-65535 bytes | 变长字符串 |
TINYBLOB | 0-255 bytes | 不超过 255 个字符的二进制字符串 |
TINYTEXT | 0-255 bytes | 短文本字符串 |
BLOB | 0-65 535 bytes | 二进制形式的长文本数据 |
TEXT | 0-65 535 bytes | 长文本数据 |
MEDIUMBLOB | 0-16 777 215 bytes | 二进制形式的中等长度文本数据 |
MEDIUMTEXT | 0-16 777 215 bytes | 中等长度文本数据 |
LONGBLOB | 0-4 294 967 295 bytes | 二进制形式的极大文本数据 |
LONGTEXT | 0-4 294 967 295 bytes | 极大文本数据 |
你要知道的数据类型:
int/integer , decimal(小数值), bigint(极大整数值) ,
char , varchar, text
date(YYYY-MM-DD日期值),time(HH:MM:SS时间值或持续时间),datetime(YYYY-MM-DD HH:MM:SS混合日期和时间值),timestamp(YYYYMMDD HHMMSS 混合日期和时间值,时间戳)
4、数据表分析和设计
数据库设计:
在上面的报表中有四个实体:学生,班级,学科,成绩
准备四张数据表(一张表描述一件事)。
班级表: class_info
列名 | 类型 | 约束 | 备注 |
---|---|---|---|
class_id | bigint | 主键 | 班级编号 |
class_name | varchar | 非空 | 班级名称 |
class_desc | varchar | 班级的描述 |
学生表:student
列名 | 类型 | 约束 | 备注 |
---|---|---|---|
stu_no | varchar | 主键 | 学生编号 |
stu_name | varchar | 非空 | 学生姓名 |
stu_birth | date | 生日 | |
stu_gender | int | 默认0 | 性别 |
stu_tel | char(11) | 电话 | |
class_id | int | 外键 | 班级编号 |
课程表:course
列名 | 类型 | 约束 | 备注 |
---|---|---|---|
cid | char(3) | 主键 | 课程编号 |
cname | varchar(30) | 非空 | 课程名称 |
成绩表:score
列名 | 类型 | 约束 | 备注 |
---|---|---|---|
cid | char(3) | 主键 | 课程编号 |
stu_no | varchar | 主键 | 学生编号 |
score | int | 默认0 | 成绩 |
5、表的创建、修改与删除
创建数据库:
create database 数据库名称 ;
在编辑工具中写好sql语句,右键运行,或者点击上面的运行按钮。
双击student数据库打开。
在编辑工具中指定当前使用的数据库:
5.1.创建表
语法:
CREATE TABLE 表名(
列名 类型 [约束...],
列名 类型 [约束],
...
列名 类型 [约束]
)
创建班级表:
-- 创建班级表 --
CREATE TABLE class_info(
class_id bigint not null primary key,
class_name varchar(100) not null,
class_desc varchar(200)
);
class_id是这个表的主键。 主键的意思是这一列数据是不能重复,也不能为空。使用这一列唯一标识这一行数据。 类似于我们的身份证号码。
not null 的意思是这一列数据不能为空。
primary key 表示这一列是主键
bigint和int都是不需要指明长度
varchar(100) 这里的100表示这一列内容的最大长度。
实例:创建数据表
-- 创建班级表 --
CREATE TABLE class_info(
class_id bigint not null primary key,
class_name varchar(100) not null,
class_desc varchar(200)
);
-- 学生表 --
create table student(
stu_no varchar(20) not null primary key,
stu_name varchar(100) not null,
stu_birth date,
stu_gender int default '1',
stu_tel char(11),
class_id bigint
);
-- 课程表 --
create table course(
cid int not null primary key,
cname varchar(200) not null
);
-- 成绩表 --
create table score(
cid int not null ,
stu_no varchar(20) not null ,
score int
);
5.2.修改表、删除表
-
增加字段语法:
Alter table 表名称 add(列名1 类型 [DEFAULT 默认值],列名1 类型 [DEFAULT 默认值]...)
为学生表添加一个邮箱,类型为varchar
alter table student add email varchar(50) ;
-
修改字段语法:
ALTER TABLE 表名称 MODIFY(列名1 类型 [DEFAULT 默认值],列名1 类型 [DEFAULT 默认值]...)
修改一列数据类型
alter table student MODIFY stuName varchar(200)
-
修改字段名语法:(这个是Oracle的语法,MySQL不支持)
ALTER TABLE 表名称 RENAME COLUMN 原列名 TO 新列名
语句: 大部分的数据库都不支持修改列名的操作,所以不建议使用
ALTER TABLE T_OWNERS RENAME COLUMN OUTDATE TO EXITDATE
-
删除字段名
--删除一个字段 ALTER TABLE 表名称 DROP 列名 --删除多个字段 ALTER TABLE 表名称 DROP (列名1,列名2...)
案例:
--删除字段 alter table student drop email
-
删除表
语法:
DROP TABLE 表名称
-
给成绩表添加联合主键
alter table score add constraint pk_cid_stu_no primary key(cid,stu_no)
6、主外键关系
6.1主键
一张表中唯一确定一行记录的列称之为主键。主键又称为主键约束。
主键是不能为空的
主键是不能重复的。
一个表中最多只能有一个主键。
主键可以由多个列组成。 多列组成的称之为联合主键。
6.1.1给一张已经创建好的表添加主键语法:
ALTER TABLE 表名 ADD CONSTRAINT 约束名称(PK_XXX) PRIMARY KEY(列名)
将课程表的课程编号设置为主键
alter table course add constraint pk_cid primary key(cid)
如果是多列联合作为主键。这种主键就称之为联合主键。 语法:
ALTER TABLE 表名 ADD CONSTRAINT 约束名称(PK_XXX) PRIMARY KEY(列名1,列名2,列名....)
给成绩表添加联合主键:
alter table score add constraint pk_stuNo_cid primary key(stuNo,cid);
6.1.2 在创建表的同时设置主键
语法1:
CREATE TABLE TABLE_NAME( TID NUMBER PRIMARY KEY, -- 直接将TID这一列设置为主键,这里的主键名称会自动生成 -- ...... );
语法2:
CREATE TABLE TABLE_NAME( TID NUMBER NOT NULL, TNAME VARCHAR2(20) NOT NULL, ...... ADD CONSTRAINT PK_TID_TNAME PRIMARY KEY(TID,TNAME)-- 添加联合主键 -- );
6.2 外键
如果公共关键字在一个关系中是主关键字,那么这个公共关键字被称为另一个关系的外键。
成绩表中的学号就是外键,成绩表中的学号都是来自于学生信息表。
学生信息表一般称之为主表(基表),成绩表称之为子表(从表)。
从表中的学号为外键,外键的列中的数据全部来自于主表。
外键有的数据,主表肯定有,主表有的数据外键不一定有。
外键引用的列是不能为null的。
外键的引用的列必须是唯一的。
外键引用的列不一定是主键。
6.2.1给已经创建好的表添外键
语法:
ALTER TABLE TABLE_NAME ADD CONSTRAINT 外键名称(FK_XXX) FOREIGN KEY(列名) REFERENCES TABLE_NAME1(列名)
我们当前的四张表表中,学生表的班级编号就是来自于班级表。
我们给学生表的班级编号添加一个外键
alter table student add constraint fk_class_id foreign key(class_id) references class_info(class_id)
外键就约束了学生表中添加数据的时候,不能随意的添加班级编号,班级编号必须在班级表中存在。
6.2.2 创建表的同时添加外键
根添加主键的语法是一样的。
案例:创建成绩表的时候直接添加外键
create table score( stuNo varchar(20) not null , cid char(3) not null references course(cid), -- 添加外键随机生产一个外键名称 -- score int default '0', add constraint fk_stuNo foreign key(stuNo) references student(stuNo) -- 添加外键 -- );
7、数据增删改
7.1插入数据
语法:
INSERT INTO 表名[(列名1,列名2,...)]VALUES(值1,值2,...)
执行INSERT后一定要再执行 commit 提交事务
给课程标题添加数据:
-- 给课程表添加数据 -- insert into course(cid,cname) values('001','忍术'); insert into course(cid,cname) values('002','幻术'); insert into course(cname,cid) values('体术','003'); commit;
给学生表添加几条数据:
-- 常规操作(window表名和列名不区分大小写,Linux下默认是区分大小写) -- -- 表名后的列名是没有顺序要求的,但是values里面的数据要和前面的列名顺序一致 -- insert into student(stu_no,stu_name,stu_birth,stu_gender,stu_tel,class_id) values('1001','梅超风','1997-09-08',2,'13513513535',1); insert into student(stu_no,stu_name,stu_birth,stu_gender,stu_tel,class_id) values('1002','程旋风','1996-10-08',1,'13513513536',1); -- 如果values后面的数据和数据表的列名顺序完全一致,可以省略表名后的列名(不推荐) -- insert into student values('1003','陆乘风','1995-06-25',1,'13813813838',2); -- 如果要使用某一列的默认值,可以使用defaule或者,不写 -- insert into student(stu_no,stu_name,stu_birth,stu_gender,stu_tel,class_id) values('1004','欧阳锋','1990-10-08',default,'13513513537',2); insert into student(stuNo,stuName,stuBirth,stuTel) values('1005','黄家驹','1999-11-09','13513513538'); -- 某一列可以为空,如果不写,则默认为null -- insert into student(stu_no,stu_name,stu_birth,stu_gender,class_id) values('1006','时迁','1999-11-09',1,2);
①如果添加的数据和默认的列的顺序一致,并且所有的列都添加了数据,则可以不写表名后面的列名。
②如果一个列是not null,则在添加数据的时候,必须给该列添加数据。
③如果一个列可以为空,并且不想添加数据, 则不要写列名和数据列,一定要确保表名后面的列名和values后面的数据个数和类型一致。
④SQL中没有双引号,只有单引号,所有的字符,字符串,日期基本都是使用单引号。数字不用引号。
⑤一个表如果有外键关系,则必须保证外键关系成立。
⑥确保主键的约束成立。
几个错误的案例:
-- not null 的列必须加入数据 -- insert into student(stuNo,,stuBirth,stuGender) values('1006','1999-11-09',1); -- 出错: Field 'stuName' doesn't have a default value -- 违反 主键约束 主键重复-- insert into student(stuNo,stuName,stuBirth,stuGender) values('1006','王大锤','1999-11-09',1); -- 出错 : Duplicate entry '1006' for key 'PRIMARY' -- 违反外键约束 -- -- 准备 -- insert into course(cid, cname) values('001','java') -- 给成绩表添加成绩 -- insert into score(stuNo,cid,score) values('1009','001',100) -- 出错:Cannot add or update a child row: a foreign key constraint fails (`student`.`score`, CONSTRAINT `fk_stuNo` FOREIGN KEY (`stuNo`) REFERENCES `student` (`stuNo`))
7.2修改和删除数据
1 修改数据
语法:
UPDATE 表名 SET 列名1=值1,列名2=值2,....WHERE 修改条件;
需求:
-- 将所有人的性别全部修改为0 -- update student set stu_gender = 0; -- 修改所有名字后面有”风“的性别为1 -- update student set stu_gender = 1 where stu_name like '%风' -- 同时修改多列 -- update student set stu_name = '司马迁',stu_gender = 1 where stu_no = '1006'
set 后面可以同时修改多个列,分别使用“,”隔开。如果没有条件就是修改表中的所有数据。
tips:使用update的时候,一定要考虑条件
2 删除数据
语法:
DELETE FROM 表名 WHERE 删除条件;
执行DELETE后一定要再执行commit提交事务
需求:删除所有学生信息
delete from student
delete 删除数据时,如果不添加条件会删除整张表的数据。
删除没有手机号码的学生的信息
delete from student where stu_tel is null
删除数据的时候,要考虑外键关系,要先删除子表数据,再删除主表数据:
-- 准备 -- insert into score(stuNo,cid,score) values('1006','001',100); -- 删除学号为 1006的学生信息 -- delete from student where stu_no = '1006' -- 错误:Cannot delete or update a parent row: a foreign key constraint fails (`student`.`score`, CONSTRAINT `fk_stuNo` FOREIGN KEY (`stuNo`) REFERENCES `student` (`stuNo`)) -- : 要先删除成绩信息,再删除学生信息
语法2:
TRUNCATE TABLE 表名称
删除整张表中的数据。 只能删除整张表。
面试题:
比较truncate与delete实现数据删除?
-
delete删除的数据可以rollback,delete删除可能产生碎片,并且不释放空间
-
truncate是先摧毁表结构,再重构表结构
-
先把数据表干掉
-
创建一个新的数据表
-
无法rollback
-
8、单表查询(1)
准备数据:
insert into course(cid,cname) values('002','LOL'); insert into score(stuNo,cid,score) values('1001','001',85);
单表查询的sql语句:
select 列名 from 表名 where 查询条件
group by 分组条件 having 分组后的条件 order by 排序条件 [limit ]分页使用的
8.1查询所有数据
语法:
select * from 表名 -- 这里的*表示所有列 -- select * from student; -- 查询的结构就是一张虚表 --
8.2 查询部分列
语法:
select 列名,列名 from 表名 select stuNo,stuName from student;
8.3查询部分行
语法:
select * from student where xxxxxx
8.3.1 关系运算和逻辑运算符
案例:
-- 查询课程号 001 的成绩信息-- select * from score where cid = '001' -- 查询课程号不是 001 程序 -- select * from score where cid <> '001' select * from score where cid != '001' -- 查询课程号 001 的,并且成绩在80以上的学生学号 -- select stuNo from score where cid = '001' and score >= 80
对照表:
java | sql |
---|---|
> | > |
< | < |
>= | >= |
<= | <= |
== | = |
!= | != / <> |
&& | and |
or | or |
! | not |
8.3.2模糊查询
[1] is null和is not null
tips:判断某一列是否为null,要使用is null, 而不是 = null
-- 查询手机号码为 null 学生信息 -- select * from student where stuTel is null; -- 查询手机号码不为 null 学生信息 -- select * from student where stuTel is not null;
[2]like
语法:
select * from 表名 where xxx like '%_哈哈';
% 表示任意多个任意字符
_ 表示一个字符
-- 查询姓梅的学员 -- select * from student where stuName like '梅%'; -- 查询名字中有”风“ -- select * from student where stuName like '%风%'; -- 查询复姓”欧阳“,名字只有一个字的 -- select * from student where stuName like '欧阳_';