SQL
SQL查询语言概览
SQL数据定义
SQL查询的基本结构
单关系查询
distinct
下面这段语句就能完成一个简单的单关系查询:
SELECT NAME
FROM instructor;
而我们有时候的数据单拿一个属性出来,数据是会大量重复的,比如我们执行下列语句:
SELECT dept_name
FROM instructor;
就会出现大量的重复。
在关系模型的数学定义中,我们不允许关系里有重复的元素。但在实践中,去重是一件非常耗时的事情。因此SQL的实现允许出现重复的数据。
我们也可以加入关键词distinct手动去重:
SELECT DISTINCT dept_name
FROM instructor;
在SQL中默认不去重,但我们也可以显式地表达不去重:
SELECT ALL dept_name
FROM instructor;
这种写法可以,但没必要。只需要知道distinct
即可。
运算符
元组的属性可以使用运算符进行运算:
SELECT ID, NAME, dept_name, salary*1.1
FROM instructor;
它会将所有数据都显示成1.1倍。但实际上仅仅是显示而已,这种操作不会实际影响关系中的数据。
where
它与编程语言中的if十分相像,只不过表达方式稍稍有点区别:
SELECT NAME
FROM instructor
WHERE dept_name = ‘Comp. Sci.‘ AND salary > 70000;
这是它的简单用法,想好好用好得知道where实际的操作是什么,一会会提及。
多关系查询
实现一个简单的多表查询:
SELECT NAME, instructor.dept_name, building
FROM instructor, department
WHERE instructor.`dept_name` = department.`dept_name`;
一个SQL查询的含义
实际上,一个SQL可以被理解成下面三步:
- 先是
from
子句,为列出的关系产生笛卡儿积。 - 在是
where
语句,挑选出符合条件的元祖 - 最后是
select
,输出指定的属性
假如这个多关系查询忘记写where
,会产生一个非常大的无用数据集,因此,在使用多表查询的时候,一定不要忘记写where
。
自然连接
实现一个简单的自然连接:
SELECT NAME, course_id
FROM instructor NATURAL JOIN teaches;
natural join
自然连接只考虑两个关系中都出现的属性上取值相同的元组对。
且对于from
来说,instructor NATURAL JOIN teaches
返回的结果是一个关系。
而自然连接也存在一些问题:很有可能会出现冲突的属性,或者是我们并不希望被合并的属性,被强行合并了:
SELECT NAME, title
FROM instructor NATURAL JOIN teaches, course
WHERE teaches.`course_id` = course.`course_id`;
--------------------------------------------------------------------------------------------------------------
SELECT NAME, title
FROM instructor NATURAL JOIN teaches NATURAL JOIN course;
这两段运行结果看起来是一样的,实际上结果并不相同,因为natural join
合并了我们并不期望合并的属性。
join (…) using (…)
为保留natural join
的优点SQL提供了一种解决方案:
SELECT NAME, title
FROM (instructor NATURAL JOIN teaches) JOIN course USING (course_id);
使用join (…) using (…)
结构,能够自己指定自然连接的属性,就不会出现冲突合并的情况
附加的基本运算
更名运算
实现一个简单的更名例子:
SELECT NAME AS instructor_name, course_id
FROM instructor, teaches
WHERE instructor.`ID` = teaches.`ID`;
它最方便的地方就是可以将长名字变成短名字,同时可以用于区分同关系的。
字符串运算
字符串运算对大小写敏感,它不同于SQL语句。并且SQL库中会有丰富的处理字符串的函数,例如大写,小写,去空格……
在其中,还有一种操作符like
可以完成模糊查询:
- %:匹配任意字符串
- _:匹配任意一个字符串
一个简单的实现例子:
SELECT dept_name
FROM department
WHERE building LIKE ‘%Watson%‘;
有时候我们需要匹配%之类的符号,可以使用escape
定义转义符:
同时也支持not like
寻找不匹配项。
select子句
*
代表所有属性
元组的显示次序
我们可以让结果对次序进行控制。实现一个简单的例子:
SELECT NAME
FROM instructor
WHERE dept_name = ‘Physics‘
ORDER BY NAME;
order by
默认升序,我们可以给他指定顺序。用asc
代表升序,desc
代表降序。
SELECT *
FROM instructor
ORDER BY salary DESC, NAME ASC;
where子句
between and
between and
可以用来表示范围
这段语句:
SELECT NAME
FROM instructor
WHERE salary <= 100000 AND salary >= 90000;
与下面这段查询结果相同:
SELECT NAME
FROM instructor
WHERE salary BETWEEN 90000 AND 100000;
并且可用not between
。
字典序比较
如果我们需要编写这么一段SQL:
SELECT NAME, course_id
FROM instructor, teaches
WHERE instructor.`ID` = teaches.`ID` AND dept_name = ‘Biology‘;
可以被改写成下列形式(按字典序比较):
SELECT NAME, course_id
FROM instructor, teaches
WHERE (instructor.`ID`, dept_name) = (teaches.`ID`, ‘Biology‘);