COLLATE utf8_general_ci
mysql 的排序规则,ci Case Insensitive的缩写,即是大小写无关,不区分大小写MySQL、SQLServer、SQLite、ORACLE、MariaDB...
关系型数据库最典型的数据结构是表,由二维表及其之间的联系所组成的一个数据组织
优点:
缺点:
redis、mongoDB、Neo4j...
非关系型数据库严格来说不是一种数据库,应该是一种结构化存储方法集合,可以是文档或者键值对等
优点:
缺点;
名称 | 解释 | 命令 |
---|---|---|
DDL (数据定义语言) | 定义和管理数据对象, 如数据库,数据表等 | CREATE、DROP、ALTER |
DML (数据操作语言) | 用于操作数据库对象中所包含的数据 | INSERT、UPDATE、DELETE |
DQL (数据查询语言) | 用于查询数据库数据 | SELECT |
DCL (数据控制语言) | 用来管理数据库的语言,包括管理权限及数据更改 | GRANT、COMMIT、ROLLBACK |
名称 | MyISAM | InnoDB |
---|---|---|
事务处理 | 不支持 | 支持 |
数据行锁定 | 不支持 | 支持 |
外键约束 | 不支持 | 支持 |
全文索引 | 支持 | 不支持 |
表空间大小 | 较小 | 较大,约2倍 |
> net start user_name; #启动数据库 > net stop user_name; #关闭数据库 > mysql -u[user_name] -p[password] #命令行运行数据库 CREATE DATABASE if not exists database_name DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci # 创建数据库并规定字符集 SELECT user FROM mysql.user; # 查看数据库所有用户 show databases; #查看所有的数据库 use database_name #进入数据库 show tables # 查看当前数据库里的所有表 desc table_name; #查看表结构,等价于describe table_name; show full columns from table_name; #查看当前表的所有列信息 show create table table_name; #显示表创建语句
若不设置条件限制则会影响额外数据
数值类型的值才能做运算
相同数据类型的值才能作比较
运算符 | 含义 | 范例 | 结果 |
---|---|---|---|
= | 等于 | 5=6 | false |
<> 或 != | 不等于 | 5!=6 | true |
> | 大于 | 5>6 | false |
< | 小于 | 5<6 | true |
>= | 大于等于 | 5>=6 | false |
<= | 小于等于 | 5<=6 | true |
BETWEEN | 在某个范围之间 | BETWEEN 5 AND 10 | - |
AND | 并且 | 5>1 AND 1>2 | false |
OR | 或 | 5>1 OR 1>2 | true |
操作符名称 | 语法 | 描述 |
---|---|---|
AND或&& | a AND b 或 a && b | 逻辑与,同时为真,结果才为真 |
OR或|| | a OR b 或 a||b | 逻辑或,只要一个为真,则结果为真 |
NOT或! | NOT a 或 !a | 逻辑非,若操作数为假,结果则为真 |
操作符名称 | 语法 | 描述 |
---|---|---|
IS NULL | a IS NULL | 若操作符为NULL,则结果为真 |
IS NOT NULL | a IS NOT NULL | 若操作符不为NULL,则结果为真 |
BETWEEN | a BETWEEN b AND c | 若a范围在b与c之间则结果为真 |
LIKE | a LIKE b | SQL模式匹配,若a匹配b,则结果为真 |
IN | a IN (a1,a2,a3,….) | 若a等于a1,a2…中的某一个,则结果为真 |
TIMESTAMP DEFAULT CURRENT_TIMESTAMP
数据类型为 timestamp 默认值为 current_timestamp 是字段默认获取当前系统时间插入CREATE TABLE [ IF NOT EXISTS ] `表名` ( # ``反引号用于引入关键字 `字段名1` 列类型 [ 属性 ] [ 索引 ] [注释] , `字段名2` 列类型 [ 属性 ] [ 索引 ] [注释] , … … `字段名n` 列类型 [ 属性 ] [ 索引 ] [注释] ) [ 表类型 ] [ 表字符集 ] [注释] ;
规定数据库中该列存放的数据类型
其中分为以下几种类型:
类型 | 说明 | 取值范围 | 存储需求 |
---|---|---|---|
tinyint | 非常小的数据 | 有符值: -27 ~ 27-1 无符号值:0 ~ 28-1 | 1字节 |
smallint | 较小的数据 | 有符值: -215 ~ 215-1 无符号值: 0 ~ 216-1 | 2字节 |
mediumint | 中等大小的数据 | 有符值: -223 ~ 223-1 无符号值: 0 ~ 224-1 | 3字节 |
int | 标准整数 | 有符值: -231 ~ 231-1 无符号值:0 ~ 232-1 | 4字节 |
bigint | 较大的整数 | 有符值: -263 ~263-1 无符号值:0 ~264-1 | 8字节 |
float | 单精度浮点数 | ±1.1754351e -38 | 4字节 |
double | 双精度浮点数 | ±2.2250738585072014e -308 | 8字节 |
decimal | 字符串形式的浮点数 | decimal(m, d) | m个字节 |
类型 | 说明 | 最大长度 |
---|---|---|
char[(M)] | 固定长字符串,检索快但费空间, 0 <= M <= 255 | M字符 |
varchar[(M)] | 可变字符串 0 <= M <= 65535 | 变长度 |
tinytext | 微型文本串 | 28–1字节 |
text | 文本串 | 216–1字节 |
类型 | 说明 | 取值范围 |
---|---|---|
DATE | YYYY-MM-DD,日期格式 | 1000-01-01~ 9999-12-31 |
TIME | Hh:mm:ss ,时间格式 | -838:59:59~838:59:59 |
DATETIME | YY-MM-DD hh:mm:ss | 1000-01-01 00:00:00 至 9999-12-31 23:59:59 |
TIMESTAMP | YYYYMMDDhhmmss 格式表示的时间戳 | 197010101000000 ~2037年的某个时刻 |
YEAR | YYYY 格式的年份值 | 1901~2155 |
int(3)
值为5时,插入表内为 005NULL 和 NOT NULL
表类型设置CREATE TABLE 表名(省略一些代码) ENGINE = InnoDB;
常见表类型:MyISAM、InnoDB 、HEAP、BOB、CSV等
使用MyISAM: 节约空间及相应速度
使用InnoDB: 安全性,事务处理及多用户操作数据表
InnoDB类型数据表只有一个*.frm文件,数据文件为上一级目录的 ibdata1 文件
MyISAM类型数据表对应三个文件:
*.frm -- 表结构定义文件
*.MYD -- 数据文件
*.MYI -- 索引文件
CHARSET= utf8;
CREATE TABLE student_demo AS SELECT * FROM student
复制 student 表数据到 student_demo 表,只会复制数据,不会带主键以及自动增长等属性
# 修改表名 ALTER TABLE demo2 RENAME AS demo3; # 修改字段 ALTER TABLE demo3 CHANGE NAME username VARCHAR(32) NOT NULL; # 添加字段 ALTER TABLE demo3 ADD PASSWORD VARCHAR(32) NOT NULL; # 删除字段 ALTER TABLE demo3 DROP PASSWORD;
INSERT INTO 表名 [ ( 字段1, 字段2, 字段3, … ) ] VALUES ( '值1', '值2', '值3', …)
INSERT INTO 表名 SET 字段名1=值1[,字段名2=值2,…]
插入母表数据同时插入子表
通过 LAST_INSERT_ID()
函数来获取前面一次插入数据的 id 来作为子表的 id 插入
-- 案例 INSERT INTO orders (customer_id, order_date, status) VALUES (1, '2019-01-01', 1); INSERT INTO order_items VALUES(LAST_INSERT_ID(), 1, 1, 2.95);
从其他表查询数据插入到目标表
INSERT INTO order_demo SELECT * FROM orders WHERE order_date < '2021-01-01'
DELETE FROM 表名 [ WHERE condition ];
delete 只是在数据文件中吧删除字段进行标记
truncate 在物理文件上操作,彻底删除
TRUNCATE [TABLE] table_name
# 删除数据表;if exists为可选,会判断是否存在该表,如不存在则抛出错误 DROP TABLE [ IF EXISTS ] 表名
UPDATE 表名 SET column_name = value [ , column_name2 = value2, …. ] [ WHERE condition ];
使用 case 语法,对符合要求的 id 数量进行运算
UPDATE batch_update SET amount = CASE id WHEN 1 THEN amount + 10 WHEN 3 THEN amount + 20 END WHERE id in (1, 3);
查询合并行并求对应值
SELECT moneyType AS '操作裂类型', SUM(transactionBalance) AS '总金额' FROM transtable GROUP BY moneyType;
跨数据库查询
SELECT id, name FROM school.student
只需要在表名前加上 '数据库名.' 即可切换到对应数据库
SELECT [ALL | DISTINCT] { * | table.* | [ table.field1 [ as alias1] [, table.field2 [as alias2]][, …]] } FROM table_name [ as table_ alias ] [ left|out|inner join table_name2 ] #联合查询 [ WHERE … ] #指定结果需满足的条件 [ GROUP BY …] #指定结果按照哪几个字段来分组 [ HAVING …] #过滤分组的记录必须满足的次要条件 [ ORDER BY… ] #指定查询记录按一个或者多个条件排序 [ LIMIT { [ offset,] row_count | row_count OFFSET offset }] ; #指定查询的记录从哪条至哪条
select * from table_name;
此方法效率低,不推荐select studentName, studentNo from student;
只查询表中对应列的数据select student.studentNo, from student;
使用 表名.列名
来指定select studentNo as '学号' from student;
select s.studentNo from student as s;
select num + 1 AS nums from student;
select name '名字' from student;
select distinct 字段名1, 字段名2... FROM 表名
-- 取出所以满足条件的值逐个进行比较 SELECT invoice_total FROM invoices WHERE invoice_total > ALL( SELECT invoice_total FROM invoices WHERE client_id = 3 ) -- 等价于 -- 取出最大值,直接比较 SELECT invoice_total FROM invoices WHERE invoice_total > ( SELECT MAX(invoice_total) FROM invoices WHERE client_id = 3 )
= ANY
判断子查询条件是否满足查询要求
可以使用 NOT EXTST 来判断不存在
-- 查询发票表里面所有的用户 -- exists 接收到的是布尔值 SELECT * FROM clients c WHERE EXISTS( SELECT client_id FROM invoices WHERE c.client_id = client_id ) -- 等价于 -- IN 接受到的是一个结果集 SELECT * FROM clients WHERE client_id IN( SELECT DISTINCT client_id FROM invoices ) -- 等价于 SELECT DISTINCT c.* FROM invoices LEFT JOIN clients c USING(client_id)
SELECT id, name, if(is_spices = 0, '否', '是') is_spices FROM tb_material_type
SELECT 字段列1,字段2 ,…FROM 表名 WHERE 字段x BETWEEN 值1 AND 值2
WHERE name REGEXP 'a'
表示名字中包含 ‘a' 的人;等同于 ’%a%‘WHERE name REGEXP '^a'
使用 ^ 符号开头,表示名字必须以 ’a‘ 开头,等价于 'a%'WHERE name REGEXP 'a$'
等价于 '%a'WHERE name REGEXP 'a|b'
'|' 符号有 or 的作用,表示名字中含有 'a' 或者 'b' 的用户
WHERE name REGEXP '[abc]o'
表示名字中含有 'ao' or 'bo' or 'co' 的用户;[]
也可以写后面,查询结果顺序同理
-
代表一个范围[][]a
前面使用多个小括号,可以匹配多位SELECT 字段列1,字段2 ,…FROM 表名 WHERE 字段x IN ( 值1,值2,值3…)
SELECT CONCAT("姓名:", StudentName) AS 新姓名 FROM student; # 去重复 distinct SELECT DISTINCT StudentNo FROM result; SELECT * FROM subject WHERE subjectname LIKE "%数学%"; # 下划线占位,后面必须有两个的才能被查出来 SELECT studentno, studentname FROM student WHERE studentname LIKE "李__"; SELECT * FROM subject WHERE classhour = 100 OR classhour = 110 OR classhour = 120; # 使用in查询方式,更为简洁效率也更高 SELECT * FROM subject WHERE classhour IN (100, 110, 120); SELECT * FROM subject where ClassHour = 100 OR ClassHour =110 OR ClassHour = 120; #普通处理方式 SELECT * FROM subject where ClassHour IN ( 100, 110,120 ); #使用IN进行查询方式,更为简洁,效率更高
合并多个查询结果
union 前面的查询语句决定列名的呈现
SELECT order_id, order_date, 'active' status FROM orders WHERE order_date >= '2019-01-01' UNION SELECT order_id, order_date, 'archived' status FROM orders WHERE order_date < '2019-01-01'
[inner/outter] JOIN ON
如果连接两个表的列名一致可以使用 using (column_name)
来替代 on cloumn_name = column_name
using (cloumn_name, clounmn_name)
来简化代码SELECT 字段1,字段2,… FROM table_1 INNER JOIN table_2 ON table_1.字段x = table_2.字段y; # INNER JOIN 与 JOIN 是相同的; # 如table_1中的行在table_2中没有匹配,则不返回; #要求:从subject和grade数据表查询课程名称和所属年级名称 SELECT SubjectName,GradeName FROM subject INNER JOIN grade ON subject.GradeID= grade.GradeID;
#要求:从subject和grade数据表查询课程名称和所属年级名称 #非等值连接查询 (返回记录为两表记录数的乘积) SELECT SubjectName, GradeName FROM subject, grade; #等值查询 (等效于内连接) SELECT SubjectName, GradeName FROM subject, grade WHERE subject.GradeID = grade.GradeID;
SELECT * FROM sql_hr.employees e JOIN sql_hr.employees m ON e.reports_to = m.employee_id
SELECT 字段1,字段2,… FROM table_1 LEFT [ OUTER ] JOIN table_2 ON table_1.字段x = table_2.字段y;
SELECT 字段1,字段2,… FROM table_1 RIGHT [ OUTER ] JOIN table_2 ON table_1.字段x = table_2.字段y;
操作符名称 | 描述 |
---|---|
INNER JOIN ( JOIN ) | 如果表中有至少一个匹配,则返回行 |
LEFT JOIN | 不论右表是否有匹配,都会返回左表的所有行 |
RIGHT JOIN | 不论左表是否有匹配,都会返回右表的所有行 |
SELECT c1.categoryName AS "父栏目名称",c2.categoryName AS "子栏目名称" FROM category AS c1,category AS c2 WHERE c1.categoryId = c2.pid; SELECT c1.categoryName AS "父栏目名称",c2.categoryName AS "子栏目名称" FROM category AS c1 LEFT JOIN category AS c2 ON c1.categoryId = c2.pid WHERE c1.pid = 1;
嵌套查询即是由多个子查询组成的,求解方式是由内向外执行
相关子查询(普通子查询子查询代码只会执行一次)
主查询和子查询使用了同一张表,给主查询赋别名与子查询对应列进行关联
相关子查询内存占用高,但是实际使用情况较多
不能使用 ANY
关键字来替代相关子查询的部分操作
SELECT * FROM employees e WHERE salary > ( SELECT AVG(salary) FROM employees WHERE office_id = e.office_id ) -- 不等价, > any 会逐个比较,不是比较互相对应的 SELECT * FROM employees e WHERE salary > ANY ( SELECT AVG(salary) FROM employees GROUP BY office_id )
在选择语句中使用子查询(子查询可以直接调用新定义的列)
SELECT invoice_id, invoice_total, (SELECT AVG(invoice_total) FROM invoices) AS invoice_average, invoice_total - (SELECT invoice_average) AS difference -- 不能直接减别名,使用 SELECT 查询 FROM invoices;
-- demo SELECT c.client_id, c.name, SUM(i.invoice_total) AS total_sales, (SELECT AVG(invoice_total) FROM invoices) AS invoice_average, SUM(i.invoice_total) - (SELECT invoice_average) AS difference FROM clients c LEFT JOIN invoices i USING(client_id) GROUP BY c.client_id -- 等价于 SELECT c.client_id, c.name, (SELECT SUM(invoice_total) FROM invoices i WHERE client_id = c.client_id) AS total_sales, (SELECT AVG(invoice_total) FROM invoices i) AS average, (SELECT total_sales - average) AS difference FROM clients c
在 from 中也可以使用子查询;需要给 from 语句设置一个别名,否则会报错
在 from子句使用子查询仅限于简单查询
SELECT * FROM( SELECT c.client_id, c.name, (SELECT SUM(invoice_total) FROM invoices i WHERE client_id = c.client_id) AS total_sales, (SELECT AVG(invoice_total) FROM invoices i) AS average, (SELECT total_sales - average) AS difference FROM clients c ) AS sales_summary WHERE total_sales IS NOT NULL
order by 是放在语句的最后
与 select 语句查询得到结果,按照指定字段进行排序
与 DESC(降序) 或 ASC 搭配使用,默认为 ASC
order by colum_name1, column_namw2
可以接多个列名,逐个排序
select id, name from student order by 1, 2
这里的1,2指的是 id, name
select * from student limit 5;
返回前5条数据select * from student limit 5, 10;
返回 6-15条数据GROUP BY date, payment_method
直接在后面写多个,用逗号隔开# 分组查询,having作为条件限制,group进行分组 SELECT s.subjectName AS "课程名", MAX(studentResult) AS "最高分", MIN(studentResult) AS "最低分", AVG(studentResult) AS "平均分", SUM(studentResult) AS "分数和", COUNT(1) AS "人数" FROM result AS r LEFT JOIN subject AS s ON s.subjectNo = r.subjectNo GROUP BY r.subjectNo HAVING AVG(studentResult) >= 60;
函数名称 | 描述 |
---|---|
COUNT( ) | 返回满足SELECT条件的记录总和数,COUNT()只会返回非空的数据列,如果要返回所有的数据列可以使用count(*) |
SUM( ) | 返回数字字段或表达式列作统计,返回一列的总和 |
AVG( ) | 通常为数值字段或表达列作统计,返回一列的平均值 |
MAX( ) | 可以为数值字段、字符字段或表达式列作统计,返回最大的值 |
MIN( ) | 可以为数值字段、字符字段或表达式列作统计,返回最小的值 |
WITH ROLLUP
运算符,自动在列最后生成一个存储聚合函数的和值,只能适用于聚合函数;且跟在 group by
条件后可以实现分类汇总,
SELECT IFNULL(city, '合计') city, IFNULL(state, '小计') state, SUM(invoice_total) FROM invoices JOIN clients USING(client_id) GROUP BY city, state WITH ROLLUP
函数名称 | 描述 |
---|---|
ROUND() | 四舍五入;SELECT ROUND(5,745, 1) 括号里第一项是要处理的数字,第二项是要保留的位数,不写就取整数 |
TRUNCATE() | 截断数字;SELECT TRUNCATE(5.7563, 2) 第一项待处理,第二项是保留的位数 |
CEILING() | 向上取整,只有一个参数 |
FLOOR() | 向下取整 |
ABS() | 取参数的绝对值 |
RAND() | 返回 0-1 的随机浮点数 |
函数名称 | 描述 |
---|---|
LENGTH() | 返回字符串的长度;SELECT LENGTH('sky') |
UPPER() | 字符串转大写 |
LOWER() | 转小写 |
LTRIM() | 去除传入参数左侧的空格;RTRIM()会去除右侧;TRIM() 会同时去除两侧的空格 |
LEFT() | LEFT('Hello,World', 5) 返回前五个字符 ;RIGHT() 同理反之 |
SUBSTRING() | SUBSTRING('Hello,World', 2, 5) 从第二位开始,返回五个字符,第三参数不传就会取到最后 |
LOCATE() | LOCATE('e', 'hello') 第一个参数是要查找的字符,后面是查找的对象;返回值是最先发现的下标,如果不存在返回 0 ,不区分大小写 |
CONCAT() | 传入多个字符串参数,函数会将他们进行拼接 |
set autocommit = 0;
关闭自动提交模式set autocommit = 1;
开启自动提交模式SELECT @@tx_isolation; # 查看当前会话的隔离级别 SELECT @@global.tx_isolation; # 查看系统当前的隔离级别 SET SESSION TRANSACTION isolation LEVEL REPEATABLE READ; # 设置当前会话当前隔离级别 set global transaction isolation level repeatable read; # 设置系统当前隔离级别 set autocommit = off 或者 start transaction; # 命令行,开始事务时
作用:是为了保证数据的完整性而实现的摘自一套机制,它具体的根据各个不同的数据库的实现而有不同的工具(约束);
ALTER TABLE tradeInfo ADD CONSTRAINT FK_cardID FOREIGN KEY(cardID) REFERENCES cardInfo(cardID);
CONSTRAINT t_id_fk FOREIGN KEY (t_id) REFERENCES t1 (id)
select * from table_name force index(index_name) where conditions;
主键是最常见的索引类型
确保数据记录的唯一性
确定数据记录的唯一性
主键的值必须是唯一的且主键的值不能为空
默认情况下,mysql会自动尝试使用索引,不需要我们手动干预
主键只能声明一次,可以一次声明多个字段为主键
create table student( studentNo int(11) primary key, # 第一种声明方式,直接在字段后面声明 StudentName varchar(5), StudentPhone int(11), primary key(studentNo, studentPhone) # 第二种声明方式,可以同时设置多个字段为主键 );
作用:避免同一个表中某数据列中的值重复
被修饰的字段具有唯一性
字段值为空是不被检查,可以插入多个 NULL
unique 可以设置给多个字段,也可以一次给多个字段声明
可以同时设置对各字段为唯一索引
create table student( studentNo int(11) unique, # 第一种设置方式,为单个字段设置索引 studentName varchar(6), studentPhone int(11) unique, unique key (studentNo, studentName) # 第二种创建方式,同时设置多个字段 );
作用:快速定位特点数据
index 和 key 关键字都可设置常规索引
应加在查找字段
不宜添加过多的常规索引,影响数据的插入、删除和修改操作
删除index约束 drop index index_table_index on index_table;
create table student( studentNo int(11), StudentName varchar(5), StudentPhone int(11), index/key (studentNo, studentPhone) # 创建表时添加 ); alter table student add index (studentNo, studentPhone); # 创建后追加
create table student( fulltext (studentName) # 创建表时添加 ); alter table student add fulltext (studentName); # 创建后添加
alter table table_name add index_name (column_name)
drop index index_name on table_name
alter table table_name drop index index_name
alter table table_name drop primary key
删除主键D:\Program Files\MySQL\MySQL Server 5.5\bin>mysqldump -u root -p myschool > D:/temp/myschool.sql