为什么要学习数据库
以前在程序中存储数据是一个变量,对象;数据都存储在内存中,程序运行结束后就销毁。
后来学习IO之后,将数据存储在文件中,做到持久存储,但是使用不方便。
学习专业的数据存储软件——数据库软件
数据库概述
数据库(DataBase/db)为了方便数据的存储和管理,它将数据按照特定的规则存储在磁盘上,就是一个存储数据的仓库
相关概念:
DB:数据库;存储数据的容器,他保存了一系列有组织的数据
DBMS:数据库管理系统;又称为数据库软件或数据库产品,用于创建或管理DB。
常见的数据库产品:
国外
-
MySQL 开源版本,也有付费版
-
Oracle数据库 付费版
-
SQL Server(微软)
-
DB2 (IBM)
国内(一般是政府项目使用)
-
南大通用GBASE: 天津南大通用数据技术股份有限公司
-
达梦:武汉达梦数据库股份有限公司
-
人大金仓:北京人大金仓信息技术股份有限公司
-
神通:神舟通用公司
Mysql数据库
MySQL是一个关系型数据库管理系统,具有快速、可靠和易于使用的特点,支持多种操作系统,支持多种编程语言连接。
关系型数据库?
以数据表为单位,表与表之间存在关联关系
非关系型数据库 redis:缓存(key:value)
结构化查询语言(Structured Query Language)简称SQL,是一种特殊目的的编程语言,是一种数据库查询和程序设计语言,用于存取数据以及查询、更新和管理关系数据库系统。
三种语言
在sql语言中根据操作不同,又分为不同类型的sql语句:
DDL
DDL(数据定义语言):用于创建和修改数据库表结构的语言。
创建删除数据库
-- 创建数据库,并设置字符集编码 并判断数据库是否存在
CREATE DATABASE IF NOT EXISTS test CHARSET utf8;
-- 删除数据库
DROP DATABASE test;
-- mysql数据库一旦创建不能修改,只能修改字符集编码
ALTER DATABASE test CHARSET gbk
创建数据库表
/*表 表名列 特定信息 姓名、性别...行 数据 张三 男
创建表的步骤确定表名:学生信息--学生表确定列名:学生的具体信息 姓名、性别、生日...列的数据类型:字符串型:char(n) 长度为n的定长字符串varchar(n) 最大长度为n的变长字符串日期时间类型:date 日期--年 月 日datetime 时间--年 月 日 时分秒数值:整数TINYINT 一个字节SAMALLINT 两个字节MEDIUMINT 三个字节INT 四个字节BIGINT 八个字节浮点数decimal(M,D) M表示总长,D表示小数点后几位TEXT列字符字符串 长文本类型
*/
-- 学生表 学号,姓名,性别,生日,电话,地址,身高,注册时间
CREATE TABLE student(num INT,name VARCHAR(10),gender CHAR(1),birthday DATE,phone CHAR(11),address VARCHAR(30),height DECIMAL(3,2),reg_time DATETIME
)
-- 删除表
DROP TABLE student
-- 创建表,并为列添加约束
/*学号 唯一,不能为空,而且只能有一个学号;可以添加主键约束(唯一不能重复,不能为空,一个表中只能有一个主键约束)PRIMARY KEY 设置主键AUTO_INCREMENT 设置主键列自动增长,只修饰主键列,而且为整数NOT NULL 不能为空约束 可添加到多个列UNIQUE 唯一约束 可添加到多个列DEFAULT '默认值' 添加默认值COMMENT '注释' 添加注释姓名,性别,生日,电话,地址,身高,注册时间
*/
CREATE TABLE student(num INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(10) NOT NULL,gender CHAR(1) NOT NULL,birthday DATE,phone CHAR(11) NOT NULL UNIQUE,address VARCHAR(30),height DECIMAL(3,2) NOT NULL,reg_time DATETIME
)
-- 修改表名
RENAME TABLE student to stu
RENAME TABLE stu to student
-- 复制表结构
CREATE TABLE stu LIKE student
-- 修改表,添加列
ALTER TABLE student ADD id INT
-- 修改表,添加外键约束
ALTER TABLE student ADD CONSTRAINT 约束名 FOREIGN KEY(majorid) REFERENCES major(id)
DML
DML:数据操纵语言;常用语句insert,delete,update
-- insert 插入
/*方式1: INSERT INTO 表名(列1,列2……,列n) VALUES(值1,值2…..,值n);方式2: INSERT INTO 表名 set 列名1=值1,..列名n=值n;方式3: INSERT INTO 表名(列1,列2……,列n) VALUES(值1,值2…..,值n),(值1,值2…..,值n);方式4:INSERT INTO 表名(列1,列2……,列n) 查询语句(查询的列数与插入列数匹配)
*/
INSERT INTO student(NAME,gender,birthday,phone,address,height,reg_time) VALUES('王天乐','女','2004-5-3','2123456789322','汉中',1.75,'2024-5-3')
INSERT INTO student(NAME,gender,birthday,phone,address,height,reg_time) VALUES('Jim','女','2004-5-3','2123456789452','England',1.75,'2024-5-3')
INSERT INTO student(NAME,gender,birthday,phone,address,height,reg_time)VALUES('张三','男','2004-5-3','13488404582','汉中',1.75,'2024-5-3'),('李四','女','2004-5-5','13488404552','汉中',1.65,'2024-2-3'),('窦鑫锐','男','2001-5-3','13688404582','汉中',1.35,'2044-5-3')
INSERT INTO stu(NAME,gender,birthday,phone,address,height,reg_time) SELECT NAME,gender,birthday,phone,address,height,reg_time FROM studentINSERT INTO student SET NAME='王天乐',gender='女',phone='2123456789321'
-- update 修改 需要注意条件的准确性,否则修改所有数据
UPDATE student SET address = '窦鑫锐' WHERE num = 1
-- delete 删除
DELETE FROM student WHERE num=1
DQL
DQL:数据查询语言查询是使用频率最高的一个操作,可以从一个表中查询数据,也可以从多个表中查询数据
-- 基本查询语法
-- select 查询的列 from 表名 where 条件 排序 数量限制 分组......
-- select 结果处理 from 表名
-- 结果处理
-- 查询特定的列
SELECT num,NAME,gender FROM student
-- 查询所有的列,在开发中一般不建议,使用哪些列查询哪些
SELECT * FROM student
-- sql中+ - * / 只能做算数运算,+不能连接字符串
SELECT num+100,NAME FROM student
-- 去除查询结果中重复数据,即查询到所有列都相同
SELECT DISTINCT NAME,gender,birthday FROM student
查询结果中使用函数
-
单行函数会对查询的每条记录进行操作
-
分组函数也称为聚合函数,统计函数,把多行最终处理为一行
-- 字符函数
-- length():获取参数值的字节个数
SELECT LENGTH(NAME) FROM student
-- char_length()获取参数值的字符个数
SELECT CHAR_LENGTH(NAME) FROM student
-- concat(str1,str2,.....):拼接字符串 AS 后面为别名
SELECT num,CONCAT(NAME,':',gender) AS NAME FROM student
-- upper()/lower():将字符串变成大写/小写
SELECT UPPER(NAME),LOWER(NAME) FROM student
-- substring(str,pos,length):截取字符串 位置从1开始
SELECT SUBSTRING(NAME,2,3) FROM student
-- instr(str,指定字符):返回子串第一次出现的索引,如果找不到返回0
SELECT INSTR(NAME,'三') FROM student
-- trim(str):去掉字符串前后的空格或子串,trim(指定子串 from 字符串)
SELECT TRIM(NAME) FROM student
SELECT TRIM('张' FROM NAME) FROM student
-- lpad(str,length,填充字符):用指定的字符实现左填充将str填充为指定长度
SELECT LPAD(NAME,5,'a') FROM student
-- rpad(str,length,填充字符):用指定的字符实现右填充将str填充为指定长度
SELECT RPAD(NAME,5,'b') FROM student
-- replace(str,old,new):替换,替换所有的子串
SELECT REPLACE(NAME,'i','I') FROM student
-- 逻辑处理
-- case when 条件 then 结果1 else 结果2 end; 可以有多个when
SELECT NAME,(CASE WHEN height>=1.80 THEN '高个子'WHEN height>=1.50 THEN '正常身高'ELSE '低个子' END) AS height,gender FROM student
-- ifnull(被检测值,默认值)函数检测是否为null,如果为null,则返回指定的值,否则返回原本的值
SELECT NAME,IFNULL(adress,'暂未录入') AS address FROM student
-- if函数:if else的 效果 if(条件,结果1,结果2)
SELECT NAME,IF(height>=1.80,'高个子','正常身高') AS height FROM student
-- 数学函数
-- round(数值,小数位数):四舍五入 不写小数位数相当于只保留整数
SELECT NAME,ROUND(height,1) FROM student
-- ceil(数值):向上取整,返回>=该参数的最小整数
SELECT NAME,CEIL(height) FROM student
-- floor(数值):向下取整,返回<=该参数的最大整数
SELECT NAME,FLOOR(height) FROM student
-- truncate(数值,保留小数的位数):截断,小数点后截断到几位,不会四舍五入
SELECT NAME,TRUNCATE(height,1) FROM student
-- mod(被除数,除数):取余,被除数为正,则为正;被除数为负,则为负
SELECT NAME,MOD(num,3) FROM student
-- rand():获取随机数,返回0-1之间的小数
SELECT NAME,RAND() FROM student
-- 日期函数
-- now():返回当前系统日期+时间
SELECT NAME,NOW() FROM student
-- curdate():返回当前系统日期,不包含时间
SELECT NAME,CURDATE() FROM student
-- curtime():返回当前时间,不包含日期
SELECT NAME,CURTIME() FROM student
-- 可以获取指定的部分,年、月、日、小时、分钟、秒YEAR(日期列),MONTH(日期列),DAY(日期列) ,HOUR(日期列) ,MINUTE(日期列)SECOND(日期列)
SELECT NAME,YEAR(reg_time),MONTH(reg_time),DAY(reg_time) FROM student
-- str_to_date(字符串格式日期,格式):将日期格式的字符转换成指定格式的日期
SELECT STR_TO_DATE('2001-2-6','%Y-%m') FROM student
-- date_format(日期列,格式):将日期转换成字符串
SELECT DATE_FORMAT(birthday,'%y-%m') FROM student
-- datediff(big,small):返回两个日期相差的天数
SELECT DATEDIFF(CURDATE(),birthday) FROM student
-- 分组函数/聚合函数、统计函数
-- sum,avg一般处理数值类型的值,max,min,count可处理任意类型的值
-- sum(列名)求和
SELECT SUM(height) FROM student
-- avg(列名)平均值
SELECT AVG(height) FROM student
-- max(列名)最大值
SELECT MAX(height) FROM student
-- min(列名)最小值
SELECT MIN(height) FROM student
-- 计数count(*)、count(1)、count(列名),列的值为空不统计,推荐使用第一个
SELECT COUNT(*) FROM student
-- 条件查询 select 结果列 from 表名 where 条件SELECT * FROM student WHERE num=1
-- and 必须满足所有条件
SELECT * FROM student WHERE gender='男' AND height>=1.70 AND address='汉中'
-- or 满足一个条件即可
SELECT * FROM student WHERE gender='男' OR height>=1.70-- 不等于 != / <>
SELECT * FROM student WHERE gender!='男'
SELECT * FROM student WHERE gender<>'男'-- 模糊查询 LIKE 字符 %字符% 通配符
SELECT * FROM student WHERE NAME LIKE '张%'
SELECT * FROM student WHERE NAME LIKE '%三%'-- between and 两者之间,包含临界值
SELECT * FROM student WHERE height BETWEEN 1.70 AND 2.0-- in 判断某字段的值是否属于in列表中的某一项
SELECT * FROM student WHERE height IN(1.75,1.85,1.95)
-- not 取非
SELECT * FROM student WHERE height NOT IN(1.75,1.85,1.95)-- is (not) null 为(非)空
SELECT * FROM student WHERE address IS NULL
SELECT * FROM student WHERE address IS NOT NULL
-- union 合并多个查询结果,可以去除重复项
SELECT num,NAME,gender FROM student WHERE gender='男'
UNION
SELECT num,NAME,gender FROM student WHERE height>1.60
-- union all 合并多个查询结果,但是不去重
SELECT num,NAME,gender FROM student WHERE gender='男'
UNION ALL
SELECT num,NAME,gender FROM student WHERE height=1.75
-- 排序
-- order by 排序列 ASC/DESC ASC代表的是升序,DESC代表的是降序,如果不写,默认是升序
SELECT * FROM student ORDER BY height
SELECT * FROM student ORDER BY height ASC
SELECT * FROM student ORDER BY height DESC
-- 多个条件排序
SELECT * FROM student ORDER BY height DESC,birthday ASC
-- 什么排序都不写默认按照主键升序排列
SELECT * FROM student
-- 数量限制 limit 开始位置(开始位置为0),查询的数量 实际使用场景为数据分页显示,一次只查询一部分数据,提高查询效率
SELECT * FROM student LIMIT 0,2
SELECT * FROM student LIMIT 2,2
SELECT * FROM student LIMIT 4,2
-- limit 在sql语句的末尾出现
-- 分组查询 在分组函数中也可以使用分组函数来进行相应的操作
-- 将某类数据分到一个组中进行处理,例如性别查询
-- 查询男生,女生各有多少人,按照性别分组
-- GROUP BY 分组条件(列名) 用谁分组谁就可以出现在结果中
SELECT COUNT(*),gender FROM student GROUP BY gender
-- 统计每年出生的人数
SELECT COUNT(*)AS number,YEAR(birthday) FROM student GROUP BY YEAR(birthday)
SELECT COUNT(*)AS number,DATE_FORMAT(birthday,'%Y')AS YEAR FROM student GROUP BY DATE_FORMAT(birthday,'%Y')
-- 分组统计姓名,查询哪些姓名重复
-- where 是对原始表中的数据进行过滤
-- HAVING在GROUP BY后面使用,可以直接对分组后的数据进行查询
SELECT * FROM (SELECT COUNT(*)AS number,NAME FROM student GROUP BY NAME)AS t WHERE t.number>1
SELECT COUNT(*)AS number,NAME FROM student GROUP BY NAME HAVING number>1
多表设计_关联查询
数据库设计范式,好的数据库设计,事半功倍,不会有歧义
第一范式
第一范式是最基本的范式(确保每列保持原子性)。如果数据库表中的所有字段值都是不可分解的原子值,就说明该数据库表满足了第一范式。
第二范式
简单的来说就是要有主键;也就是要求其他字段都依赖于主键
通过主键可以精确的定位到某一行的数据
第三范式
不用的信息可以放在不同的表中,如果两张表有关系的话,只需要在另一张表中放另一张表的主键进行关联,关联表中其他的非主键信息就不需要了。
外键
外键:引用另外一个数据表的某条记录。
外键列类型与主键列类型保持一致
数据表之间的关联/引用关系是依靠具体的主键(primary key)和外键(foreign key)建立起来的.
-
当主表中没有对应的记录时,不能将记录添加到从表
-
不能更改主表中的值而导致从表中的记录孤立
-
从表存在与主表对应的记录,不能从主表中删除该行
-
删除主表前,先删从表
关联查询
关联查询也称多表查询
-- 查询学生信息 学号,姓名,性别,生日,专业
-- 如果不佳任何关联条件,会导致出现笛卡尔乘积现象
SELECT * FROM student,major-- 内连接,只把满足条件的筛选出来
SELECT * FROM student,major WHERE majorid=id
SELECT * FROM student s INNER JOIN major m ON s.majorid=m.id-- 外连接,
-- 左外连接 把左边表中所有数据查询出来,右边表中只会查询满足条件的
SELECT * FROM student s LEFT JOIN major m ON s.majorid=m.id-- 右外连接 把右边表中所有数据查询出来,左边表中只会查询满足条件的
SELECT * FROM student s RIGHT JOIN major m ON s.majorid=m.id-- 统计每个专业的学生
SELECT COUNT(s.num),m.name FROM student s RIGHT JOIN major m ON s.majorid=m.id GROUP BY m.name-- GROUP_CONCAT() 把同一组中,多个课程名称连接起来
-- 查询学生选课
SELECTs.num,s.name,s.gender,m.name,GROUP_CONCAT(c.name) cnameFROM student s LEFT JOIN major m ON s.majorid = m.midLEFT JOIN student_course sc ON s.num = sc.student_numLEFT JOIN course c ON c.id = sc.courseidGROUP BY s.num,s.name,s.gender,m.name
-- 自连接
SELECT * FROM AREA ap JOIN AREA ac ON ap.id = ac.pid JOIN AREA ax ON ac.id = ax.pid
-- 子查询 在一个查询语句中又出现了查询语句
-- 子查询可以出现在from 或者where后面
-- from之后称为表子查询(结果一般魏多行多列)把查询结果当作一张表
-- where 标量子查询(结果集只有一行一列)
-- 列子查询(结果集只有一列多行)
-- 查询身高最高的学生 标量子查询
SELECT * from student WHERE height=(SELECT MAX(height) FROM student)
-- 列子查询
SELECT * from student WHERE height IN(SELECT height FROM student WHERE height=1.65 OR height=1.75)
-- 查询姓名重复 表子查询
SELECT * FROM (SELECT COUNT(*)AS number,NAME FROM student GROUP BY NAME)AS t WHERE t.number>1