一篇搞懂SQL
Posted 笔绘丹心
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一篇搞懂SQL相关的知识,希望对你有一定的参考价值。
前言
根据廖雪峰老师的教程,整理出一篇文章
一,为什么需要数据库?
小量的数据可以使用excel或者cvs存储,但是大批量的数据,这些都无法满足需求。如何管理这些数据就成了大问题。
所以,数据库作为一种专门管理数据的软件就出现了。应用程序不需要自己管理数据,而是通过数据库软件提供的接口来读写数据。至于数据本身如何存储到文件,那是数据库软件的事情,应用程序自己并不关心
二,数据库的分类以及哪种最广为适用
- 层次模型
- 网状模型
- 关系模型
其中关系型数据库,广为适用
为什么呢?因为相比层次模型和网状模型,关系模型理解和使用起来最简单。
三,如何安装数据库
要在Windows或Mac上安装mysql,首先从MySQL官方网站下载最新的MySQL Community Server版本:
https://dev.mysql.com/downloads/mysql/
选择对应的操作系统版本,下载安装即可。在安装过程中,MySQL会自动创建一个root
用户,并提示输入root
口令
如何验证是否安装成功?
MySQL安装后会自动在后台运行。为了验证MySQL安装是否正确,我们需要通过mysql这个命令行程序来连接MySQL服务器。
在命令提示符下输入mysql -u root -p,然后输入口令,如果一切正确,就会连接到MySQL服务器,同时提示符变为mysql>。
输入exit退出MySQL命令行
四,关系模型
什么是主键?
能够通过某个字段唯一区分出不同的记录,这个字段被称为主键。
对主键的要求,最关键的一点是:记录一旦插入到表中,主键最好不要再修改,因为主键是用来唯一定位记录的,修改了主键,会造成一系列的影响。
由于主键的作用十分重要,如何选取主键会对业务开发产生重要影响。如果我们以学生的身份证号作为主键,似乎能唯一定位记录。然而,身份证号也是一种业务场景,如果身份证号升位了,或者需要变更,作为主键,不得不修改的时候,就会对业务产生严重影响。
所以,选取主键的一个基本原则是:不使用任何业务相关的字段作为主键。
###什么是外键?
可以把数据与另一张表关联起来,这种列称为外键。通过一个表的外键关联到另一个表,我们可以定义出一对多,一对一,一对多的关系
什么是索引
索引是关系数据库中对某一列或多个列的值进行预排序的数据结构。
在设计关系数据表的时候,看上去唯一的列,例如身份证号、邮箱地址等,因为他们具有业务含义,因此不宜作为主键。
但是,这些列根据业务要求,又具有唯一性约束:即不能出现两条记录存储了同一个身份证号。这个时候,就可以给该列添加一个唯一索引
五,查询数据
1.基本查询
SELECT * FROM <表名>
使用SELECT * FROM students时,SELECT是关键字,表示将要执行一个查询,*表示“所有列”,FROM表示将要从哪个表查询
SELECT语句其实并不要求一定要有FROM子句。我们来试试下面的SELECT语句:
SELECT 100+200; 计算出300,但是计算并不是sql的强项,可以用来验证sql是否安装成功。
2.条件查询
SELECT * FROM <表名> WHERE <条件表达式>
SELECT语句可以通过WHERE条件来设定查询条件,查询结果是满足查询条件的记录。例如,要指定条件“分数在80分或以上的学生”,写成WHERE条件就是SELECT * FROM students WHERE score >= 80
条件查询关键字
AND
SELECT * FROM students WHERE score >= 80 AND gender = 'M';
OR
SELECT * FROM students WHERE score >= 80 OR gender = 'M';
NOT
第三种条件是NOT <条件>,表示“不符合该条件”的记录,不常用
SELECT * FROM students WHERE NOT class_id = 2;
表达式的优先级
如果不加括号,条件运算按照NOT、AND、OR的优先级进行,即NOT优先级最高,其次是AND,最后是OR。加上括号可以改变优先级。
3.投影查询
如果我们只希望返回某些列的数据,而不是所有列的数据,我们可以用SELECT 列1, 列2, 列3 FROM …,让结果集仅包含指定列。这种操作称为投影查询
SELECT id, score, name FROM students;
####给查询的列明添加别名
使用SELECT 列1, 列2, 列3 FROM …时,还可以给每一列起个别名,这样,结果集的列名就可以与原表的列名不同。它的语法是SELECT 列1 别名1, 列2 别名2, 列3 别名3 FROM …
SELECT id, score points, name FROM students;
排序
我们使用SELECT查询时,细心的读者可能注意到,查询结果集通常是按照id排序的,也就是根据主键排序。这也是大部分数据库的做法。如果我们要根据其他条件排序怎么办?可以加上ORDER BY子句
SELECT id, name, gender, score FROM students ORDER BY score;
倒序 DESC
如果要反过来,按照成绩从高到底排序,我们可以加上DESC表示“倒序”
SELECT id, name, gender, score FROM students ORDER BY score DESC;
升序 ASC
默认的排序规则是ASC:“升序”,即从小到大。ASC可以省略
双重排序
如果score列有相同的数据,要进一步排序,可以继续添加列名。例如,使用ORDER BY score DESC, gender表示先按score列倒序,如果有相同分数的,再按gender列排序:
SELECT id, name, gender, score FROM students ORDER BY score DESC, gender;
4. 分页查询
分页实际上就是从结果集中“截取”出第M~N条记录。这个查询可以通过LIMIT OFFSET 子句实现
SELECT id, name, gender, score
FROM students
ORDER BY score DESC
LIMIT 3 OFFSET 0;
LIMIT 3 OFFSET 0表示,对结果集从0号记录开始,最多取3条。注意SQL记录集的索引从0开始。
如果要查询第2页,那么我们只需要“跳过”头3条记录,也就是对结果集从3号记录开始查询,把OFFSET设定为3
SELECT id, name, gender, score
FROM students
ORDER BY score DESC
LIMIT 3 OFFSET 3;
计算公式
LIMIT总是设定为pageSize;
OFFSET计算公式为pageSize * (pageIndex - 1)
5.聚合查询
通过聚合函数查询叫做聚合查询,比如COUNT(),可以查询所有的个数
常用的聚合函数
统计男生的平均成绩
SELECT AVG(score) average FROM students WHERE gender = 'M'
分组 group by
GROUP BY子句指定了按某个字段分组
6.多表查询
SELECT查询不但可以从一张表查询数据,还可以从多张表同时查询数据。查询多张表的语法是:
SELECT * FROM <表1> <表2>。
7.连接查询
连接查询是另一种类型的多表查询。连接查询对多个表进行JOIN运算,简单地说,就是先确定一个主表作为结果集,然后,把其他表的行有选择性地“连接”在主表结果集上
INNER JOIN
注意INNER JOIN查询的写法是:
先确定主表,仍然使用FROM <表1>的语法; 再确定需要连接的表,使用INNER JOIN <表2>的语法; 然后确定连接条件,使用ON
<条件…>,这里的条件是s.class_id =
c.id,表示students表的class_id列与classes表的id列相同的行需要连接; 可选:加上WHERE子句、ORDER
BY等子句
INNER JOIN, RIGHT JOIN ,LEFT JOIN 的区别
总结
JOIN查询需要先确定主表,然后把另一个表的数据“附加”到结果集上;
INNER JOIN是最常用的一种JOIN查询,它的语法是SELECT … FROM <表1> INNER JOIN <表2> ON
<条件…>;JOIN查询仍然可以使用WHERE条件和ORDER BY排序
六,修改数据
INSERT:插入新记录;
UPDATE:更新已有记录;
DELETE:删除已有记录
1. INSERT
INSERT INTO <表名> (字段1, 字段2, ...) VALUES (值1, 值2, ...);
INSERT INTO students (class_id, name, gender, score) VALUES (2, '大牛', 'M', 80);
-- 查询并观察结果:
SELECT * FROM students;
2.UPDATE
UPDATE <表名> SET 字段1=值1, 字段2=值2, ... WHERE ...;
UPDATE students SET name='大牛', score=66 WHERE id=1;
-- 查询并观察结果:
SELECT * FROM students WHERE id=1;
要特别小心的是,UPDATE语句可以没有WHERE条件,会使得整个表被更新,这是比较危险的操作
3.DELETE
DELETE FROM <表名> WHERE ...;
DELETE FROM students WHERE id=1;
-- 查询并观察结果:
SELECT * FROM students;
七,管理MYSQL
1.SHOW DATABASES;
表示列出所有数据库
其中,information_schema、mysql、performance_schema和sys是系统库,不要去改动它们。其他的是用户创建的数据库。
2.CREATE DATEBASE
CREATE DATABASE test用于创建数据库
3.DROP DATABASE test
DROP DATABASE用于删除数据库
4.SHOW TABLES
表示列出数据库下所有的表
DESC 查看表结构
DESC students
表示查看students表结构
5.SHOW CREATE TABLE
SHOW CREATE TABLE students
表示查看创建表students的结构
6.DROP TABLE
删除表DROP TABLE students
7.增加列
ALTER TABLE students ADD COLUMN birth VARCHAR(10) NOT NULL;
8.删除列
ALTER TABLE students DROP COLUMN birthday
9.修改列
ALTER TABLE students CHANGE COLUMN birth birthday VARCHAR(20) NOT NULL
10.退出mysql
EXIT 表示断开与server 的连接
11.插入或者替换
REPLACE INTO students (id, class_id, name, gender, score) VALUES (1, 1, '小明', 'F', 99);
12.插入或更新
INSERT INTO ... ON DUPLICATE KEY UPDATE ...
INSERT INTO students (id, class_id, name, gender, score) VALUES (1, 1, '小明', 'F', 99) ON DUPLICATE KEY UPDATE name='小明', gender='F', score=99;
13.插入或更新
如果我们希望插入一条新记录(INSERT),但如果记录已经存在,就啥事也不干直接忽略,此时,可以使用INSERT IGNORE INTO …语句:
INSERT IGNORE INTO students (id, class_id, name, gender, score) VALUES (1, 1, '小明', 'F', 99);
14.快照
如果想要对一个表进行快照,即复制一份当前表的数据到一个新表,可以结合CREATE TABLE和SELECT
CREATE TABLE students_of_class1 SELECT * FROM students WHERE class_id=1;
八,事务
什么是事务
把多条语句作为一个整体进行操作的功能,被称为数据库事务,数据库事务可以确保该事务范围内的所有操作都可以全部成功或者全部失败。如果事务失败,那么效果就和没有执行这些SQL一样,不会对数据库数据有任何改动
系统自动执行的叫做隐式事务,要手动把多条SQL语句作为一个事务执行,使用BEGIN开启一个事务,使用COMMIT提交一个事务,这种事务被称为显式事务
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;
回滚事务 ROLLBACK
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
ROLLBACK;
隔离级别
Read Uncommitted
隔离级别最低的一种事务级别。在这种隔离级别下,一个事务会读到另一个事务更新后但未提交的数据,如果另一个事务回滚,那么当前事务读到的数据就是脏数据,这就是脏读(Dirty Read)
Read Committed
一个事务可能会遇到不可重复读(Non Repeatable Read)的问题。
不可重复读是指,在一个事务内,多次读同一数据,在这个事务还没有结束时,如果另一个事务恰好修改了这个数据,那么,在第一个事务中,两次读取的数据就可能不一致。
Repeatable Read(默认隔离级别)
在这种隔离级别下,一个事务可能会遇到幻读(Phantom Read)的问题。
幻读是指,在一个事务中,第一次查询某条记录,发现没有,但是,当试图更新这条不存在的记录时,竟然能成功,并且,再次读取同一条记录,它就神奇地出现了
Serializable
是最严格的隔离级别。在Serializable隔离级别下,所有事务按照次序依次执行,因此,脏读、不可重复读、幻读都不会出现。
虽然Serializable隔离级别下的事务具有最高的安全性,但是,由于事务是串行执行,所以效率会大大下降,应用程序的性能会急剧降低。如果没有特别重要的情景,一般都不会使用Serializable隔离级别。
以上是关于一篇搞懂SQL的主要内容,如果未能解决你的问题,请参考以下文章