Mysql

SQL简介

什么是SQL

  • SQL 指结构化查询语言,全称是 Structured Query Language。
  • SQL 让您可以访问和处理数据库,包括数据插入、查询、更新和删除。
  • SQL 语言采用英语关键词,使其易读易写。
  • SQL 提供了丰富的操作数据的功能,从简单的查询到复杂的数据库管理操作。

SQL能做什么

  • 面向数据库执行查询
  • 可从数据库取回数据
  • 可在数据库中插入新的记录
  • 可更新数据库中的数据
  • 可从数据库删除记录
  • 可创建新数据库
  • 可在数据库中创建新表
  • 可在数据库中创建存储过程
  • 可在数据库中创建视图
  • 可以设置表、存储过程和视图的权限
  • 允许多个人同时操作

SQL相关

  • 数据库管理系统(DataBase-Management System,DBMS):由一个相互关联的数据的集合和一组用以访问这些数据的程序组成。这个数据集合通常称作数据库(database)
  • 关系型数据库:基于关系模型,使用一系列表来表达数据以及这些数据之间的关系。MySQL就是关系型数据库。
    • 关系模型已经成为当今主要的数据模型,它比之前的的网络模型和层次模型简化了编程者的工作。现在开始流行的NoSQL,泛指非关系型的数据库。

Mysql

了解Mysql

Mysql配置文件

  • Ubuntu20上通过apt安装的mysql配置文件及目录是/etc/mysql/mysql.conf.d,windows上面是安装目录下的my.ini。如果需要改MySQL的一些设置就需要在配置文件里面去改

查看Mysql服务

  • Linux上,通过:service mysql status
  • Windows下通过任务管理器即可查看
  • 启动Mysql:service mysql start

登录Mysql

  • 输入mima查询用户名和密码(这是我自己写的命令),出现一个管理员用户和一个普通用户
  • 本地连接:mysql -u用户名 -p密码
    • 不行展示密码就mysql -u用户名 -p
  • 远程连接:mysql -hIP地址 -P端口 -u用户 -p-->>输入密码
  • 输入exit或者quit退出

最重要的SQL命令

  • SELECT - 从数据库中提取数据
  • UPDATE - 更新数据库中的数据
  • DELETE - 从数据库中删除数据
  • INSERT INTO - 向数据库中插入新数据
  • CREATE DATABASE - 创建新数据库
  • ALTER DATABASE - 修改数据库
  • CREATE TABLE - 创建新表
  • ALTER TABLE - 变更(改变)数据库表
  • DROP TABLE - 删除表
  • CREATE INDEX - 创建索引(搜索键)
  • DROP INDEX - 删除索引

基础语法

  • MySQL 语句的规范:
    • 关键字与函数名称全部大写
    • 数据库名称、表名称、字段名称全部小写,用反引号括起来
    • SQL语句必须以分号结尾,表示结束
    • 当然不这样也行,只是一种规范
  • 查看当前用户:SELECT USER()

  • 查库:SHOW DATABASES
  • 进入某个数据库:USE XXX(库名)
  • 判断在哪个数据库里:SELECT DATABASE()
  • 创建数据库:CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] \库名``
    • 用大括号的部分,就是多选一
    • 用中括号的部分, 是可选项
    • Mysql中的DATABASE和SCHEMA等效,在其他数据库中可能会有不一样
  • 删除数据库:DROP {DATABASE | SCHEMA} [IF EXISTS] \库名``
补充说明

