数据类型(整数)
MySQL支持所有标准SQL数值数据类型:
关键字INT是INTEGER的同义词,m表示该数据类型指定的显示宽度,指定能够显示的数值中数字的个数。比如说,定义:year int(4),声明一个只显示4位数字宽度表示年的字段
显示宽度和数据类型的取值范围是无关的(int unsigned)
数据类型(小数)
关键字DEC是DECIMAL的同义词
MySQL中使用浮点数和定点数来表示小数。它们都可以用(m,n)来表示,其中m称为精度,表示总共的位数;n称为标度,是表示小数的位数(会四舍五入)
数据类型(日期)
date 20190101 (格式要求严格,差一位都不行)
如果定义了timestamp 不能为空值,默认为当前时间(不常用)
插入值时 values(now())代表当前时间
create table t_5(
dt datetime NOT NULL #非空
DEFAULT CURRENT_TIMESTAMP #默认当前时间
ON UPDATE CURRENT_TIMESTAMP #更新时使用当前时间
)
数据类型(字符串)
char(18) 最多255个字符
定长存储,浪费空间,范围小,节省时间
不足的位数补空格(查询时不显示空格)
varchar(18)最多65535个字符
变长存储,节省空间,范围大,存取速度慢
char适合:身份证号/手机号/QQ号用户名密码等经常做查询的
varchar适合:评论,朋友圈,微博等查询频率不高的
数据类型(枚举/集合)
enum 单选行为(枚举)
- 例如建表时定义字段
- 性别 enum(“男”,“女”)
set 多选行为(集合)
- 例如建表时定义字段
- 爱好 set(“游泳”,“篮球”,“下棋”,“音乐”,“旅游”)
- insert into t_1 values(1,"shang","游泳,篮球,音乐")
- insert into t_1 values(2,"Alex","洗头,洗头,旅游,按摩")
- 会自动去重和去掉不存在的
主键
-
表中的每一行都应该具有可以唯一标识自己的一列(或一组列)
-
而这个承担标识作用的列称为主键。
如果没有主键,数据的管理将会十分混乱。比如会存在多条一模一样的记录,删除和修改特定行十分困难
-
任何列都可以作为主键,只要它满足以下条件:
- 任何两行都不具有相同的主键值(唯一)
- 每个行都必须具有一个主键值(不能为空)
- 主键列的值不允许进行修改和更新
设置主键
-- 创建数据库
CREATE DATABASE test2;
-- 显示数据库列表
SHOW DATABASES;
--使用数据库
USE test2;
-- 创建表之后设置主键:
CREATE TABLE t1(id INT NOT NULL,NAME CHAR(20));
ALTER TABLE t1 ADD PRIMARY KEY (id);
-- 创建时就带有主键的
CREATE TABLE t2(id int primary key,name char(20));
-- 自动更新的主键
CREATE TABLE t_user(
id INT PRIMARY KEY AUTO_INCREMENT,
-- id 你自己起的字段名字。
-- int 数据类型,整型。
-- primary key 定义这个字段为主键。
-- auto_increment 定义这个字段为自动增长,即如果INSERT时不赋值,则自动加1
uname VARCHAR(32) );
-- 添加信息
INSERT INTO t_user(uname) VALUES('吕布')
-- 查看
SELECT * FROM t_user;
select查询
CREATE TABLE t_user(id INT PRIMARY KEY AUTO_INCREMENT,uname VARCHAR(32),age INT,country VARCHAR(10));
INSERT INTO t_user(uname) VALUES('吕布')
-- 查询一个表中的所有数据(所有列)
SELECT * FROM t_user;
-- 查询某一列
SELECT uname FROM t_user;
-- 查询某几列
SELECT uname,country,age FROM t_user;
-- 修改select后面字段的顺序可以修改显示结果的顺序
-- 查询某几列,并且所有人年龄增加50(使用算数表达式)
SELECT uname,country,age+50 FROM t_user;
-- 修改列名的显示(起别名)注意不要用关键字,as可以省略
SELECT age+50 AS '年龄' FROM t_user;
-- 查询时去除重复项(国家会重复)
SELECT DISTINCT country FROM t_user;
-- distinct:作用范围是后面所有字段的组合(可以有多个字段)
SELECT DISTINCT country,uname FROM t_user;
-- 查询每个国家都有谁,注意:distinct后面的字段用逗号分隔,逗号两边不能有空格
排序
SELECT DISTINCT country,uname FROM t_user ORDER BY country;
-- 按国家排序
SELECT DISTINCT country,uname,age FROM t_user ORDER BY country,age;
-- 按国家和年龄排序(默认从低到高)
SELECT DISTINCT country,uname,age FROM t_user ORDER BY country,age DESC;
-- 排列顺序从高到低
SELECT DISTINCT country,uname,age FROM t_user ORDER BY country,age ASC;
-- 排列顺序从低到高(默认)
-- ASC升序,DESC降序,
限制查询条件
-- 查出所有年龄超过20岁的人
SELECT uname,age FROM t_user WHERE age>20;
-- 查出某个国家所有年龄超过20的人
SELECT uname,age FROM t_user WHERE age>20 AND country='魏国';
-- 查出年龄为21或者67的人
SELECT uname FROM t_user WHERE age=21 OR age=67;
设置查询条件
like:
- WHERE 子句中可以使用等号 = 来设定获取数据的条件, country='魏国’
- 但是有时候我们需要获取含有某个字符的所有记录,这时我们就需要在 WHERE 子句中使用 LIKE 子句
- SELECT uname,age FROM t_user WHERE age>20 AND uname LIKE ‘吕%';
- SELECT uname,age FROM t_user WHERE age>20 AND uname LIKE ‘%乔';
- SQL LIKE 子句中使用百分号 %字符来表示任意字符,如果没有使用百分号 %, LIKE 子句与等号 = 的效果是一样的
分页
在查询时可以只检索前几条或者中间某几行数据(数据量很大时,几百万条)
SELECT * FROM t_user LIMIT 0,3;
limit 后面的第一个数字设置从哪里开始检索(偏移量,从0开始)
limit 后面的第二个数字是设置显示多少条
函数-聚合函数
1.什么是聚合函数
聚合函数aggregation function又称为组函数。 ``认情况下 聚合函数会对当前所在表当做一个组进行统计。
2.聚合函数的特点
1.每个组函数接收一个参数(字段名或者表达式) 统计结果中默认忽略字段为NULL的记录
2.要想列值为NULL的行也参与组函数的计算,必须使用IFNULL函数对NULL值做转换。
3.不允许出现嵌套 比如sum(max(xx))
为了快速得到统计数据(多条数据的统计结果),mysql数据中的最常用的五个聚合函数,
count(): 查询表中某项数据一共包含多少条(统计总数)
-- 查询表中共包含多少条数据(会检索所有列)
SELECT COUNT(*) FROM t_user ;
-- 查询表中一共有多少个人(只会检索一列)
SELECT COUNT(uname) FROM t_user ;
-- 推荐使用第二种写法,可以提高效率
max(列):求此列的最大值
SELECT MAX(age) FROM t_user ;
min(列):求此列的最小值
SELECT MIN(age) FROM t_user ;
sum(列):求此列的和
SELECT SUM(age) FROM t_user ;
avg(列):求此列的平均值
SELECT AVG(age) FROM t_user ;
-- 查出总人数、最大年龄、最小年龄、年龄的总和、平均年龄
SELECT COUNT(uname),MAX(age),MIN(age),SUM(age),AVG(age) FROM t_user ;
内置函数(了解即可)
字符串函数
-- ascii(str)查看字符的ASCII码值,str是空时返回0
SELECT ASCII('a')
-- char(数字)查看ASCII码值对应的字符
SELECT CHAR(97)
-- concat(str1,str2,...)拼接字符串
SELECT CONCAT(12,34,'ab')
SELECT uname,CONCAT(age,'岁') FROM t_user;
-- length(str)字符串中包含的字符个数
SELECT LENGTH('abc')
-- space(n):返回由n个空格组成的字符串
-- replace(str,from_str,to_str):替换字符串
SELECT REPLACE('123abc123','123','def')
-- lower(str) upper(str):大小写转换
SELECT LOWER('aBcD')
SELECT UPPER('aBcD')
截取字符串
-- left(str,len)截取字符串左端的len个字符
SELECT LEFT('qwertyui',3)
-- right(str,len)截取字符串右端的len个字符
SELECT RIGHT('qwertyui',3)
-- substring(str,pos,len) 指定位置截取:截取字符串str的位置pos起的len个字符(从1开始)
SELECT SUBSTRING('qwertyuio',2,3)
SELECT SUBSTRING(uname,1,1) FROM t_user;
-- 截取所有人物的姓
SELECT DISTINCT SUBSTRING(uname,1,1) FROM t_user;
-- 同时去除重复项
去除空格
-- ltrim(str):返回删除了左空格的字符串
SELECT LTRIM(' abc ')
-- rtrim(str):返回删除了右空格的字符串
SELECT RTRIM(' abc ')
-- trim(方向 remstr from str):返回从某侧删除remstr后的字符串str
-- 方向词包括both(两侧)、leading(左)、trailing(右)
SELECT TRIM(‘ abc ’) --删除两侧空格
SELECT TRIM(BOTH ‘x’ FROM ‘xxxabcxxx’) --删除两侧特定字符
SELECT TRIM(LEADING 'x' FROM 'xxxabcxxx')
SELECT TRIM(TRAILING 'x' FROM 'xxxabcxxx')
数学函数
-- abs(n):求绝对值
SELECT ABS(-30)
-- mod(m,n):求m%n的余数
SELECT MOD(3,2)
-- floor(n):表示向下取整
SELECT FLOOR(5.6)
-- ceiling(n):表示向上取整
SELECT CEILING(5.6)
-- round(n): 表示将值 n 四舍五入为整数,无小数位
SELECT ROUND(5.6)
-- round(n,d): 表示将值 n 四舍五入为小数点后 D 位的数值,D为小数点后小数位数
-- 若要保留 n 值小数点左边的 D 位,可将 D 设为负值
SELECT ROUND(345.6789,2)
-- pow(x,y):求x的y次幂
SELECT POW(2,3)
-- PI():获取圆周率
SELECT PI( )
-- rand():获取一个0.0-1.0之间的随机数
SELECT RAND( )
-- 其他:还有其他很多三角函数,网上查询即可
日期和时间函数
-- 获取当前日期
SELECT CURRENT_DATE()
-- 获取当前时间
SELECT CURRENT_TIME()
-- 获取当前日期和时间
SELECT NOW()
-- 举例
UPDATE t_user SET birthday = NOW() WHERE uname = '吕布'
-- date_format(data,format)
SELECT DATE_FORMAT('2018-8-8','%Y年%m月%d日')
SELECT DATE_FORMAT(CURRENT_DATE(),'%y年%m月%d日')
UPDATE t_user SET brithday=DATE_FORMAT(CURRENT_DATE(),'%y年%m月%d日') WHERE uname = '吕布';
-- format参数可用的值如下:
-- %Y 年份,返回4 位整数
-- %y 年份,返回2 位整数
-- %m 月,返回0-12的整数
-- %d 日期,返回0-31之间的整数
-- %H 小时 (00..23)
-- %h 小时 (01..12)
-- %i 分钟(00..59)
-- %s 秒 (00..59)
分组查询和过滤
-- 分组:将表中数据分成若干小组,例如分为男人和女人,不同国籍等等
-- 语法格式:group by
-- 查看每个国家有多少人
SELECT COUNT(*) FROM t_user GROUP BY country;
-- 绿色部分通过COUNT() 函数返回指定列的行数(有多少条数据)
-- 蓝色部分通过国家去分组,显示每个国家有多少人
-- 查看每个国家的平均年龄
SELECT AVG(age) FROM t_user GROUP BY country;
-- 查看每个国家的总人数,年龄总和,平均年龄,最高年龄,最低年龄
SELECT country,COUNT(uname),SUM(age),AVG(age),MAX(age),MIN(age) FROM t_user GROUP BY country;
-- 查看每个国家的总人数,年龄总和,平均年龄,最高年龄,最低年龄,但是排除某个国家
SELECT country,COUNT(uname),SUM(age),AVG(age),MAX(age),MIN(age) FROM t_user WHERE country!='吴国' GROUP BY country;
-- 列出每个国家小于20岁的人
SELECT country,uname FROM t_user WHERE age<20 GROUP BY country;
SELECT 列名 FROM 表名 WHERE 过滤条件
-- 使用where,可以用来过滤单行,如果想要过滤分组或者聚合之后的数据,要加having
-- 显示每个国家的平均年龄,但是仅显示那些总年龄超过100的国家
SELECT country,AVG(age) FROM t_user WHERE SUM(age)>100 GROUP BY country;
-- 上面的写法报错,where在聚合前先筛选记录,但此时表中并没有sum(age)这条记录
-- having在聚合后对组记录进行筛选
SELECT country,AVG(age) FROM t_user GROUP BY country HAVING SUM(age)>100;
-- 注意顺序:having放在分组之后,因为作用的对象不同。WHERE 子句作用于表和视图,HAVING 子句作用于组
having 和 where
WHERE 在分组和聚合计算之前进行选取(它控制哪些行进入聚合计算),因此,WHERE 子句不能包含聚合函数
HAVING 在分组和聚合之后选取分组的行
而且HAVING 子句总是包含聚集函数
(严格来讲,你可以写不使用聚集的 HAVING 子句, 但同样的条件用WHERE更有效)
综上所述:
having要跟在group by之后,对分组查询的结果进行过滤(过滤分组)
where要出现在group by之前,执行表中所有数据来进行过滤(过滤行)
另外,having可以用聚合函数,并支持所有where子句操作符
where子句操作符
-- <,>,=,!=,>=,<=,and,not,or,like
-- 其中 <,>,=,!=,>=,<=属于比较运算符
-- and,not,or属于逻辑运算符
SELECT uname FROM t_user WHERE age>10 AND age<30;
-- where子句操作符:
-- between操作符稍显特殊,它需要两个操作符
SELECT * FROM book WHERE number BETWEEN 2 AND 4
-- 在使用BETWEEN时,必须指定两个值来限定范围,这两个值必须用AND关键字分隔。 BETWEEN匹配范围中所有的值,包括指定的开始值和结束值
-- 空值检查
SELECT * FROM book WHERE number IS NOT NULL
-- 上述语句返回number不为空的行IS NULL 空值判断
-- IN操作符:用来指定条件范围,范围中的每个条件都可以进行匹配。 IN取合法值的由逗号分隔的清单,全都括在圆括号中。
SELECT * FROM book WHERE number IN (2,4)
-- IN操作符有两个优点:
-- 第一:在使用长的合法选项清单时, IN操作符的语法更清楚且更直观。如WHERE number IN (1,3,5,7,9)。
-- 第二:IN是可以包含其他SELECT语句,使得能够更动态地建立WHERE子句
-- NOT操作符:只有一个功能,那就是否定它之后所跟的任何条件:
WHERE number NOT IN (1,3,5,7,9)SELECT * FROM book WHERE number NOT BETWEEN 2 AND 4
-- 复杂的子句中, NOT非常有用。例如,在与IN操作符联合使用时, NOT使找出与条件列表不匹配的行非常简单。MySQL支持使用NOT对IN 、BETWEEN、like等子句取反。
表的约束
表的约束:保证数据的完整新和安全性
例如id必须有值或填写性别时只能是男或女,不能写入其他数据
主键约束(primary key):要求主键列数据唯一,并且不能为空
唯一约束(unique):要求该列唯一,允许为空
非空约束(not null):某类内容不能为空
外键约束(foreign key):用于两表间建立关系
主键约束
主键约束是数据库中最重要的一种约束
在关系中,主键值不能为空,也不允许出现重复(非空且唯一)
一个表中只允许一个主键
主键是表中能够唯一确定一个行数据的字段
CREATE TABLE t_user(id INT NOT NULL,PRIMARY KEY (id));
-- 默认值(default XXX):设置一个默认值
主键字段可以是单字段或多字段的组合
创建一个新表
主键字段可以是单字段或多字段的组合
上面的例子中:first_name,last_name都有可能重复,但多列组合是唯一的,但是每一个单独的列依然可以有重复的值
当一个列不足以用来表示一条记录的唯一性的时候,就需要设置多个列为复合主键,来标识一条记录的唯一性
一般情况下,主键的字段长度和字段数目要越少越好
SQL语句:
CREATE TABLE t_user(first_name VARCHAR(32) NOT NULL,last_name VARCHAR(32) NOT NULL,PRIMARY KEY(first_name,last_name));
唯一性约束
唯一性约束:要求该列数据唯一(确保不出现重复),允许为空
CREATE TABLE t_user(id INT PRIMARY KEY AUTO_INCREMENT, -- 自增必须是唯一非空数字
uname VARCHAR(32) UNIQUE);
-- 或者
CREATE TABLE t_user(id INT PRIMARY KEY AUTO_INCREMENT,uname VARCHAR(32),UNIQUE KEY(uname));
外键
外键:用来和其他表建立联系
关系型数据库中的一个表中有若干个属性(列),若其中某一个属性组能唯一标识一条记录,该属性组就可以成为一个主键 比如 学生表(学号,姓名,性别,班级) 其中每个学生的学号是唯一的,学号就是一个主键 课程表(课程编号,课程名,学分) 其中课程编号是唯一的,课程编号就是一个主键 成绩表(学号,课程编号,成绩,班级) 成绩表中单一一个属性无法唯一标识一条记录,学号和课程号的组合才可以唯一标识一条记录,所以 学号和课程号的属性组是一个主键
成绩表中的学号不是成绩表的主键,但它和学生表中的学号相对应,并且学生表中的学号是学生表的主键,则可以设置成绩表中的学号是学生表的外键同理 成绩表中的课程号是课程表的外键
外键具有保持数据完整性和一致性的机制,目前MySQL只在InnoDB引擎下支持
(ENGINE=INNODB)
外键是表中的一个列,其值必须在另一个表的主键或者唯一键中列出
作为主键的表称为 主表,作为外键的表称为 依赖表
外键会参照主表的主键或唯一键
外键约束:
-- 学生表
CREATE TABLE t_student(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,sname VARCHAR(25),sex VARCHAR(10));
INSERT INTO t_student VALUES (1,"小明","男"),(2,"小红","女");
-- 班级表
CREATE TABLE t_class(cname VARCHAR(25),cid INT,FOREIGN KEY(cid) REFERENCES t_student(id));
-- 此时再右键点击打开表,设置cid时只能从id中包含的数据中选择
外键的作用有两点:
1.对子表(外键所在的表)的作用:子表在进行写操作的时候,如果外键字段在父表中找不到对应的匹配,操作就会失败
2.对父表的作用:对父表的主键字段进行删和改时,如果对应的主键在子表中被引用,操作就会失败
以下情况创建外键会失败:
外键的引用类型不一样,如主键是int外键是char
找不到主表中引用的列
主键和外键的字符编码不一样
存储引擎
存储引擎:存储数据的方式
数据库存储引擎是数据库底层软件组件,数据库管理系统使用数据引擎进行创建、查询、更新和删除数据操作
使用不同的存储引擎还可以获得特定的功能
InnoDB存储引擎提供了具有提交、回滚和崩溃恢复能力的事务安全,支持外键。但是比起Myisam存储引擎,InnoDB写的处理效率差一些并且会占用更多的磁盘空间。MySQL 5.5.5 之后,InnoDB 作为默认存储引擎
Myisam表不支持事务、也不支持外键,但访问速度快,对事务没有要求
建表的时候可以指定引擎
create table t_p(...) engine = myisam;
alter table t_p engine = innodb;
了解内容:查询当前数据库支持的搜索引擎 show engines
5.0版本之前用type,之后用engine
索引和视图
索引
索引:当数据库中存在很多条记录,例如几十万条,查询速度就成了一个问题
此时可以建立类似目录的数据库对象,实现快速查询,这就是索引
例如在书中查询某个内容时,先在目录中查询,然后根据目录所示的页码找到查询内容,大大缩短了查询时间
索引的作用:索引用于快速找出在某个列中有一特定值的行,不使用索引,MySQL必须从第一条记录开始读完整个表,直到找出相关的行,表越大,查询数据所花费的时间就越多,如果表中查询的列有一个索引,MySQL能够快速到达一个位置去搜索数据文件,而不必查看所有数据,那么将会节省很大一部分时间
-- 建立一个索引:
-- 1,创建表时,主键会默认带有索引
-- 2,创建一个索引
CREATE INDEX index_1 ON t_user(uname)
-- 创建一个索引 索引名 从 表名 在哪个字段
CREATE TABLE mytable( -- 创建表时直接指定
ID INT NOT NULL,
username VARCHAR(16) NOT NULL,
INDEX index_1 (username)
);
-- 3,删除索引
DROP INDEX index_1 ON t_user
优点:
所有的MySql列类型(字段类型)都可以被索引,也就是可以给任意字段设置索引
大大加快数据的查询速度
缺点:
1、创建索引和维护索引要耗费时间,并且随着数据量的增加所耗费的时间也会增加
2、索引也需要占空间,如果我们有大量的索引,索引文件可能会占很多空间
3、当对表中的数据进行增加、删除、修改时,索引也需要动态的维护,降低了数据的维护速度。
使用原则:
并不是每个字段都设置索引就好,也不是索引越多越好,而是需要自己合理的使用
1、对经常更新的表就避免对其进行索引,对经常用于查询的字段应该创建索引
2、数据量小的表最好不要使用索引,因为由于数据较少,可能查询全部数据花费的时间比遍历索引的时间还要短,索引就可能不会产生优化效果
3、在不同值少的列上(字段上)不要建立索引,比如在"性别"字段上只有男,女两个不同值
相反的,在一个字段上不同值较多时(唯一性较好)建立索引
视图
视图:就是一条SELECT语句执行后返回的结果集(显示结果是一个表)
例如之前的分组查询语句:
-- 查看每个国家的总人数,年龄总和,平均年龄,最高年龄,最低年龄
SELECT country,COUNT(uname),SUM(age),AVG(age),MAX(age),MIN(age) FROM t_user GROUP BY country;
-- 为上面的语句创建视图:
CREATE VIEW v_user AS SELECT country,COUNT(uname),SUM(age),AVG(age),MAX(age),MIN(age) FROM t_user GROUP BY country;
SELECT * FROM v_user;
-- 以后在使用上面的查询语句时只需要使用视图名
在创建一个视图时,只存放视图的定义,也就是动态检索数据的查询语句,并不存放视图对应的数据,在用户使用视图时才去求相对应的数据,所以视图称为''虚表''
视图的作用:专门进行某些查询
方便操作:减少复杂的SQL语句,增强可读性
更加安全:在外界访问你的数据库时,经常不想让他访问所有数据这时候可以建立视图,在视图中写好查询语句,同时限制外界的访问权限只能通过你给定的视图去查询
删除视图:
DROP VIEW v_user;