1. 了解SQL
数据库(database)
数据库管理系统(DBMS)
表(table):存储的数据是同一类型的数据或清单
表名在同一数据库中唯一。
模式、架构(schema):数据库和表的布局及特性的信息
列(column):表中的一个字段。所有表都是由一个或多个列组成
行(row):表中的一个记录(record)
主键(primary key):一列(或几列),其值能够唯一表示表中的每一行。
可以做主键的列要满足:
- 任意两行都不具有相同的主键值
- 每一行都必须具有一个主键值(不能为NULL)
- 主键列中的值不允许修改和更新
- 主键值不能重用(如果某行删除也不可以把其主键赋给其他行)
- 如果有多列主键,则列值组合必须唯一。
SQL(Structured Query Language:结构化查询语言)
SQL语句不区分大小写,存在关键字(keyword)
假设存在一个表(testTable)
name | age | id | sex |
---|---|---|---|
张三 | 18 | 1 | 男 |
李四 | 19 | 2 | 男 |
...... | ....... | ...... | ...... |
2. 检索数据
SELECT语句
简单使用
/* SELECT 列名
FROM 表名; */ #列名可以为多个,用英文逗号隔开
SELECT *
FROM testTable; # 使用 * 代表获取表中的所有列
检索不同的值
使用DISTINCT
SELECT DISTINCT 列名
FROM 表名;
# 若是检索多列的不同值,其检索结果为组合和的不同
限制检索结果(不同的数据库的该语法不同)
MySQL使用的是LIMIT
、OFFSET
# 只显示前五行
SELECT 列名 # 同样是支持多列检索
FROM 表名
LIMIT 5;
# 从第2行开始接着显示5行
SELECT 列名
FROM 表名
LIMIT 5 OFFSET 1; # 是从第 0 行开始检索的,因此 OFFSET后是 2 - 1
# 简单写法
SELECT 列名
FROM 表名
LIMIT 1,5; # 注意:逗号前面的是OFFSET的值,后面是LIMIT的值!!!
注释方式
单行注释支持 #
(部分DBMS不支持)、--
,多行注释使用/* */
3. 排序检索数据
子句(clause):SQL语句有子句构成,有些子句是必须的,有些则是可选的。
明确地排序可以使用ORDER BY
子句
ORDER BY
子句只能放在SQL语句的最后面
按列名字母顺序排列
# 单列 SELECT 列名 FROM 表名 ORDER BY 列名; # 同样的也是支持多列的 SELECT 列名a,列名b,列名c FROM 表名 ORDER BY 列名b, 列名c; # 先按字母顺序排列列表b,如果列表 b中存在相同的,就按照字母排列列表 c # 如果列表 b 中的值都是唯一的,就不会再按照列表 c中的值去排序了。
按列位置排序
SELECT 列名a,列名b,列名c FROM 表名 ORDER BY 2,3; # 效果同上,只不过是省略了列名
指定排序方向
默认的是从A ~ Z
的升序排序,可以使用关键字DESC
进行Z ~ A
降序排序(ASC
是升序,可省略)SELECT 列名a, 列名b, 列名c FROM 表名 ORDER BY 2,3 DESC; # 在某最后加上 DESC 关键字即可 # DESC只对其前面的那个一个起到作用 SELECT 列名a, 列名b, 列名c FROM 表名 ORDER BY 2 DESC, 3; # 此时是对第 2 列的进行降序排列,若有相同,再对第 3 列进行升序排列
若想对多列进行降序排列,则需要在其后各加上一个
DESC
关键字
4. 过滤数据
使用WHERE
子句,只需要指出 搜索条件(search criteria)
- WHERE子句操作符
操作符 | 说明 | 操作符 | 说明 |
---|---|---|---|
= | 等于 | > | 大于 |
<> 和 != | 不等于 | < | 小于 |
>= 和 !< | 大于等于和不小于 | <= 和 !> | 小于等于和不大于 |
BETWEEN ? AND ? | 在指定的两个值之间 | IS NULL | 为 NULL 值 |
检查单个值
SELECT 列名a, 列名b FROM 表名 WHERE 搜索条件; # 举个栗子 # (假设有一个数据库,其中一个表名为 testTable) SELECT name, age FROM testTable WHERE age < 10; # 列出 age 小于 10的name 和 age # 再举个栗子 SELECT name, age FROM testTable WHERE name = 'zhangsan'; # 列出 name是张三的 name和age.注意,字符串类型要用 引号 来限定字符串。
检查值的范围
#使用 BETWEEN AND # 举个栗子 SELECT name, age FROM testTable WHERE age BETWEEN 5 AND 10; # 列出 age值在5 和 10 之间的 name 和age。[5,10]
空值检查
# 不能使用 = NULL,这是错误的,要使用 IS NULL # 举个栗子 SELECT name FROM testTable WHERE age IS NULL; # 列出 age 是 NULL 值的 name。
5.高级数据过滤
SQL允许使用多个 WHERE 子句,即使用AND子句
或OR子句
。(AND
和OR
是逻辑操作符)
AND操作符
SELECT 列名1,列名2,列名3 FROM 表名 WHERE 条件1 AND 条件2; # 举个栗子 SELECT name, age, sex FROM testTable WHERE sex = '男' AND age < 18; # 列出性别男,且小于18岁的name,age,sex;
OR操作符
SELECT 列名1,列名2,列名3 FROM 表名 WHERE 条件1 OR 条件2; # 同上,只需满足其中一个条件就可
注意:
AND
的优先级高于OR
SELECT name,age FROM testTable WHERE 条件1 OR 条件2 AND 条件3; # 其相当于 条件1 OR (条件2 AND 条件3); # 这是因为 AND 的优先级高于 OR,同时存在 AND 和 OR是,先对 AND进行处理
IN操作符
IN操作符是用来指定范围的,在范围中的每个条件进行匹配。
实际上,
IN
和OR
具有相同功能,书写更简便。# 对于下面的 WHERE (age = 10 OR age = 20) AND sex = '男'; # 可以使用 WHERE age IN (10,20) AND sex = '男'; # 来实现。
IN
的执行速度更快IN
的最大优点是可以包含其他的SELECT
语句SELECT 列名1,列名2 FROM 表名 WHERE 列名 IN (条件1,条件2); # 举个栗子 SELECT name,age FROM testTable WHERE age IN (18,19); # 列出年龄为18 和 19岁的。
NOT
操作符
只对NOT后紧接着的那个条件起作用。SELECT 列名1,列名2 FROM 表名 WHERE NOT 条件; # 举个栗子 SELECT name,age FROM testTable WHERE NOT age=18; # 列出age 不是 18的。
NOT
还可以否定IN
、BETWEEN
等子句,比如WHERE NOT age IN (15,20); # 年龄不是15 或不是 20的。
6. 使用通配符进行过滤
要想使用通配符,需要使用到
LIKE
操作符。准确来说,
LIKE
是谓词而不是操作符 (没看懂~唔)通配符只能用于搜索文本字段(字符串),非文本数据类型字段不能使用通配符嗷~。
是否区分大小写与DBMS的不同及其配置有关。
(通配符搜索
好用
,但最好少用
,因为速度慢)常用的通配符
百分号(%)通配符
# % 表示任何字符出现任意次数 # 举个栗子:检索 abc 开头的字符串 WHERE name LIKE 'abc%'; # 检索xyz结尾的字符串 WHERE name LIKE '%xyz'; # 检索包含 efg的字符串 WHERE name LIKE '%efg%';
注意:字符串后面可能跟有若干个空格
比如,如果某列有 50 个字符,但存储的文本是 abcdefgh(8个字符),填满则还需要42个空格,要想检索
a%h
是无法成功的,只有使用a%h%
这样,才可以匹配的到。【还有方法就是使用函数来去除掉空格】下划线(\_)通配符
# _ 表示 单个 任意字符 # 举个栗子,检索flag WHERE str LIKE 'fl_g';
方括号([])通配符。【MySQL等不支持,SQL Server支持】
# 使用方括号来指定一个字符集 [] # 举个栗子:检索flag WHERE str LIKE 'fl[abcdef]g';
7. 用正则表达式进行搜索
上一节中的
LIKE
是配合通配符使用的,而正则表达式REGEXP
更加的强大# 举个栗子 SELECT prod_name FROM products WHERE prod_name REGEXP '1000'; # 这样在该数据库里是有结果的 # 如果使用 LIKE,如WHERE prod_name LIKE '1000';是没有结果的!!! 原因呢?
LIKE 和 REGEXP 是有很重要的区别,
LIKE
是对整个列的匹配,而REGEXP
是在列的值内进行匹配。MySQL 的正则表达式匹配默认是不区分大小写的,若要区分,可以使用
BINARY
,使用方法 WHERE prod_name REGEXP BINARY 'AbCd'# OR匹配 WHERE prod_name REGEXP 'a|b|c' # 相当于匹配到 a 或 b 或 c #匹配几个字符之一:要用到 [] WHERE prod_name REGEXP '[123] Ton' # 可以匹配到 1 Ton、2 ton 等等 # 匹配范围 如 [1-5] :为匹配 1-5之间的任意一个数字 # 匹配特殊字符,如 .(点),?等,需要用到转义字符(\\)==> 转义点号 \\.,转义反斜杠==> \\\
MySQL中的转义字符(
\\
),不同于C、Python等语言中的单个反斜杠,这是因为MySQL自己要解释一个,正则表达式库要解释另一个除此之外,还有一些好用的匹配字符类,如
[:alnum:]
相当于[a-zA-Z0-9]
,[:digit:]
相当于[0-9]
匹配多个实例的,如
* + ? {n} {n,} {n,m}
,与其他语言的正则表达式用法几乎一致。定位元字符:
^ 文本的开始
,$ 文本的结尾
[[:<:]] 词的开始
,[[:<:]] 词的结尾
^
在[]
内,是否定该集合,如:[^123]
;在[]
外是指文本的开头,如^[abc]
8.创建计算字段
- 字段(filed):基本与列的意思相同...
SQL语句内即可完成许多格式、数据上的工作,在数据服务器中完成这些操作会比在客户端中快得多。
对于不同的DBMS,其语法是有差异的。
SQL Server 支持使用
+
,DB2,Oracle,PostgreSQL使用||
。而MySQL,MariaDB则要使用到函数
Concat()
AS
:关键字可以用来取别名CONCAT()
:MySQL和MariaDB中用来拼接字段的函数TRIM()
:函数用来去除字符串两端的空格LTRIM()
、RTRIM()
:分别用来去除字符串左、右两边的空格拼接字段
# 举个栗子 拼接字段 SELECT CONCAT(vend_name, '(', vend_country, ')') FROM Vendors; # --------------- # 栗子 去除空格 SELECT TRIM(vend_name),TRIM(vend_country) FROM Vendors; # ----------------- # 取别名 AS SELECT vend_name AS vname, vend_country AS vcountry FROM Vendors; # 别名和原名有同样的作用
执行算术计算
# 没什么特别的,就是在SELECT 后面的子句里使用了运算符号 # 举个栗子 SELECT prod_id, quantity, item_price, quantity*item_price AS total_price FROM OrderItem;
9. 使用函数处理数据
函数有很多
CONCAT() 拼接 LEFT() Length() Locate() Lower() LTrim() Right() Soundex()
**日期和时间处理函数**
**数值处理函数**:Abs、Cos、Exp(指数)、Mod(取余)、Pi、Rand、Sin、Sqrt(平方根)、Tan
## 10 汇总数据
**SQL聚集函数**
| 函数 | 说明 |
| :-----: | :--------------: |
| AVG() | 返回某列的平均值 |
| COUNT() | 返回某列的行数 |
| MAX() | 返回某列的最大值 |
| MIN() | 返回某列的最小值 |
| SUM() | 返回某列值的和 |
***语法***:函数名(列名),如`SELECT AVG(prod_price)`
> AVG()忽略列值的 NULL行
>
> COUNT(),如果是COUNT(列名),就会忽略NULL行,如果是COUNT(\*),就不会忽略NULL行
>
> MAX():忽略NULL行,如果是文本,就返回相应顺序的最后一行
>
> MIN():与MAX相反。
>
> SUM():忽略NULL行
>
> `DISTINCT`可以和SUM()、AVG()搭配使用
>
> ```mysql
> SELECT AVG(DISTINCT prod_price) AS avg_price
> ```