在MYSQL5.0版本之后,MySQL默认在数据库中存放一个"information_schema"的数据库,是mysql自带的一个信息数据库,保存着关于MySQL服务器所维护的所有其他数据库的信息。

  • 该数据库中可利用的表
    • SCHEMATA表存储该用户创建的所有数据库名的库名。
      • schema_name字段用来存储数据库名
    • TABLES表:储存了数据库的库名以及各个数据库中的表名等信息,可以根据数据库的库名查询到该数据库包含的表有哪些。
    • schema_name表:储存了所有数据库的库名
    • table_schema表:储存了数据库名
    • tables表:储存了数据库库名,以及该库中包含的表名
    • table_schema表:储存了数据库名
    • table_name表:储存了表名
    • 库名为:TABLES_SCHEMA,表名为:TABLE_NAME,字段名为:COLUMN_NAME.
  • 注:表和字段可能具有相对性

  • 查表:SHOW TABLES [FROM \库名`]`
  • 查看当前数据库中的数据表:SHOW TABLES
  • 创建表:
CREATE TABLE [IF NOT EXISTS] table_name(
	->column_name data_type,
	->column_name data_type,
	->column_name data_type,
	...);
  • column_name是字段名,也就是列名
  • data_type是字段类型,常见字段类型有整型和字符串
  • 查看表的创建信息:SHOW CREATE TABLE tb_name
  • 修改表名:ALTER TABLE \tb_name1` RENAME `tb_name2``
  • 查看表字段结构:DESCRIBE tb_name
    • 可简写为:DESC tb_name
      示例:
mysql> DESCRIBE `student`;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int         | YES  |     | NULL    |       |
| name  | varchar(20) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
# Field:字段名
# Type:字段类型
# Null:非空约束,即字段能否为空值
# Key:键约束
# Default:约束
# Extra:其他约束
  • 删除表:DROP TABLE table_name

字段

  • 查字段SHOW COLUMNS FROM tb_name
# 添加字段
ALTER TABLE `tb_name` ADD [COLUNM](
	->`col_name` column_definition(data_type),
	->`col_name` column_definition,
	......);
	
# 删除字段
ALTER TABLE `tb_name` DROP `col_name`,DROP `col_name`,......;

# 修改字段类型
## 法一:
### MODIFY:修改列的数据类型
ALTER TABLE `tb_name` MODIFY `col_name` data_type;
## 法二:
### CHANGE:改列名和数据类型
ALTER TABLE `tb_name` CHANGE `col_name1` `col_name2` data_type;

数据

# 查看数据
SELECT * FROM `tb_name`;
SELECT `col_name1`,`col_name2` FROM `tb_name` [WHERE ...]

# 插入数据
## 字段值是字符串类型的用单/双引号引起来,不然会报错
INSERT [INTO] `table_name`[(`col_name1`,`col_name2`,...)]{VALUES|VALUE} ({expr|DEFAULT}),(expr|DEFAULT),(...)...;
### 插入多个字段值用VALUES
#### 示例
INSERT INTO `student`(`id`,`name`)VALUES(1,'lili'),(2,'lisa');
### 如果不指定字段就要为所有字段匹配字段值
#### 示例
INSERT INTO `tb_name`VALUES(,,,,,)

# 更新数据
UPDATE `tb_name` SET `col_name1`={expr1|DEFAULT} [WHERE ...] [OR ...] [AND ...]
##更新数据时,如果不用WHERE限定条件,就会更改字段的所有字段值

# 删除数据
DELETE FROM `tbl_name` WHERE where_conditon;
## 相同数据???
常用的数据类型

MySQL 支持多种类型,大致可以分为三类:数值、日期/时间和字符串(字符)类型。

数值类型 大小 范围(有符号) 范围(无符号) 用途
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) 双精度 浮点数值
日期/时间类型 大小(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:01' UTC 到 '2038-01-19 03:14:07' UTC结束时间是第 2147483647 秒,北京时间 2038-1-19 11:14:07,格林尼治时间 2038年1月19日 凌晨 03:14:07 YYYY-MM-DD hh:mm:ss 混合日期和时间值,时间戳
字符串类型 大小 用途
CHAR 0-255 bytes 定长字符串
VARCHAR 0-65535 bytes 变长字符串
TEXT 0-65 535 bytes 长文本数据
  • char(n) 和 varchar(n) 中括号中 n 代表字符的个数,并不代表字节个数,比如 CHAR(30) 就可以存储 30 个字符

表约束与表关系

表约束

  • 可以在创建时或创建后添加
  • 尽量不要在有数据的时候添加,不然数据和约束冲突就会报错
  • 约束就是规定字段存储数据的规则
# 参照示例
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int         | YES  |     | NULL    |       |
| name  | varchar(20) | NO  | UNI | NULL    |       |
+-------+-------------+------+-----+---------+-------+
# NULL:非空约束,YES表示可以为空,NO表示不能为空
# Key:UNI表示添加了唯一约束,PRI表示添加了主键约束,MUL表示添加了外键约束
# Default:默认约束
# Extra:自增约束
非空约束
  • 约束数据库字段的某个值是否可以为空
  • NULL列的字段为YES则可以为空,NO则字段值不能为空
  • 当字段设置为非空时,插入值就必须要插入值,否则就会报错
  • 添加非空约束:ALTER TABLE MODIFY \col_name` data_type NOT NULL`
  • 注意:要删除的字段值为NULL的时候,不能用=来判断,要用IS
  • 删除非空约束:ALTER TABLE MODIFY \col_name` data_type`
唯一约束
  • 字段添加唯一约束之后,该字段的值不能重复,也就是该字段的值在该表中唯一
  • 不提供约束名就默认约束名为字段名
# 添加唯一约束
ALTER TABLE `tb_name` ADD [CONSTRAINT[symbol]]UNIQUE [INDEX|KEY] [index_name] [index_type](index_col_name)
## 示例:
ALTER TABLE `tb_name` ADD UNIQUE `other_name` (`col_name`);
### 创建唯一约束的时候要给约束一个约束名

# 删除唯一约束
ALTER TABLE `tbl_name` DROP {INDEX|KEY}(一般用KEY) index_name(即other_name)
## 示例:
ALTER TABLE `tb_name` DROP KEY `other_name`
主键约束
  • 即非空+唯一,一张表只能存在一个主键
  • 主键保证记录的唯一性,自动为NOT NULL
  • 真主键:NOT NULL+PRI KEY
  • 伪主键:NOT NULL+UNI KEY,表中没有主键时会默认这个伪主键为主键,表中表现为NOT NULL+PRI KEY此时删除就要按照主键的规格来删
    • 如果此时添加一个真主键,伪主键就会改回NOT NULL+UNI KEY
    • 如果添加过真主键,真主键被删除后删除伪主键不能按照主键的规格删
# 添加主键约束
ALTER TABLE `tb_name` ADD [CONSTRAINT[sysbol]]PRIMARY KEY [index_type] (index_col_name)
## 示例:
ALTER TABLE `tb_name` ADD PRIMARY KEY(`col_name`)

# 删除主键约束
ALTER TABLE `tb_name` DROP PRIMARY KEY
## 注意:删除主键约束后非空约束会留下
自增约束
  • 即自增长,只能添加在主键上
    • 伪主键也可以添加自增约束
  • 自动编号,默认情况下,初始值为1,每次的增量为1
    • 初始值只能在创建表的时候设置
  • 自增长约束只能有一个
# 添加自增约束:
ALTER TABLE `tb_name` CHANGE `col_name` `col_name` data_type AUTO_INCREMENT{=num};
# 删除自增约束:
ALTER TABLE `user` CHANGE `id` `id` INT NOT NULL ;
默认约束
  • 添加数据的时候如果没有给该字段设置值,则会有一个默认值存在
  • 法一:ALTER TABLE tb_name ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}
    • 示例:ALTER TABLE tb_name ALTER col_name SET DEFAULT XXX
  • 法二:ALTER TABLE tb_name MODIFY col_name data_type DEFAULT XXX
