3.3 SQL查询的基本结构
SQL查询的基本结构由三个子句构成:select、from和where。
查询的输入是在from子句中列出的关系,在这些关系上进行where和select子句中指定的运算,然后产生一个关系作为结果。
我们通过例子介绍SQL的语法,后面再描述SQL查询的通用结构。
3.3.1 单关系查询
instructor关系模式定义如下
instructor(ID,name,dept_name,salary)
找出所有教师的名字
我们考虑使用大学数据库例子的一个简单查询:“找出所有教师的名字”。教师的名字可以在instructor关系中找到,因此我们把instructor关系放到from子句中。教师的名字出现在name属性中,因此我们把name放到select子句中。
1 | select name from instructor; |
其结果是由属性名为name的单个属性构成的关系。
找出所有教师所在的系名
现在考虑另一个查询:”找出所有教师所在的系名”,此查询可写为:
1 | select dept_name from instructor; |
因为一个系有多个教师,所以在instructor关系中,一个系的名称可以出现不止一次。
在关系模型的形式化数学定义中,关系是一个集合。因此,重复的元组不会出现在关系中。
在实践中,去除重复是相当费时的,所以SQL允许在关系以及SQL表达式结果中出现重复。因此,在上述SQL查询中,每个系名在instructor关系的元组中每出现一次,都会在查询结果中列出一次。
去除查询结果中的重复 select distinct
有时候我们想要强行删除重复,可在select后加入distinct关键词。如果我们想去除重复,可将上述查询重写为:
1 | select distinct dept_name from instructor; |
在上述查询的结果中,每个系名最多只出现一次。
保留查询结果中的重复 select all
SQL允许我们使用关键词all来显式指明不去除重复:
1 | select all dept_name from instructor; |
不过SQL是默认保留重复元组的,所以all关键词可以省略。
算术运算符
select子句还可带含有加(+)、减(-)、乘(*)、除(/)运算符的算术表达式。
算术运算符可用于常数或者元组的属性
算术运算符的运算对象可以是常数或元组的属性。例如,查询语句:
1 | select ID, name, dept_name, salary*1.1 from instructor; |
将返回一个与instructor一样的关系,只是属性salary的值是原来的1.1倍。这显示了如果我们给每位教师增长10%的工资的结果。注意这并不导致对instructor关系的任何改变。
特定类型的算术函数
SQL还提供了一些特殊数据类型,如各种形式的日期类型,并允许一些作用于这些类型上的算术函数。我们在4.5.1节进一步讨论这个问题。
where子句
where子句允许我们只选出那些在from子句的结果关系中满足特定谓词的元组。
找出所有在Computer Science系并且工资超过70000美元的教师的姓名
考虑查询”找出所有在Computer Science系并且工资超过70000美元的教师的姓名”,该查询用SQL可以写为:
1 | select name from instructor |
逻辑连词
SQL允许在where子句中使用逻辑连词and、or和not。
逻辑连词的运算对象是包含比较运算符的表达式
逻辑连词`运算对象可以是包含比较运算符<、<=、>、>=、=和<>的表达式。SQL允许我们使用比较运算符来比较字符串、算术表达式以及特殊类型,如日期类型。
在本章的后面,我们将研究where子句谓词的其他特征。
大学数据库模式
classroom(building,room_number,capacity)department(dept_name,building,budget)course(course_id,title,dept_name,credits)instructor(ID,name,dept_name,salary)section(course_id,sec_id,semester,year,building,room_number,time_slot_id)teaches(ID,course_id,sec_id,semester,year)student(ID,name,dept_name,tot_cred)takes(ID,course_id,sec_id,semester,year,grade)advisor(s_ID,i_ID)time_slot(time_slot_id,day,start_time,end_time)prereq(course_id,prereq_id)