# 这是单行注释
-- 这是单行注释
/*
这是多行注释
*/
注意我们建立数据库或者表时,数据库一般以db_开头,数据表一般以tb_开头,算是一种命名风格,不过不同公司规范不一样,我说的这个只是一种命名规范。
CREATE DATABASE db_my;
-- 展示有多少个数据库
show databases;
CREATE TABLE tb_person
(
person_id int primarykey auto_increment not null comment '用户id',
lastaname varchar(255) comment '姓,英文中姓名倒置',
firstname varchar(255) comment '名,英文中姓名倒置',
address varchar(255) comment '用户住址,会尽可能精确到省市区县乡村组级别',
province varchar(255) comment '所在省',
city varchar(255) comment '所在城市'
)charset=utf8;
-- 展示数据库表信息
show tables;
-- 显示数据库表结构信息
desc tb_person;
/*
所有字段数据插入,字段顺序和插入数据类型必须和数据库表定义时一样
person_id int ,
lastaname varchar(255) ,
firstname varchar(255) ,
address varchar(255) ,
province varchar(255) ,
city varchar(255)
*/
INSERT INTO tb_person
VALUES (2, 'shen', 'lei', 'hunanshengchangshashiyueluqu','hunan', 'changsha');
# 插入多条数据
INSERT INTO tb_person
VALUES (3, 'bing', 'shao', 'hubeiwuhanhanyi','hubei', 'wuhan'), (4, 'zi', 'jiao', 'henanzhengzhouyixu','henan', 'zhengzhou');
-- 注意看,这时候字段顺序可以做调换,只要按照字段顺序进行值的插入即可
INSERT INTO tb_person (city,province,person_id)
VALUES ('guangzhou','guangdong', 5);
# 这里,SELECT uid FROM tb_user WHERE id=1是一个数据集合,插入到tb_collect表中,插入时需要更新的字段是uid这个字段,当然可以是多个字段。
INSERT INTO tb_collect(uid)
SELECT uid FROM tb_user
WHERE id=1;
SELECT person_id,city
FROM tb_person;
SELECT * FROM table_name;
SELECT DISTINCT city
FROM tb_person;
SELECT * FROM tb_person WHERE city='changsha';
SELECT * FROM tb_person
WHERE city='changsha'
AND person_id > 50;
SELECT * FROM tb_person
WHERE city='changsha'
OR province='hubei';
-- 注意字符串也是可以排序的,ASC就是ascending,DESC就是descending,不过默认就是asc升序,所以升序时可以省略ASC
SELECT * FROM tb_person
ORDER BY firstname ASC;
SELECT * FROM tb_person
ORDER BY person_id DESC;
SELECT *
FROM tb_person
LIMIT 3;
# 查询数据库中city字段中,以字母c开头的所有数据并返回;%代表匹配0个或者多个字母
SELECT * FROM tb_person
WHERE city LIKE 'c%';
-- 查询所有数据中,字段province以字母i结尾的所有数据,并返回
SELECT * FROM tb_person
WHERE province LIKE '%i';
-- 查询所有数据中,字段address中包含changsha的数据,并返回
SELECT * FROM tb_person
WHERE address LIKE '%changsha%';
-- 下划线_ 就是匹配一个字母,这里就是查找数据库中,字段address以某个字母开头,但后面内容是unanshengchangshashiyueluqu的数据,并返回
SELECT * FROM tb_person
WHERE address LIKE '_unanshengchangshashiyueluqu';
/* regexp就是regex expression正则表达式的意思,可以在其中插入正则表达式进行处理
这里的意思就是以^就是开头,[GFS]就是以这个中括号中字母的任意一个,合并起来就是以GFS中任意一个字母开头的值。数据库中firstname中,以GFS中任意一个字母开头的数据
*/
SELECT * FROM tb_person
WHERE firstname REGEXP '^[GFS]';
-- 检索数据库中每一条数据,对比字段lastname在('zhao','qian', 'sun', 'li', 'zhou', 'wu', 'zheng', 'wang')中的数据,并返回
SELECT * FROM tb_person
WHERE lastname IN ('zhao','qian', 'sun', 'li', 'zhou', 'wu', 'zheng', 'wang');
# 检索数据库中每一条数据,字段person_id [1, 20],大于等于1,并且小于等于20
SELECT * FROM tb_person
WHERE person_id BETWEEN 1 AND 20;
注意使用update语句,一定一定记得加where约束,否则会导致表中所有数据被更新,这是一个有风险的操作,请一定注意。
-- 记得加where约束条件
UPDATE tb_person
SET city='shanghai', person_id=7
WHERE province='shanghai';
在公司开发中,数据删除分为物理删除和逻辑删除,逻辑删除就是给数据一个标记如deleted为true,但是数据本身不会被从数据库或者文件中删除;物理删除就是真正的把数据删除掉,一般物理删除操作需要比较谨慎处理,因为数据才是公司最大财富
# 根据约束条件进行删除,注意做约束条件处理,这也是一个危险操作
DELETE FROM tb_person
WHERE person_id=5;
LEFT JOIN、RIGHT JOIN、INNER JOIN、OUTER JOIN四大类,组合起来是大致7种场景。如果进行嵌套,则会有更复杂的情形。
数据库联结可以看作是数学里面的集合运算,交集、并集、差集以及它们的组合运用。
经典截图如下
数据准备,常见的电商场景,用户信息和用户收藏记录
-- 用户信息表
create table if not exists tb_user(
uid int primarykey auto_increment not null comment '用户的id,一般使用算法生成如雪花算法',
name varchar(255) comment '用户名字,全名',
address varchar(255) comment '用户地址',
birthday date comment '用户生日,一般精确到天即可,注意时区处理'
)charset=utf8;
-- 用户收藏商品表
create table if not exists tb_collect(
collect_id int primarykey auto_increment not null comment '收藏记录id,每条数据都有一个唯一id',
uid int not null comment '用户id',
item_name varchar(255) comment '收藏的商品名',
item_id varchar(255) comment '收藏商品id',
collect_time datetime comment '收藏时间'
)charset=utf8;
# 从表tb_user和tb_collect中,找到符合tb_user.uid=tb_collect.uid的数据,再从这个结果集合中,分别检索tb_user.name, tb_user.birthday和tb_collect.item_name, tb_collect.datetime的数据,再展示出来
SELECT tb_user.name, tb_user.birthday, tb_collect.item_name, tb_collect.datetime
FROM tb_user
INNER JOIN tb_collect
ON tb_user.uid=tb_collect.uid;
-- 将tb_user和tb_collect左联,tb_user为主。条件是tb_user.uid=tb_collect.uid。再从这个结果集中针对tb_user.name, tb_user.birthday以及 tb_collect.item_name, tb_collect.datetime做结果查询。
SELECT tb_user.name, tb_user.birthday, tb_collect.item_name, tb_collect.datetime
FROM tb_user
LEFT JOIN tb_collect
ON tb_user.uid=tb_collect.uid
ORDER BY tb_user.name DESC;
-- 将tb_user跟tb_collect右联,tb_collect为主。
SELECT tb_user.name, tb_user.birthday, tb_collect.item_name, tb_collect.datetime
FROM tb_user
RIGHT JOIN tb_collect
ON tb_user.uid=tb_collect.uid
ORDER BY tb_user.name DESC;
-- 这和会生成笛卡尔积,数据量会暴涨,所以对于笛卡尔积操作慎用,处分其中一个表较小,否则2个大表做笛卡尔积运算,内存可能溢出。
SELECT tb_user.name, tb_user.birthday, tb_collect.item_name, tb_collect.datetime
FROM tb_user
FULL JOIN tb_collect
ON tb_user.uid=tb_collect.uid
ORDER BY tb_user.uid DESC;
UNION 不能用于列出两个表中所有的uid。如果一些uid是同一个,每个uid只会列出一次。UNION 只会选取不同的值
-- 将2个select结果集合做合并,同时去掉重复的值
SELECT uid FROM tb_user
UNION
SELECT uid FROM tb_collect
ORDER BY uid;
# 将2个select的结果集合做合并,不管是否重复,都展示出来
SELECT uid FROM tb_user
UNION ALL
SELECT uid FROM tb_collect
ORDER BY uid;
这些是字段约束设置,可以通过 CREATE TABLE 语句定义,或者在表创建之后通过 ALTER TABLE 语句修改。
/*
NOT NULL 约束强制列不接受 NULL 值。
NOT NULL 约束强制字段始终包含值。这意味着,如果不向字段添加值,就无法插入新记录或者更新记录。
*/
-- 建表时设置约束
CREATE TABLE tb_computer(
id int NOT NULL comment '电脑的id',
brand varchar(255) NOT NULL comment '电脑品牌',
price decimal(10, 3) NOT NULL comment '电脑价格,使用decimal,不使用float和double',
color varchar(30) comment '颜色'
)charset=utf8;
-- 建表后设置约束
ALTER TABLE tb_computer
MODIFY color varchar(30) NOT NULL;
-- 建表后去除约束
ALTER TABLE tb_computer
MODIFY color varchar(30) NULL;
CREATE TABLE tb_mobilephone
(
phone_id int NOT NULL comment '电话id',
brand varchar(255) NOT NULL comment '品牌',
color varchar(255) comment '颜色',
price decimal(10, 2) comment '价格',
UNIQUE (phone_id )
)charset=utf8;
-- 建表后,给某个字段单独加约束
ALTER TABLE tb_mobilephone
ADD UNIQUE (phone_id )
-- 建表后,给多个字段一起加约束,还可以对这个约束命名
ALTER TABLE tb_mobilephone
ADD CONSTRAINT constraint_id_name UNIQUE (phone_id , brand )
-- 撤销约束
ALTER TABLE tb_mobilephone
DROP INDEX constraint_id_name
CREATE TABLE tb_cpu
(
cpu_id int NOT NULL comment 'cpu id',
brand varchar(255) NOT NULL comment '品牌',
model varchar(255) comment '型号',
gen int comment '第几代CPU',
price decimal(10, 2) comment '价格',
PRIMARY KEY (cpu_id )
)charset=utf8;
-- 添加主键,一般业务场景都不会随便修改主键。从流程上来说,数据库表前期建立就会遵循很严格的流程,保证字段数目,命名,主键等设置符合现在以及未来需求。而不是建立好之后修改主键,成本和代价是比较高的,一般不建议这么做。
ALTER TABLE tb_cpu
ADD PRIMARY KEY (cpu_id )
-- 撤销主键
ALTER TABLE tb_cpu
DROP PRIMARY KEY
注意,数据库是存储公司数据的仓库,是非常重要的资产。虽然mysql提供了很多功能,但一些危险性和敏感性操作,一般都不要去尝试,特别是在生产环境下。切记切记
CREATE TABLE tb_mouse
(
id int NOT NULL AUTO_INCREMENT comment '鼠标id',
color varchar(255) NOT NULL comment '颜色',
brand varchar(255) comment '品牌',
price decimal(10, 2) comment '价格',
model varchar(255) comment '型号',
PRIMARY KEY (ID)
)charset=utf8;
-- 让自增从100开始
ALTER TABLE tb_mouse AUTO_INCREMENT=100
默认地,AUTO_INCREMENT 的开始值是 1,每条新记录递增 1。SQL中数组等计数都是从1开始的,和生活中计数是一样的规则
CREATE TABLE tb_order
(
order_id int NOT NULL comment '订单id',
order_price decimal(10, 2) NOT NULL comment '订单价格',
uid int comment '用户id',
PRIMARY KEY (order_id) comment '设置主键',
FOREIGN KEY (uid) REFERENCES tb_user(uid) comment '设置外键'
)charset=utf8;
-- 表建立后,设置外键
ALTER TABLE tb_order
ADD FOREIGN KEY (uid)
REFERENCES tb_user(uid)
-- 表建立后,设置多个外键并给约束添加名字
ALTER TABLE tb_order
ADD CONSTRAINT constraint_order
FOREIGN KEY (uid)
REFERENCES tb_user(uid)
-- 表建立后,去除外键
ALTER TABLE tb_order
DROP FOREIGN KEY constraint_order
-- 检查cup_id必须大于0
CREATE TABLE tb_cup
(
cup_id int NOT NULL comment '杯子id',
brand varchar(255) NOT NULL comment '品牌',
color varchar(30) comment '颜色',
price decimal(10, 2) comment '价格',
CHECK (cup_id >0)
)charset=utf8;
-- 建表后,添加check约束
ALTER TABLE tb_cup
ADD CHECK (cup_id >0)
-- 建表后,添加check约束并命名
ALTER TABLE tb_cup
ADD CONSTRAINT check_cup CHECK (cup_id >0 AND color='black')
-- 建表后,删除约束
ALTER TABLE tb_cup
DROP CHECK check_cup
CREATE TABLE tb_shoes
(
shoes_id int NOT NULL comment '鞋子id',
brand varchar(255) NOT NULL comment '品牌',
color varchar(30) comment '颜色',
price decimal(10, 2) comment '价格',
size decimal(8, 2) DEFAULT 0,
stock int comment '库存数量'
)charset=utf8;
-- 建表后,添加默认值
ALTER TABLE tb_shoes
ALTER brand SET DEFAULT 'xiaomi'
-- 建表后,删除字段默认值
ALTER TABLE tb_shoes
ALTER brand DROP DEFAULT
CREATE INDEX 语句用于在表中创建索引。
==在不读取整个表的情况下,索引使数据库应用程序可以更快地查找数据。==在表中创建索引,以便更加快速高效地查询数据。无法看到索引,它们只能被用来加速搜索/查询。
==更新一个包含索引的表需要比更新一个没有索引的表花费更多的时间,这是由于索引本身也需要更新。==因此,理想的做法是仅仅在常常被搜索的列(以及表)上面创建索引。
-- 创建一个简单索引,允许重复的值
CREATE INDEX index_price
ON tb_shoes(price);
-- 建立多个字段的索引值
CREATE INDEX s_index
ON tb_shoes(brand , price );
-- 在表上创建一个唯一的索引。不允许使用重复的值:唯一的索引意味着两个行不能拥有相同的索引值. 所以一般是针对unique字段进行索引建立
CREATE UNIQUE INDEX index_id
ON tb_shoes(shoes_id );
-- mysql删除索引
ALTER TABLE table_name DROP INDEX index_name;
-- mysql 删除数据库表
DROP TABLE table_name;
-- mysql删除数据库
DROP DATABASE database_name;
-- 删除数据库表中数据, TRUNCATE TABLE 删除表中的所有行,但表结构及其列、约束、索引等保持不变。删除速度比delete更快
TRUNCATE TABLE table_name;
-- 删除数据库表中数据,delete操作会删除数据,但会保留表结构,并且在之后需要时可以回滚数据
DELETE TABLE table_name;
-- 向表中添加列
ALTER TABLE table_name
ADD column_name datatype;
-- 删除表中的列
ALTER TABLE table_name
DROP COLUMN column_name;
-- 改变表中字段类型
ALTER TABLE table_name
MODIFY COLUMN column_name datatype;
视图是基于 SQL 语句的结果集的可视化的表。可以理解为编程语言当中的集合变量,例如代码执行中使用arraylist来承载中间过程中产生的数据集合。
视图总是显示最新的数据!每当用户查询视图时,数据库引擎通过使用视图的 SQL 语句重建数据.如果接触过计算型变量如swift语言,就可以有比较深的感受
CREATE VIEW view_name AS
SELECT column_name1, column_name2, column_name3
FROM table_name
WHERE condition;
-- 建立视图
CREATE VIEW [High Price Shoes] AS
SELECT price, color
FROM tb_shoes
WHERE price > 200;
-- 查询视图中数据
SELECT * FROM [High Price Shoes];
CREATE OR REPLACE VIEW view_name AS
SELECT column_name1, column_name2, column_name3
FROM table_name
WHERE condition;
-- 像视图中添加一列内容数据
CREATE VIEW [High Price Shoes] AS
SELECT price, color, brand
FROM tb_shoes
WHERE price > 200;
DROP VIEW view_name;
-- 注意看这里,AS之前是原始的字段或者值,as之后就是别名。 很多时候也有省略的写法,但这样会带来困扰,建议还是加上as会让sql语句可读性高很多
SELECT firstname AS fn, city AS c
FROM tb_person;
-- 数据库表名也可以起别名,针对嵌套的sql语句,某个查询结果集也是可以起别名的
SELECT city
FROM tb_person AS person;
sql自带的日期函数,可以返回日期相关的值
- NOW() 返回当前的日期和时间
- CURDATE() 返回当前的日期
- CURTIME() 返回当前的时间
- DATE() 提取日期或日期/时间表达式的日期部分
- EXTRACT() 返回日期/时间的单独部分
- DATE_ADD() 向日期添加指定的时间间隔
- DATE_SUB() 从日期减去指定的时间间隔
- DATEDIFF() 返回两个日期之间的天数
- DATE_FORMAT() 用不同的格式显示日期/时间
MySQL中日期数据类型
DATE - 格式:YYYY-MM-DD
DATETIME - 格式:YYYY-MM-DD HH:MM:SS
TIMESTAMP - 格式:YYYY-MM-DD HH:MM:SS
YEAR - 格式:YYYY 或 YY
-- 不涉及时分秒具体时间的日期比较其实很简单
SELECT * FROM tb_order WHERE datetime='20018-12-1'
-- 在where条件中判断值是否为null
SELECT price, brand, FROM tb_shoes
WHERE brand IS NULL;
-- 在where条件中判断值是否不是null
SELECT price, brand, FROM tb_shoes
WHERE brand IS NOT NULL;
函数可以大致分为2类,SQL Aggregate 函数(计算从列中取得的值,返回一个单一的值)SQL Scalar 函数(基于输入值,返回一个单一的值)。
SQL Aggregate 函数
- AVG() - 返回平均值
- COUNT() - 返回行数
- FIRST() - 返回第一个记录的值
- LAST() - 返回最后一个记录的值
- MAX() - 返回最大值
- MIN() - 返回最小值
- SUM() - 返回总和
SELECT AVG(column_name) FROM table_name;
-- 获取所有鞋子录入到数据库中所有价格的平均数
SELECT AVG(price) FROM tb_shoes;
SELECT COUNT(column_name) FROM table_name;
-- 返回数据库中所有记录的条数
SELECT COUNT(*) FROM table_name;
-- 返回指定列不同值的条数,DISTINCT 去重
SELECT COUNT(DISTINCT column_name) FROM table_name;
-- mysql中,使用以下方式可以获取first()函数一样的效果,虽然Mysql本身不支持这个first()函数
SELECT column_name FROM table_name
ORDER BY column_name ASC
LIMIT 1;
-- 最后一条的化,直接倒序排列,再取第一条也是一样的效果。mysql不支持这个函数
SELECT column_name FROM table_name
ORDER BY column_name DESC
LIMIT 1;
SELECT MAX(column_name) FROM table_name;
SELECT MIN(column_name) FROM table_name;
SELECT SUM(column_name) FROM table_name;
-- 物以群分,根据某个字段对数据做分类
SELECT brand, price
FROM tb_shoes
WHERE color = 'black'
GROUP BY brand;
SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name
HAVING aggregate_function(column_name) operator value;
SELECT column_name(s)
FROM table_name
WHERE EXISTS
(SELECT column_name FROM table_name WHERE condition);
-- 检索数据库中的鞋子数量乘以单价得到总价,品牌
SELECT brand, price * IFNULL(stock, 0)
FROM tb_shoes;
SQL Scalar 函数
- UCASE() - 将某个字段转换为大写
- LCASE() - 将某个字段转换为小写
- MID() - 从某个文本字段提取字符,MySql 中使用
- SubString(字段,1,end) - 从某个文本字段提取字符
- LEN() - 返回某个文本字段的长度
- ROUND() - 对某个数值字段进行指定小数位数的四舍五入
- NOW() - 返回当前的系统日期和时间
- FORMAT() - 格式化某个字段的显示方式
SELECT UCASE(column_name) FROM table_name;
SELECT LCASE(column_name) FROM table_name;
-- 从brand字段中提取前四个字符,就是1--4且包含,注意sql计数从1开始
SELECT MID(brand,1,4) AS short_brand
FROM tb_shoes;
SELECT LENGTH(column_name) FROM table_name;
SELECT ROUND(column_name,decimals) FROM table_name;
SELECT NOW() FROM table_name;
SELECT FORMAT(column_name,format) FROM table_name;