基于 MySQL 的数据库实践(更名运算)
考虑下面的查询查询。
select name, course_id
from instructor, teaches
where instructor.ID = teaches.ID;
它的结果是一个具有属性 name,course_id 的关系,结果中的属性名来自 from 子句中关系的属性名。但是这样的手段会在更复杂的情况下遇到问题,① from 子句的两个关系中可能存在同名属性,这样结果里就会出现重复的属性名 ②如果我们在 select 子句中使用算术表达式,那么结果属性就没有名字 ③我们希望使用新的名称来取代原来的属性名。
基于以上原因,SQL 提供了一个重命名(rename)结果关系中的属性的方法,即使用 as 子句。
old-name as new-name
as 子句即可以出现在 select 子句中,也可以出现在 where 子句中。
例如,我们想用名字 instructor_name 来代替属性名 name,则可以重写上面的查询如下。
mysql> select name as instructor_name, course_id
-> from instructor, teaches
-> where instructor.ID = teaches.ID;
+-----------------+-----------+
| instructor_name | course_id |
+-----------------+-----------+
| Srinivasan | CS-101 |
| Srinivasan | CS-315 |
| Srinivasan | CS-347 |
| Wu | FIN-201 |
| Mozart | MU-199 |
| Einstein | PHY-101 |
| El Said | HIS-351 |
| Katz | CS-101 |
| Katz | CS-319 |
| Crick | BIO-101 |
| Crick | BIO-301 |
| Brandt | CS-190 |
| Brandt | CS-190 |
| Brandt | CS-319 |
| Kim | EE-181 |
+-----------------+-----------+
15 rows in set (0.01 sec)
as 子句在重命名关系时非常管用,重命名关系的原因是把一个长的关系名替换成一个短的关系名,这样在查询的其他地方使用起来就很方便。
重写查询,对于大学中所有讲授课程的教师,列出他们的姓名以及所讲述的所有课程标识。
mysql> select T.name, S.course_id
-> from instructor as T, teaches as S
-> where T.ID = S.ID;
+------------+-----------+
| name | course_id |
+------------+-----------+
| Srinivasan | CS-101 |
| Srinivasan | CS-315 |
| Srinivasan | CS-347 |
| Wu | FIN-201 |
| Mozart | MU-199 |
| Einstein | PHY-101 |
| El Said | HIS-351 |
| Katz | CS-101 |
| Katz | CS-319 |
| Crick | BIO-101 |
| Crick | BIO-301 |
| Brandt | CS-190 |
| Brandt | CS-190 |
| Brandt | CS-319 |
| Kim | EE-181 |
+------------+-----------+
15 rows in set (0.00 sec)
重命名一个关系的另一个重要原因是为了适用于需要比较同一个关系中的元组的情况。在这种情况下,我们需要把一个关系跟它自身做笛卡尔积运算,如果不重命名,则不可能把一个元组与其他元组区分开来。
考虑查询,找出满足以下条件的所有教师的姓名,他们的工资至少比 Biology 系的某一个教师的工资要高。
mysql> select distinct T.name
-> from instructor as T, instructor as S
-> where T.salary > S.salary and S.dept_name = 'Biology';
+----------+
| name |
+----------+
| Wu |
| Einstein |
| Gold |
| Katz |
| Singh |
| Brandt |
| Kim |
+----------+
7 rows in set (0.01 sec)
注意上面的查询中不能使用 instructor.salary 这样的写法,因为指称不明。在上面的查询中,T 和 S 可以被认为是 instructor 关系的两份拷贝,但更准确地说是被声明为 instructor 关系的别名(alias)。类似于 T 和 S 这样被用来重命名关系的标识符在 SQL 标准中被称作相关名称(correlation name),但通常也被称作表别名(table alias)或相关变量(correlation variable)或元组变量(tuple variable)。
上述查询可以用更好的方式表达,找出工资比 Biology 系教师的最低工资高的所有教师的姓名,我们使用前一种表达式因为它更符合我们现在学到的 SQL 语法,但在后面的实践中将看到这种表达也可以用 SQL 语法直观的表示。