学习SQL的材料是《SQL必知必会》这本小册子,小册子浓缩了SQL的精华,很适合从未接触过SQL的初学者学习。标题中的“番茄”指的是番茄工作时间,不过我的单个番茄工作时间为45分钟,阅读完册子的核心部分加上做笔记总共花费了13个番茄时间。
一、什么是SQL?
SQL是structured query language(结构化查询语言)的缩写,是一种专门用来与数据库沟通的语言。
SQL优点:
- 几乎所有的DBMS都支持SQL
- 简单易学
- 可以进行非常复杂和高级的数据库操作
四个重要概念
- 表
- 用来存储某种特定类型的数据的结构化清单,存储在表中的数据是相同类型的
- 列
- 表中的一个字段,一个或多个列组成表
- 行
- 表中的一个记录,也即是数据库记录(record)
- 主键(primary key)
- 表的行或列中唯一标识自己的值,如顾客ID、身份证号
二、检索数据-SELECT语句
首先明确要选择什么(select what?),从什么地方(where?)选择;SQL不区分大小写;多条SQL语句必须以(;
)分隔开来。
例如,检索一个列:
1 | select prod_name |
也可以检索多个列:
1 | select prod_id, prod_name, prod_price |
也可以用通配符(*
)来检索所有列
1 | select * |
检索列下面不等的值
1 | select distinct vend_id |
返回特定的行
1 | select top 5 prod_name |
当然,不同的DBMS有不同的语法规则,但是基本的语句往往是可以移植的,复杂的语句就不行。其实SQL很好理解的,看查询语句就跟学习简单得英语语法一样,并且词汇量还不大,转来转去就那么几个关键词。
三、排序检索数据-ORDER BY
按照单个列进行排列
1 | select prod_name |
按照多个列进行排列
1 | select prod_id, prod_price, prod_name |
按位置进行排序
1 | select prod_id, prod_price, prod_name |
按照指定顺序进行排列,SQL默认返回的结果是升序排列,有的时候我们需要返回的结果能够按照降序或者升序来进行排列,在SQL语句中可以通过升序(asc)和降序(desc)语句实现
1 | select prod_id, prod_price, prod_name |
也可以对指定列进行升序或者降序排列
1 | select prod_id, prod_price, prod_name |
四、过滤数据
1. SELECT WHERE
在select语句中,数据根据where子句中指定的搜索条件进行过滤,可以进行单个值、范围值、不匹配值、空值检查。另外还可以通过AND和OR组合多个条件进行过滤,不过AND和OR条件得组合需要用括号分隔加以分组。
1 | select ... |
操作符 | 说明 | 检查 |
---|---|---|
= | 等于 | |
<>或!= | 不等于 | 不匹配检查 |
< | 小于 | |
<= | 小于等于 | |
!< | 不小于 | |
> | 大于 | |
>= | 大于等于 | |
!> | 不大于 | |
between | 在指定的两个值之间 | 范围值检查 |
is null | 为null值 | 空值检查 |
2. NOT和IN操作符
where子句中的NOT操作符有且只有一个功能,那就是否定后面的条件,NOT也从不单独使用
1 | select ... |
IN操作符取一组由逗号分隔、括在圆括号中间的合法值,IN操作符有诸多优点:
- 清楚、直观
- 运行更快
- 可以包含其他SELECT语句
1 | select prod_name, prod_price |
3. 使用通配符(wildcard)过滤
主要介绍三种通配符,搭配where使用可以进行快速搜索,但是不要过多使用
百分号%
通配符
1 | select prod_id, prod_name |
下划线_
通配符的用途与%一样,不过它只能匹配单个字符,而不是多个,如果需要匹配多个则需要多添加一个下划线__
1 | select prod_id, prod_name |
方括号[]
通配符用来指定一个字符集,它必须匹配指定位置的一个字符
1 | # 找出所有J或M开头的结果 |
1 | # 用前缀字符^(脱字号)找出所有J或M开头以外的结果 |
四、计算字段
这里介绍两种SQL语言中计算字段的手段,分别是拼接、算术计算。
首先是拼接,假如表中包含姓名和地址信息,且需要在格式化的名称中列出供应商的名字,
1 | select name + '('+ address + ')' |
输出的结果
1 | zhangsan (hunan) |
我们发现上述返回的结果并不理想,空格和括号并不是我们想要的,如果需要返回的结果没有空格,可以使用SQL的RTRIM()
函数去掉字符串右边的所有空格来完成,同理,LTRIM()
则是去掉字符串左边所有的空格,TRIM()
去掉字符串左右两边所有空格。
1 | select rtrim(name) + '('+ rtrim(address) + ')' |
输出的结果
1 | zhangsan(hunan) |
第二种则是对检索出来的数据进行算术计算,
1 | select prod_id, |
五、处理数据
对一个值或多个值操作
常用的文本处理函数
函数 | 说明 |
---|---|
LEFT() | 返回字符串左边的字符 |
LENGTH() | 返回字符串的长度 |
LOWER() | 将字符串转换为小写 |
LTRIM() | 去掉字符串左边的空格 |
RIGHT() | 返回字符串右边的字符 |
RTRIM() | 去掉字符串右边的空格 |
SOUNDEX() | 返回与字符串发音类似的字符 |
UPPER() | 将字符串转换为大写 |
常用的数值处理函数还有ABS()、EXP()、PI()、SIN()、COS()
等等,上述两种数值处理函数均针对一个数值进行的操作,如果要针对表中的一列进行操作则需要AVG()、COUNT()、SUM()、MAX()、MIN()
等等函数,这几个函数在进行操作时都会忽略空的行(NULL)。值得注意的是COUNT()
函数的用法,COUNT(*)
对表中的行数进行计数,不管表中包含的是空值还是非空值,而COUNT(column)
则只对非空值的行计数。
数据分组
数据分组用到两个语句,分别是GROUP BY
和HAVING
。
①有必要说清楚分组GROUP BY
与排序ORDER BY
的区别,分组是将输出的结果以分组的形式呈现,而排序则是让输出结果按照顺序进行排列,换言之,分组的结果不一定是按照顺序排列的。
②where
和having
的功能也差不多,区别在于where
是在数据分组前进行过滤,而having
是在数据分组后进行过滤的。
六、查询数据
在SQL中,查询数据主要有子查询、内联结、外联结和组合查询等方法。子查询是通过嵌套查询语句来实现的,子查询语句只能返回一个列,不论是可读性还是调试性,子查询都有明显的缺陷,不推荐使用子查询。
相比子查询,另外一种查询方式——联结查询则是一种更方便的查询方法。
联结查询
如果我们手头上有两个表,这两个表中存在相同的列,在多个表中检索出数据则需要通过内联结。
1 | # 创建表与表之间的联结 |
除了内联结之外,SQL中还有外联结、左(右)外联结和全外联结几种模式,这里就不一一讨论了。
组合查询
当查询时需要多个where select
限定语句时,只需在语句之间添加关键字UNION
即可,简单一点理解就是取两个或多个查询结果的交集,所以这就要求where select
返回的结果必须具有相同的格式。
1 | select ... |
六、插入、更新、删除数据
用INSERT
插入数据,不管是插入完整的行,插入行的一部分还是插入某些查询的结果,values值的个数必须与行数要相等。
1 | insert into customers(..,..) |
1 | # 从一个表复制到另一个表 |
更新和删除数据分别用到UPDATE
和DELETE
语句,比如要更新某个客户的电子邮件
1 | # 更新customers表下ID为10003客户的电子邮件 |
用SQL语句删除数据也是很简单的,比如删除掉某一行客户的信息,记住delete从表中删除行,但是并不删除表本身。记住一条重要的原则,使用delete语句的时候一定要配合where子句使用,防止误操作。
1 | delete from customers |
七、创建表
使用CREATE TABLE
语句创建表,创建表的时候必须给出下列信息:
- 表的名字
- 列的名字和定义,用逗号分隔
比如,
1 | create table products |
到此,SQL的基础知识就差不多总结结束了,这篇文章简单介绍了如何检索、排序、过滤数据,以及如何针对数据进行简单操作,可以说十分小白。不过作为一个在写这篇笔记之前几乎没有接触过数据库语言的菜鸟,错误在所难免,本文章不建议给初学者作为学习参考,仅作个人防止遗忘,要学习SQL还是去看看《SQL必知必会》这本小册子吧。