创建表的时候添加约束
CREATE TABLE `students`(
	->`id` INT PRIMARY KEY AUTO_INCREMENT,
	->`name` VARCHAR(20) NOT NULL,
	->`age` INT DEFAULT 18,
	->`phone` CHAR(20),UNIQUE `phone_uni`(`phone`))
	AUTO_INCREMENT=100;

表关系

  • 这里的关系指的是数据在逻辑上,人赋予的关系
    • 比如:每一人用户表里面存放用户的重要信息, 再定一个用户信息详细表,用来存放用户的详细信息,这个详细信息表就是用户表的就存在一个一对一的关系
  • 一对一关系: 如用户表对应用户的详细信息,指的是一个实体的某个数据与另外一个实体的一个数据有关联关系
    • 建议添加唯一外键:给其中一张表添加外键,但这个外键必须要有唯一约束
  • 一对多关系: 如一个学院当中,有若干学生,指的是一个实体的某个数据与另外一个实体的多个数据有关联关系
    • 外键只能建立在多的那张表
    • 添加数据时先添加父表(一),再添加子表(多)
    • 删除数据时先删除子表,再删除父表
  • 多对多关系: 如课程和学生之间,一个课程有很多学生,一个学生对应很多课程,一个实体的数据对应另外一个实体的多个数据,另外实体的数据也同样对应当前实体的多个数据
    • 对于多对多关系,需要创建第三张关系表(C),关系表中通过外键加主键的形式实现这种关系。这里需要注意的是
    • 在多对多关系中,我们常用中间表来表示
    • 表A和表B对表C的关系分别都是一对多
    • 联合主键+双外键
外键约束
  • 是对其他表的约束
  • 可以把两张表联系起来,关联两张表的字段
  • 外键列和参照列数据类型一致
  • 外键必须关联到键上面去
# 查看所有外键
SELECT CONSTRAINT_NAME FROM	INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE	CONSTRAINT_SCHEMA = 'mydb' AND CONSTRAINT_NAME != 'PRIMARY';

