一、SQL:
1、什么是SQL:
SQL,全称 Structured Query Language,是一种结构化查询语言,数据库访问语言。自1970年代诞生到现在。
2、SQL的功能:
SQL 可用于在数据库中增加,删除,修改,查询数据;
SQL 可用于新建数据库,新建数据表;
SQL 可用于新建视图,函数;
SQL 可用于简单的数据清洗;
SQL 可用于简单的数据分析;
SQL 可搭配 Hive,Spark SQL 做大数据;
SQL 可搭配 SQLFlow 做机器学习;
SQL 可搭配一定的工具做数据报表。
3、RDBMS:
RDBMS,全称relational database management system(关系数据库管理系统),是一种数据库软件,但我们经常狭义地称呼它为数据库。RDBMS将数据及数据关系以数据库和数据表的形式存储,并提供 SQL 访问接口。
目前主流 RDBMS 有 MySQL、PostgreSQL、SQL Server 和 Oracle;其中MySQL和PostgreSQL是免费开源且使用广泛的数据库。
4、SQL的分类:
DML(Data Manipulation Language)数据操纵语言,负责数据访问和数据操作
如:insert,delete,update,select(插入、删除、修改、检索)简称CRUD操新增Create、查询Retrieve、修改Update、删除Delete
DDL(Data Definition Language)数据库定义语言,负责数据库结构定义和数据库对象定义
如:create table之类
DCL(Data Control Language)数据库控制语言
如:grant、deny、revoke等,只有管理员才有相应的权限
DQL(Data Query Language) 数据查询语言:
是由SELECT子句,FROM子句,WHERE子句组成的查询块:
SELECT <字段名表>
FROM <表或视图名>
WHERE <查询条件>
二、Mysql:
1、数据库:
数据库是一个长期存储在计算机内的、有组织的、有共享的、统一管理的数据集合。是按照数据结构来组织、存储和管理数据的仓库。目前常用的数据库主要分为开源 MySQL 数据库(包括官方版 MySQL、Percona MySQL MariDB)和商业版数据库 ( 包括 SQL Server、Oracle、DB2 )。
2、数据库的分类:
(1)关系型数据(SQL)
关系型数据库,是指采用了关系模型来组织数据的数据库,从语言功能层面来讲,一般是指用 SQL 语言来进行操作管理的关系型数据库。常用的关系型数据库有 MySQL、Oracle、SQLServer、PostGreSQL。
(2)非关系型数据库(NoSQL)
NoSQL 通常指的是 non-relational ,也可以理解为 Not Only SQL,泛指非关系型数据库。常见的非关系型数据库有 MongDB、HBase、Redis。
(3)新型数据库(NewSQL)
NewSQL 是对各种新的可扩展/高性能数据库的简称,这类数据库不仅具有 NoSQL 对海量数据的存储管理能力,还保持了传统数据库支持 ACID 和 SQL 等特性。常见的 NewSQL 有 Google Spanner/F1、阿里 OceanBase、腾讯 TDSQL、TiDB、Cockroach。
3、关系型数据库:
顾名思义,关系型数据库就是一种建立在关系模型的基础上的数据库。关系模型表明了数据库中所存储的数据之间的联系(一对一、一对多、多对多)。
关系型数据库中,我们的数据都被存放在了各种表中(比如用户表),表中的每一列就存放着一条数据(比如一个用户的信息)。
4、mysql数据库:
MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件之一。
MySQL是一种关系型数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。
MySQL所使用的 SQL 语言是用于访问数据库的最常用标准化语言。MySQL 软件采用了双授权政策,分为社区版和商业版,由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,一般中小型网站的开发都选择 MySQL 作为网站数据库。
三、数据库的相关操作:
建库:
create database dbname DEFAULT CHARACTER SET utf8;
删库:
drop database dbname;
查看所有数据库:
show databases;
use 命令选中数据库:
use item_name;
四、数据表:
1、设计数据表:
数据表命名是小写字母和下划线_组成,用来分割不同单词之间的含义,例如 “student_course” 表示学生选课关联表,实际命名需要根据具体功能而定,好的命名规范在实际工作中也是很重要的。
(1)确定字段:
字段名称 | 含义 |
---|---|
id | 自增主键 |
name | 学生姓名 |
age | 学生年龄 |
id_number | 身份证号 |
(2)确定数据类型:
字段名称 | 数据类型 |
---|---|
id | 无符号整型(UNSIGNED INT) |
name | VARCHAR(50) |
age | UNSIGNED INT |
id_number | VARCHAR(18) |
(3)新建数据表:
create table student(
id int primary key auto_increment,
name varchar(50) not null,
age int not null,
id_number varchar(20));
2、数据表的相关操作:
(1)创建表:
创建tb_door表,有id,door_name,tel字段
create table tb_door(
id int primary key auto_increment,
door_name varchar(100),
tel varchar(50)
);
(2)修改表:
添加字段:
alter table student add grade int not null;
修改表名:
alter table student rename new_student;
(3)删:
删除表:
drop table new_student;
删除字段:
alter table student drop grade;
(4)查看表结构:
desc student;
六、字段的相关操作:
1、插入:
(1)插入数据:
INSERT INTO student (name,age,id_number) VALUES ('秦小贤',18,'42011720200604088X');
(2)查询数据:
select * from student;
*表示通配符,可以换成任何字段:
select name,age,id_number from student;
使用*查询的效率较低。
(3)一次性插入多条数据:
INSERT INTO student (name,age,id_number) VALUES ('王小虎',21,'530401198704022145'),('张敏',16,'52012419991105536X'),('李雪',22,'32040519950324890X');
2、删除:
(1)删除一条数据:
delete from student where id = 4;
(2)删除所有数据:
delete from student;
3、修改:
(1)修改一条数据:
update student set age = 22 where name = '王小虎';
(2)修改多条数据:
#修改前三条数据:
update student set age = 24 limit 3;
七、数据类型:
1、整型:
类型 | 大小 | SIGNED(有符号) | UNSIGNED(无符号) | 说明 |
---|---|---|---|---|
tinyint | 1字节 | -128~127 | 0~255 | 小整型 |
smallint | 2字节 | -32768~32767 | 0~65535 | 小整型 |
mediumint | 3字节 | -8388608~8388607 | 0~16777215 | 中整型 |
int | 4字节 | -2147483648~2147483647 | 0~49294967295 | 整型 |
bigint | 8字节 | -9223372036854775808 ~ 9223372036854775807 | 0~18446744073709551615 | 大整型 |
mysql没有boolean类型的数据,一般用tinyint(1)来表示boolean;
2、浮点型:
类型 | 大小 | SIGNED(有符号) | UNSIGNED(无符号) | 说明 |
---|---|---|---|---|
float | 4字节 | -3.402823466E+38 ~ -1.175494351E-38, 0, 1.175494351E-38 ~ 3.402823466351E+38 | 0,1.175494351E-38 ~ 3.402 823 466 E+38 | 单精度浮点型 |
double | 8字节 | -1.7976931348623157E+308 ~ -2.2250738585072014E-308, 0, 2.2250738585072014E-308 ~ 1.7976931348623157E+308 | 0, 2.2250738585072014E-308 ~ 1.797693134862315 7E+308 | 双精度浮点型 |
decimal | 每4个字节存储9个数字,小数点占1字节 | DECIMAL(M,D),取决于M和D,M是整数部分,D是小数部分 | DECIMAL(M,D),取决于M和D,M是整数部分,D是小数部分 | 精确类型,常用来表示金额 |
3、日期和时间:
类型 | 大小 | 格式 | 范围 |
---|---|---|---|
date | 3字节 | YYYY-MM-DD | 1000-01-01 ~ 9999-12-31 |
time | 3-6字节 | HH::MM:SS[.微秒] | -838:59:59 ~ 838:59:59 |
year | 1字节 | YYYY | 1901 ~ 2155 |
datetime | 5-8字节 | YYYY-MM-DD HH:MM:SS[.微秒值] | 1000-01-01 00:00:00 ~ 9999-12-31 23:59:59 UTC |
timestamp | 4-7字节 | YYYY-MM-DD HH:MM:SS[.微秒值] | 1970-01-01 00:00:00 ~ 2038-01-19 03:14:07 UTC |
4、字符串:
类型 | 范围 | 说明 |
---|---|---|
char | 1~255个字节 | 固定长度 |
varchar | 字段存储所占字节数不能超过65535字节 | 可变长度 |
tinytext | 最大长度255字节 | 可变长度 |
text | 最大长度65535个字节 | 可变长度 |
mediumtext | 最大长度16777215个字节 | 可变长度 |
longtext | 最大长度4294967295个字节 | 可变长度 |
5、枚举:
类型 | 范围 | 说明 |
---|---|---|
enum | 几何数最大65535 | 枚举值类型,只能插入列表中指定的值 |
6、二进制:
类型 | 范围 | 说明 |
---|---|---|
tinyblob | 最大长度255字节 | 可变长度 |
blob | 最大长度65535个字节 | 可变长度 |
mediumblob | 最大长度16777215个字节 | 可变长度 |
longblob | 最大长度4294967295个字节 | 可变长度 |
八、约束:
1、非空约束 not null:数据不能为空。
2、唯一约束 unique:数据不能重复。
3、主键约束 primary key:主键是一条记录的唯一标识,具有唯一性,不能重复。
4、外键约束 froeign key:是能确认另一张表记录的字段,用于保持数据的一致性。 比如,A表中的一个字段,是B表的主键,那它就可以是A表的外键。
5、默认约束 default:为字段提供默认值。
6、检查约束 check:为字段的赋值提供判断功能。
一个综合的案例:
create table test_tb(
id int primary key auto_increment,
id_number varchar(20) not null unique,
name varchar(18) not null,
age int not null default 0,
CHECK(age >= 0 and age<=200));
create table test_forgrein(
user_id int primary key not null,
address varchar(50),
FOREIGN KEY(user_id) REFERENCES test_tb(id));
九、函数:
1、基本函数:
(1)lower(字段名):数据转小写。
upper(字段名):数据转大写。
length(字段名):字段长度。
substr(字段名,a,b):截取子串,从a开始到b结束。
concat(字段名,"字符串"):将字符串拼接到字段后。
replace(字段名,"a","b"):将字段中的a替换成b。
ifnull(字段名,a):如果字段为空,则将其替换为a。
round(字段名,保留小数位数) & ceil(字段名,保留小数位数) & floor(字段名,保留小数位数):四舍五入、向上取整、向下取整。
uuid:返回UUID。
now:
select now() -- 年与日 时分秒
select curdate() --年与日
select curtime() --时分秒
year & month & day:
--hour()时 minute()分 second()秒
select now(),hour(now()),minute(now()),second(now()) from emp ;
--year()年 month()月 day()日
select now(),year(now()),month(now()),day(now()) from emp ;
转义字符:用\将'转换为普通字符。
2、聚合函数:
1、count
select count(*) from emp --底层优化了
select count(1) from emp --效果和*一样
select count(comm) from emp --慢,只统计非NULL的
2、max / min
select max(sal) from emp --求字段的最大值
select max(sal) sal,max(comm) comm from emp
select min(sal) min from emp --获取最小值
select min(sal) min,max(sal) max from emp --最小值最大值
SELECT ename,MAX(sal) FROM emp group by ename --分组
3、sum / avg 平均值
select count(*) from emp --总记录数
select sum(sal) from emp --求和
select avg(sal) from emp --平均数
十、条件查询和分组:
1、条件查询:
1、distinct
使用distinct关键字,去除重复的记录行
SELECT loc FROM dept;
SELECT DISTINCT loc FROM dept;
2、where
注意:where中不能使用列别名,不能使用聚合函数。
select * from emp
select * from emp where 1=1 --类似没条件
select * from emp where 1=0 --条件不成立
select * from emp where empno=100 --唯一条件
select * from emp where ename='tony' and deptno=2 --相当于两个条件的&关系
select * from emp where ename='tony' or deptno=1 --相当于两个条件的|关系
select name, sal from emp where sal=1400 or sal=1600 or sal=1800;
-- 或
select name, sal from emp where sal in(1400,1600,1800);
select name, sal from emp where sal not in(1400,1600,1800);
3、like
通配符%代表0到n个字符,通配符下划线_代表1个字符
select * from emp where ename like 'l%' --以l开头的
select * from emp where ename like '%a' --以a结束的
select * from emp where ename like '%a%' --中间包含a的
select * from emp where ename like 'l__' --l后面有两个字符的 _代表一个字符位置
4、null
select * from emp where mgr is null --过滤字段值为空的
select * from emp where mgr is not null --过滤字段值不为空的
5、between and
SELECT * FROM emp
select * from emp where sal>3000 and sal<10000
select * from emp where sal>=3000 and sal<=10000--等效
select * from emp where sal between 3000 and 10000--等效
6、limit
分数最高的记录:按分数排序后,limit n,返回前n条。Oracle做的很笨,实现繁琐,后期有介绍,而mysql做的很棒,语法简洁高效。在mysql中,通过limit进行分页查询:
select * from emp limit 2 --列出前两条
select * from emp limit 1,2 --从第二条开始,展示2条记录
select * from emp limit 0,3 --从第一条开始,展示3条记录--前三条
7、order by
SELECT * FROM emp order by sal #默认升序
SELECT * FROM emp order by sal desc #降序
2、分组:
将查询的结果进行分组统计,group by表示如何分组,having表示过滤的条件。
(1)group by:
select count(user_level),user_level from user group by user_level;
注意:
->查询有聚合函数和普通的字段时,普通字段要作为分组的对象。
(2)having:
select count(user_level),user_level from user group by user_level
having count(user_level) >2;
十一、事务:
1、何为事务:
事务是一组原子性的SQL查询,事务内的SQL语句,要么全部执行成功,要么全部执行失败。即任何一条语句失败,都必须回滚所有的步骤。
2、事务的特点:
关系型数据库都有ACID的特性:即原子性(atomicity)、一致性(consistency)、隔离性(isolation)、持久性(durability)。
原子性(atomicity):一个事务被视为一个完整的最小工作单元,事务中的数据库操作,要么全部执行成功,要么全部执行失败回滚,不能只成功执行了其中的一部分数据库操作;
一致性(consistency):数据库总是从一个一致性的状态转换到另一个一致性的状态。在银行转账的例子中,即使执行到第四条 SQL 语句时失败,用户的支票账户也不会损失 100 元人民币,因为执行失败时,事务进行了回滚,所做的修改并没有保存到数据库中;
隔离性(isolation):通常来说,一个事物所做的修改在提交以前,对其他事务是不可见的。在银行转账的例子中,当执行完第三条 SQL 语句时,此时另外一个程序在汇总支票账户,它所查询到的用户A的支票账户,并没有减去 100 元人民币;
持久性(durability):事务提交成功,所做的修改就会永久保存到数据库中,即使系统崩溃,修改的数据也不会丢失。
在 MySQL 中,事务是在存储引擎层实现的。MySQL 是支持多种存储引擎的数据库,但并不是所有的存储引擎都支持事务,比如 MyISAM 就不支持事务。
事务增加了数据库的安全性,同时也需要数据库做很多额外的工作。相比没有实现 ACID 的数据库,实现了 ACID 的数据库需要更强的 CPU、内存、以及磁盘空间。
3、隔离级别:
在 SQL 标准中,包含了四种隔离级别,即未提交读(read uncommitted)、提交读(read committed)、可重复读(repeatable read)、可串行化(serializable)。
未提交读(read uncommitted):一个事务还未提交,它所做的变更能被别的事务看到。事务可以读取未提交的数据,被称为脏读(dirty read),这种隔离级别在实际应用中一般很少使用;
提交读(read committed):一个事务提交之后,它所做的变更才能被别的事务看到。大多数数据库的默认隔离级别是提交读(read committed),比如 Oracle;
可重复读(repeatable read):一个事务在执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。在可重复读隔离级别下,未提交变更对其他事务也是不可见的。该级别保证了在同一个事务中,多次读取同样记录的结果是一致的。MySQL 的默认事务隔离级别是可重复读(repeatable read);
可串行化(serializable):serializable 是最高的隔离级别。对同一行数据,读写都会进行加锁。当出现锁冲突时,后面访问的事务必须等前一个事务完成,才能继续执行。实际应用场景很少用到这种隔离级别,只有在非常需要确保数据一致性,而且可以接受没有并发的情况,才会使用这种隔离级别。
隔离级别 | 脏读可能性 | 不可重复度可能性 | 幻读可能性 | 加锁读 |
---|---|---|---|---|
未提交读(read uncommitted) | yes | yes | yes | no |
提交读(read committed) | no | yes | yes | no |
可重复读(repeatable read) | no | no | yes | no |
可串行化(serializable) | no | no | no | yes |
4、脏读、幻读、修改丢失、不可重复读:
脏读:当一个事务正在对一个数据进行操作,但是操作的结果还没有写入到数据库中时,另一个事务来读取这个数据,所进行的操作的结果很可能是不正确的。
幻读:假设有事务A,B 和数据X,当A顺序读取X,Y,Z后,B在数据库中插入新的数据N,M,而后A第二次读取,发现多了几条数据。
修改丢失:假设有事务A,B 和数据X,Y,Z,当A读取X时,B也读取X,然后A对X进行写入,随后B对X进行写入。如此A写入的数据就被覆盖(丢失)了。
不可重复读:假设有事务A,B 和数据X,A读取X后,B对X进行修改,此时A再次读取X,会出现前后X的值不同的情况。即同一个事务两次读取一个数据的结果不同。
5、Mysql事务的特点:
(1)自动提交:
如果不是显式地开始一个事务,每个查询都会被当做一个事务执行 commit。
(2)隔离级别调整:
默认情况下,MySQL 的隔离级别是可重复读(repeatable read)。MySQL 可以通过 set transaction_isolation 命令来调整隔离级别,新的隔离级别会在下一个事务开始时生效。
6、事务处理:
#多条语句时,批量执行,事务提交
#有了事务,多步操作就形成了原子性操作,高并发下也不会引起数据错乱
#mysql的事务默认就是开启的 -- 多条语句一起操作时,要么一起成功要么一起失败
BEGIN; #关闭事务的自动提交
INSERT INTO user (id) VALUES(25);#成功
INSERT INTO user (id) VALUES(5);#已经存在5了,会失败
COMMIT; #手动提交事务
回滚 rollback
#多条语句,批量执行,insert插入重复的主键导致失败时,事务回滚
BEGIN;
INSERT INTO user (id) VALUES(15);
INSERT INTO user (id) VALUES(35);#存在了
ROLLBACK;#事务回滚,就不会再提交了
十二、多表联查:
多表查询是指基于两个和两个以上的表的查询。
1、笛卡尔积:
#把两个表的数据都拼接起来
SELECT * FROM dept,emp
2、内连接:inner join,只有数据存在时才能发送连接。即连接结果不能出现空行。
select stu.sname,stu.sbirthday,s.degree from students stu inner join scores s on s.sno = stu.sno where s.degree > 70;
3、外连接:left join,如果数据不存在,左表记录会出现,而右表为null填充。right join,如果数据不存在,右表记录会出现,而左表为null填充.
十三、索引:
1、什么是索引:
MySQL 索引的工作原理,类似一本书的目录,如果要在一本书中找到特定的知识点,先通过目录找到对应的页码。
2、索引的优缺点:
总的来说,索引三个优点如下:
索引可以大大减少 MySQL 需要扫描的数据量;
索引可以帮助 MySQL 避免排序和临时表;
索引可以将随机 IO 变为顺序 IO。
缺点:
对于非常小的表,大多数情况,全表扫描会更高效;
对于中大型表,索引就非常有效;
对于特大型表,建索引和用索引的代价是日益增长,这时候可能需要和其他技术结合起来,如分区表。
3、索引的实现:
一般使用B树,B+树或哈希表来实现。
4、索引的分类:
1、主键索引:
数据表的主键列使用的就是主键索引。
一张数据表有只能有一个主键,并且主键不能为 null,不能重复。
2、辅助索引:
单值索引:一个索引只包括一个列,一个表可以有多个列
唯一索引:索引列的值必须唯一,但允许有空值;主键会自动创建唯一索引
复合索引:一个索引同时包括多列
5、索引的实现:
#查看索引
show index from students;
#新建单值索引
create index sname_index on students(sname);
alter table students add index (sname);
#删除索引
alter table students drop index sname;
#新建唯一索引:
alter table students add unique (sname);
#创建复合索引
alter table students add index idx_name_birth (sname,sbirthday);
#创建复合唯一索引:
alter table students add unique uni_idx (sname,sbirthday);
十四、Mysql存储引擎:
MySQL 的存储引擎是插件式的,用户可以根据实际的应用场景,选择最佳的存储引擎。MySQL默认支持多种存储引擎,以适应不同的应用需求。
使用 show engines; 来查看Mysql支持的存储引擎。
和存储引擎相关的命令:
mysql> show variables like '%storage_engine%'; #查看默认引擎。
show table status like "table_name" ;#查看表的存储引擎。
从上图可以看出,Mysql默认使用的存储引擎是InnoDB,是最重要、使用最广泛的存储引擎。InnoDB 具有提交、回滚、自动崩溃恢复的事务安全保障,拥有独立的缓存和日志,提供行级别的锁粒度和强大的并发能力。在大多数使用场景中,包括事务型和非事务型存储需求,InnoDB 都是更好的选择,除非有非常特别的原因需要使用其他存储引擎。
InnoDB具有以下特点:
(1)自动增长列:
InnoDB 表的自动增长列,插入的值可以为空,也可以人工插入,如果插入的值为空,则实际插入的值是自动增长后的值。
create table test_tb(
id int primary key auto_increment,
id_number varchar(20) not null unique,
name varchar(18) not null,
age int not null default 0,
CHECK(age >= 0 and age<=200));
create table test_forgrein(
user_id int primary key not null,
address varchar(50),
FOREIGN KEY(user_id) REFERENCES test_tb(id));
当id为自动增长时,如果插入为null,则实际插入的数据是自动增长后得到的值。InnoDB中,自增长列必须是索引,同时必须是索引的第一个列 。如果不是第一个列,数据库会报出异常!
(2)主键和索引
InnoDB 表是基于聚簇索引建立的,聚簇索引也叫主索引,也是表的主键,InnoDB 表的每行数据都保存在主索引的叶子节点上。InnoDB 表必须包含主键,如果创建表时,没有显式指定主键,InnoDB 会自动创建一个长度为 6 个字节的 long 类型隐藏字段作为主键。所有的 InnoDB 表都应该显式指定主键。
InnoDB 表中,除主键之外的索引,叫做二级索引。二级索引必须包含主键列,如果主键列很大的话,其他的所有索引都会很大。因此,主键是否设计合理,对所有的索引都会产生影响。
一般来说,主键的设计原则大致如下:
满足唯一和非空约束;
主键字段应尽可能地小;
主键字段值基本不会被修改;
优先考虑自增字段,或查询最频繁的字段。
十五、SQL优化:
原则:
1、减少数据访问: 设置合理的字段类型,启用压缩,通过索引访问等减少磁盘IO
2、返回更少的数据: 只返回需要的字段和数据分页处理 减少磁盘io及网络io
3、减少交互次数: 批量DML操作,函数存储等减少数据连接次数
4、减少服务器CPU开销: 尽量减少数据库排序操作以及全表查询,减少cpu 内存占用
5、利用更多资源: 使用表分区,可以增加并行操作,更大限度利用cpu资源
总结到SQL优化中,就三点:
- 最大化利用索引;
- 尽可能避免全表扫描;
- 减少无效数据的查询;
优化手段:
1. 尽量避免在字段开头模糊查询,会导致数据库引擎放弃索引进行全表扫描。
即避免:
select id,user_name from user_tb where user_name like "%陈%"
而应当:
select id,user_name from user_tb where user_name like "陈%"
2、不要在where子句中使用or来连接条件,or可能会导致索引失效,应当用UNION或UNION ALL:
即避免:
SELECT * FROM student WHERE id=1 OR salary=30000
而应当:
SELECT * FROM student WHERE id=1
UNION ALL
SELECT * FROM student WHERE salary=30000
3、避免使用in或not in,同样会导致索引失效,数值可以使用between and,子查询可以用exist代替:
即避免:
SELECT * FROM student WHERE ID IN (1,2,3);
而应当:
SELECT * FROM student where id BETWEEN 1 AND 3;
避免:
SELECT * FROM student WHERE id IN (SELECT id FROM Sid);
而应当:
SELECT * FROM student EXIST (SELECT id FROM Score WHERE Score.id=student.id);
4、避免null值判断,应当给属性赋初值,如:0;
5、查询尽量避免返回大量数据,应当使用分页;
6、字符串怪现象:不加单引号时,是字符串跟数字的比较,它们类型不匹配,MySQL会做隐式的类型转换,把它们转换为数值类型再做比较
反例:
#未使用索引
EXPLAIN
SELECT * FROM student WHERE NAME=123
正例:
#使用索引
EXPLAIN
SELECT * FROM student WHERE NAME='123'
7、查询条件不能用 <> 或者 !=;
8、order by 条件要与where中条件一致,否则order by不会利用索引进行排序;
9、避免在where中对字段进行表达式操作;
即避免:
select * from student where id+1-1=1;
而应当:
select * from student where id = 1+1-1;
10、distinct过滤的字段要少:过滤字段会消耗大量的计算机资源;