# 添加外键
ALTER TABLE tb_name(需要添加外键的表) ADD [CONSTRAINT 外键名] FOREIGN KEY [id] (index_col_name, ...) REFERENCES tb_name(要参考的表) (index_col_name, ...) 
[ON DELETE {CASCADE | SET NULL | NO ACTION | RESTRICT}](删除时发生什么操作)  /  
[ON UPDATE {CASCADE | SET NULL | NO ACTION | RESTRICT}](更新时发生什么操作)
## CASCADE    删除包含与已删除键值有参照关系的所有记录
## SET NULL   修改包含与已删除键值有参照关系的所有记录,使用NULL值替换(只能用于已标记为NOT NULL的字段)
## RESTRICT   拒绝删除要求,直到使用删除键值的辅助表被手工删除,并且没有参照时(这是默认设置,也是最安全的设置)
## NO ACTION同 RESTRICT 也是首先先检查外键;  (拒绝删除或者更新父表)
### 示例:
ALTER TABLE `student` ADD FOREIGN KEY (`dept_id`)(要添加外键的字段) REFERENCES `department`(`d_id`) ON DELETE SET NULL
联合主键
  • 两个字段的组合不能出现重复值
  • ALTER TABLE tb_name ADD PRIMARY KEY(col1_name,col2_name)

数据库三范式

  • 第一范式(1NF):符合1NF的关系中的每个属性都不可再分。
    • 1NF是所有关系型数据库的最基本要求
    • 简单来说,就是不能出现多个表头
  • 第二范式(2NF):2NF在1NF的基础之上,消除了非主属性对于码的部分函数依赖
    • 简单来说,只能描述一个对象(主键),其它列名(副键)与对象之间相互完全依赖
  • 第三范式(3NF):3NF在2NF的基础之上,消除了非主属性对于码的传递函数依赖
    • 简单的说,所有的非主属性只在整个数据库里面出现一次,副键与副键之间,不能存在依赖关系范式的作用是尽可能避免数据的冗余和插入/删除/更新的异常

表查询

视图

  • 三范式让表查询变得复杂,对于常用的数据查询,反复写复杂的查询语句十分不方便,因此可以创建一个虚拟的表(不存数据)
  • 这个虚拟表的数据来源于数据库中存在的其他表,虚拟表的数据来源就在定义时给定,源表被改动该表也会改动
# 创建视图
CREATE [OR REPLACE] VIEW view_name [(column_list)] AS select_statement    [WITH [CASCADED | LOCAL] CHECK OPTION]
## 示例:
CREATE VIEW `view_name` AS SELECT * FROM `tb1_name` RIGHT JOIN `tb2_name`
# 删除视图
DROP VIEW view_name

事务(非常重要)

  • 遵循原子性,即多条SQL语句当作一条执行,如果有一条失败则都会失败
  • 遵循一致性,即多个并行事务执行结果必须按照某个顺序串行执行
  • 遵循隔离性,即事务的执行不受其他事务影响
  • 遵循持久性,即事务处理结束后,对数据的修改是永久的
  • 关键字:
    • BEGIN:开始
    • ROLLBACK:回滚
    • COMMIT:提交/确认
BEGIN;# 固定数据
SQL语句
ROLLBACK;# 回滚到BEGIN时候的数据状态
COMMIT;# 确认操作,此时回滚不会再回到BEGIN的数据状态

单表查询

  • SELECT * FROM tb_name;
    • SELECT 后面跟上要查询的字段,* 号代表所有的字段
    • 一般来说,查询所有字段是最耗时长的,所以今后查询数据尽可能按需所取。
  • 条件查询:条件查询条件可以是大于等于不等于(>,=,<>)等等,也可以是更加复杂的判断都是可以的。
    • 示例:SELECT col_name FROM tb_name WHERE xxx
  • 取别名:如果列名或者表名太长,可以给它们取一个别名,可以方便取使用
    • SELECT col_name AS new_name FROM tab_name AS new_name2
  • 行查询:SELECT * FROM tb_name\G;
    • 按行显示数据
  • 模糊查询:()代表或者,这个查询相当于正则查询
    • 示例:SELECT * FROM stu WHERE si_age IN (19,30)查询19或30的数据
    • LIKE关键词的查询更加模糊
      • 示例:SELECT * FROM tb_name WHERE col_name LIKE 'L%'
      • 查询某字段所有匹配L...的数据
      • %代表通配符
      • _匹配一个字符
  • 区间表示:
    • 示例:SELECT * FROM stu WHERE si_age BETWEEN 19 AND 30
    • 用大于号小于号也行

多表查询

内连接
  • 笛卡尔坐标系:把两张表想象成X轴和Y轴,轴上的每个点,就是两个表里面的每行数的集合
SELECT * FROM `department` INNER JOIN `students`;
SELECT * FROM `department` , `students`;
SELECT * FROM `department` CROSS JOIN  `students`;
SELECT * FROM  `department` JOIN `students`;
## 以上这个四个SQL的结果都一样,都是笛卡尔积,也叫无条件连接/交叉连接等,不推荐,比较耗内存
注意在mysql中,INNER JOIN 和 CROSS JOIN 是一样的。
# 当然也是可以
SELECT * FROM `department` INNER JOIN `students` ON `department`.`d_id` = `students`.`dept_id`;
SELECT * FROM `department` INNER JOIN `students` WHERE `department`.`d_id` = `students`.`dept_id`;
SELECT * FROM `department` p , `students` s WHERE p.`d_id`=s.`dept_id`;
SELECT * FROM `department` p CROSS JOIN `students` s WHERE p.`d_id` = s.`dept_id`;
SELECT * FROM `department` AS `p` , `students` AS `s` WHERE p.`d_id`=s.`dept_id`;
## 这是有条件连接
## WHERE相比于ON在数据量较大的时候比较占内存
外连接
左连接
  • A LEFT JOIN B 会以左边的表为主,展式左边表的所有数据,展式右边表中符合ON子句中条件的数据,没有为NULL
  • SELECT * FROM 第一张表 LFET JOIN 第二张表 ON 主表.s_id=sd.stu_id;
右连接
  • SELECT * FROM 第一张表 RIGHT JOIN 第二张表 ON 主表.s_id=sd.stu_id;
全连接
  • UNION操作符
    • UNION 操作符用于合并两个或多个 SELECT 语句的结果集
    • 它可以从多个表中选择数据,并将结果集组合成一个结果集
    • 使用 UNION 时,每个 SELECT 语句必须具有相同数量的列,且对应列的数据类型必须相似
      • 即被拼接两张表的字段数要相同
    • UNION 操作符默认会去除重复的记录,如果需要保留所有重复记录,可以使用 UNION ALL 操作符
    • 即两张表拼接然后消除重复的内容
      语法:
SELECT column1, column2, ...
FROM table1
UNION
SELECT column1, column2, ...
FROM table2;
# 示例1:
SELECT s.`name`,c.`name` FROM `students` s LEFT JOIN `select` se ON s.`s_id`=se.`stu_id` LEFT JOIN `course` c ON c.`id`=se.`coures_id`
UNION {ALL}
SELECT s.`name`,c.`name` FROM `students` s LEFT JOIN `select` se ON s.`s_id`=se.`stu_id` LEFT JOIN `course` c ON c.`id`=se.`coures_id`;
# 示例2:
SELECT s.`name`,c.`name` FROM `students` s LEFT JOIN `select` se ON s.`s_id`=se.`stu_id`
UNION {ALL}
SELECT s.`name`,c.`name` FROM `students` s RIGHT JOIN `select` se ON s.`s_id`=se.`stu_id`

子表查询

  • 在一个SQL语句中出现两个SQL语句,就是子表查询
  • 把一个命令的结果作为条件给另一个命令使用
  • 子表结果只有为一行的时候才能传递给WHERE
  • 下面这个子表查询是在JOIN这个地方建立查询
# 示例1:
SELECT s.`name`, e.`name`FROM `students` s 
LEFT JOIN(
SELECT se.`stu_id`,c.`name` FROM `select` se JOIN `course` c ON se.`coures_id` = c.`id`	) e
ON s.`s_id`=e.`stu_id`;
# 示例2:
SELECT * FROM `stu` WHERE `dept_id`=(
SELECT `d_id` FROM `department` WHERE `d_name`='PYTHON');

对结果集排序:ORDER BY

SELECT * FROM table_name
ORDER BY column_name [ASC|DESC]
  • ASC : 升序(默认)。
  • DESC: 降序。

限制行数:LIMIT

  • 对查询出来的结果限制显示的行数
    示例:
SELECT * FROM `students` s JOIN `student_details` sd ON s.`s_id`=sd.`stu_id` ORDER BY  s.`s_id` DESC LIMIT 3;

分组查询

  • 分组是个常见的操作,常用于分组统计
  • 使用GROUP BY后,会按照GROUP BY后面的字段进行分组,且必须是明确的字段,不能是*
    • GROUP BY后面不能通过WHERE来筛选
  • 因此SELECT后面也不能是*
  • 其次可以使用HAVING可以对分组之后的结果进行筛选
    • 注意:HAVING 后的字段必须是SELECT后出现过的
  • 示例:
SELECT d.`d_id`,d.`name`,COUNT(*) FROM `department` d LEFT JOIN `students` s ON d.`d_id`=s.`dept_id` GROUP BY d.`d_id`,d.`name`;
# COUNT(*)统计该字段下各个数据分布的数据量
SELECT d.`d_id`,d.`name`,COUNT(*) FROM `department` d LEFT JOIN `students` s ON d.`d_id`=s.`dept_id` GROUP BY d.`d_id`,d.`name` HAVING COUNT(*)>1;

AND & OR 运算符

如果第一个条件和第二个条件都成立,则 AND 运算符显示一条记录。
如果第一个条件和第二个条件中只要有一个成立,则 OR 运算符显示一条记录。

Mysql函数

处理NULL(IFNULL)

SELECT IFNULL(`col_name`,430)(如果该字段的数据为NULL则返回后面那个值) FROM `tb_name`

字段去重(DISTINCT)

  • 得到该字段不重复的的数据
SELECT DISTINCT `name` FROM `students`

字符串截取

LEFT是从左边开始截取,RIGHT是用右边开始截取,SUBSTRING可以指定截取范围

SELECT LEFT(`col_name`,2),IFNULL(`col_name`,430) FROM `students`
# 截取数据左边两个字符
SELECT RIGHT(`col_name`,2),IFNULL(`col_name`,430) FROM `students`

SELECT SUBSTRING(`col_name`,2,5),IFNULL(`col_name`,430) FROM `students`

字符串拼接(CONCAT)

SELECT CONCAT(s.`name`,sd.`id_card`) FROM `students` s LEFT JOIN `student_details` sd ON s.`s_id`=sd.`stu_id`;

类型转换

SELECT CAST(sd.`id_card` AS CHAR) FROM `students` s LEFT JOIN `student_details` sd ON s.`s_id`=sd.`stu_id`;SELECT CONVERT(s.`dept_id`,SIGNED) FROM `students` s ;

时间函数

SELECT DAY('2017-08-18')-DAY('2017-08-01’);
SELECT NOW();

SQL优化

执行顺序(不怎么重要)

1.FROM: 对FROM的左边的表和右边的表计算笛卡尔积。产生虚表VT1
2.ON: 对虚表VT1进行ON筛选,只有那些符合<join-condition>的行才会被记录在虚表VT2中
3.JOIN: 如果指定了OUTER JOIN(比如left join、 right join),那么保留表中未匹配的行就会作为外部行添加到虚拟表VT2中,产生虚拟表VT3, rug from子句中包含两个以上的表的话,那么就会对上一个join连接产生的结果VT3和下一个表重复执行步骤1~3这三个步骤,一直到处理完所有的表为止。
4.WHERE: 对虚拟表VT3进行WHERE条件过滤。只有符合<where-condition>的记录才会被插入到虚拟表VT4中
5.GROUP BY: 根据group by子句中的列,对VT4中的记录进行分组操作,产生VT5.
6.CUBE | ROLLUP: 对表VT5进行cube或者rollup操作,产生表VT6.
7.HAVING: 对虚拟表VT6应用having过滤,只有符合<having-condition>的记录才会被 插入到虚拟表VT7中。
8.SELECT: 执行select操作,选择指定的列,插入到虚拟表VT8中。
9.DISTINCT: 对VT8中的记录进行去重。产生虚拟表VT9.
10.ORDER BY: 将虚拟表VT9中的记录按照<order_by_list>进行排序操作,产生虚拟表VT10.
11.LIMIT:取出指定行的记录,产生虚拟表VT11, 并将结果返回。

查找优化

  • 要想SQL执行快一点,应该尽量避免模糊匹配,如:like, in, not in 等这些匹配条件
  • 尽量避免整表扫描,如SELECT *
  • 建立合适的索引3
  • 使用合适的存储引擎
  • 在JOIN中,尽量用小表LEFT JOIN 大表
  • 除非十分必要,尽量不要使用ORDER BY,GROUP BY 和 DISTINCT(去重),尽量用索引来代替
posted @ 2025-02-08 12:22  micryfotctf  阅读(56)  评论(0)    收藏  举报