SELECT: FROM¶
说明¶
为SELECT或UPDATE语句声明数据源
语法¶
select_from ::=
table_reference ::=
table_ref_table ::=
table_ref_query ::=
table_ref_join ::=
joinop ::=
参数¶
table_reference
查询的一个数据源,可以为表、视图、函数调用、子查询或表联接的结果。
table_name
基本表或视图的名称。
joinop
联接操作类型。神通数据库中支持的联接操作类型有CROSS JOIN, JOIN, [NATURAL] LEFT [OUTER] JOIN, [NATURAL] RIGHT [OUTER] JOIN, [NARUAL] FULL [OUTER] JOIN, [NATURAL] INNER JOIN等多种类型,不指定类型的JOIN相当于INNER JOIN。
join_condition
联接条件。类似于WHERE子句中的查询条件,但只能使用参与联接的两个表中的字段。
join_column_list
联接字段列表。列表中的字段必须是参与联接的两个表中的共同字段,指定联接字段列表的作用相当于进行在这些字段上的等值联接条件,即TABLE1 joinop TABLE2 USING(A, B)相当于TABLE1 joinop TABLE2 ON TABLE1.A = TABLE2.A AND TABLE1.B = TABLE2.B。
t_alias
表的别名。
c_alias_list
列别名列表。
注解
FROM子句为SELECT语句声明了一个到多个数据源,其输出是各个数据源的输出进行笛卡尔积并加以联接条件进行筛选之后的结果。每个数据源可以是以下三种类型之一:
- 一个基本表或视图;
一个用圆括号括起的子查询;
一个联接表,即多个数据源进行联接之后的结果。
一个查询中最多可以使用32张表,是这针对于视图展开之后的结果而言的,即若FROM子句中的某个数据源为视图,而视图的定义中又涉及到多张基本表,则认为该查询也使用了多张表。
神通数据库中支持的联接类型包括笛卡尔积联接(CROSS JOIN),内联接(INNER JOIN或JOIN),外联接(包括左外联接LEFT OUTER JOIN, 右外联接RIGHT OUTER JOIN, 全外联接FULL OUTER JOIN)等多种类型。除CROSS JOIN这外的所有联接类型又可以通过在前面加上NATURAL关键字成为自然联接。
CROSS JOIN和不带联接条件的INNER JOIN/JOIN的作用相同,都是输出两个数据源进行笛卡尔积的结果。
LEFT OUTER JOIN除了返回所有联接行,还返回那些在右手边数据源中没有匹配行的左手边数据源行与空值右手边行联接的结果(即这部分联接结果中那些只来自于右手边数据源的属性都为NULL);相反,RIGHT OUTER JOIN除了返回所有联接行,还返回那些在左手边数据源中没有匹配行的右手边数据源行与空值左手边行联接的结果(即这部分联接结果中那些只来自于左手边数据源的属性都为NULL)。FULL OUTER JOIN返回所有联接行,加上所有未匹配的左手边行(只来自于右手边数据源的属性用NULL值填充),再加上所有未匹配的右手边行(只来自于左手边数据源的属性用NULL值填充)。
除了CROSS JOIN,其它的联接类型都需要指定联接条件,可以使用以下三种方式之一来指定:
- 使用ON join_condition,这是最灵活的方式,用户不但可以指定进行等值联接(如ON A = B),还可以指定使用其它的比较操作(如ON A < B, ON A LIKE B)进行联接,甚至是表达式(如ON A + 1 = B)。
使用USING join_column_list,这相当于指定了join_column_list中的所有字段上的等值条件,如USING A, B相当于指定了ON LEFT_TABLE.A = RIGHT_TABLE.A AND LEFT_TABLE.B = RIGHT_TABLE.B,因此要求join_column_list中的字段为两个数据源中的共同字段。
使用NATURAL关键字,这相当于为两个数据源中的所有共同字段指定了等值联接条件,如STUDENT NATURAL JOIN ELECT相当于STUDENT JOIN EELCT ON STUDENT.SNO = ELECT.SNO。使用NATURAL关键字的联接又称为自然联接。
示例¶
示例1: 自然联接
-- 清理环境
DROP TABLE tab1 CASCADE;
DROP TABLE tab2 CASCADE;
-- 创建表并插入数据
CREATE TABLE tab1 (a INT, b INT, c INT);
INSERT INTO tab1 VALUES(1, 10, 900);
INSERT INTO tab1 VALUES(2, 20, 500);
INSERT INTO tab1 VALUES(2, NULL, 200);
INSERT INTO tab1 VALUES(3, 30, 1000);
INSERT INTO tab1 VALUES(3, 40, 800);
INSERT INTO tab1 VALUES(3, 10, 600);
SELECT * FROM tab1 ORDER BY a, b, c;
A(int) |B(int) |C(int) |
------------------------------------
1 |10 |900 |
------------------------------------
2 |20 |500 |
------------------------------------
2 |null |200 |
------------------------------------
3 |10 |600 |
------------------------------------
3 |30 |1000 |
------------------------------------
3 |40 |800 |
总数目:6
CREATE TABLE tab2 (c INT, d VARCHAR(20));
INSERT INTO tab2 VALUES(900, 'aa');
INSERT INTO tab2 VALUES(500, 'a');
INSERT INTO tab2 VALUES(200, 'aaa');
INSERT INTO tab2 VALUES(1000, 'aaaaa');
INSERT INTO tab2 VALUES(300, 'a');
SELECT * FROM tab2 ORDER BY c, d;
C(int) |D(varchar) |
----------------------------
200 |aaa |
----------------------------
300 |a |
----------------------------
500 |a |
----------------------------
900 |aa |
----------------------------
1000 |aaaaa |
总数目:5
-- 自然连接
SELECT a, b, c, d FROM tab1 NATURAL JOIN tab2 ORDER BY a, b, c, d;
A(int) |B(int) |C(int) |D(varchar) |
----------------------------------------------------
1 |10 |900 |aa |
----------------------------------------------------
2 |20 |500 |a |
----------------------------------------------------
2 |null |200 |aaa |
----------------------------------------------------
3 |30 |1000 |aaaaa |
总数目:4
-- 删除表
DROP TABLE tab2;
DROP TABLE tab1;
示例2: 外联接
-- 清理环境
DROP TABLE tab1 CASCADE;
DROP TABLE tab2 CASCADE;
-- 创建表并插入数据
CREATE TABLE tab1 (a INT, b INT, c INT);
INSERT INTO tab1 VALUES(1, 10, 900);
INSERT INTO tab1 VALUES(2, 20, 500);
INSERT INTO tab1 VALUES(2, NULL, 200);
INSERT INTO tab1 VALUES(3, 30, 1000);
INSERT INTO tab1 VALUES(3, 40, 800);
INSERT INTO tab1 VALUES(3, 10, 600);
SELECT * FROM tab1 ORDER BY a, b, c;
A(int) |B(int) |C(int) |
------------------------------------
1 |10 |900 |
------------------------------------
2 |20 |500 |
------------------------------------
2 |null |200 |
------------------------------------
3 |10 |600 |
------------------------------------
3 |30 |1000 |
------------------------------------
3 |40 |800 |
总数目:6
CREATE TABLE tab2 (c INT, d VARCHAR(20));
INSERT INTO tab2 VALUES(900, 'aa');
INSERT INTO tab2 VALUES(500, 'a');
INSERT INTO tab2 VALUES(200, 'aaa');
INSERT INTO tab2 VALUES(1000, 'aaaaa');
INSERT INTO tab2 VALUES(300, 'a');
SELECT * FROM tab2 ORDER BY c, d;
C(int) |D(varchar) |
----------------------------
200 |aaa |
----------------------------
300 |a |
----------------------------
500 |a |
----------------------------
900 |aa |
----------------------------
1000 |aaaaa |
总数目:5
-- 左外连接
SELECT a, b, tab1.c as c1, tab2.c as c2, d FROM tab1 LEFT OUTER JOIN tab2 ON tab1.c = tab2.c ORDER BY a, b, c1, c2, d;
A(int) |B(int) |C1(int) |C2(int) |D(varchar) |
------------------------------------------------------------------
1 |10 |900 |900 |aa |
------------------------------------------------------------------
2 |20 |500 |500 |a |
------------------------------------------------------------------
2 |null |200 |200 |aaa |
------------------------------------------------------------------
3 |10 |600 |null |null |
------------------------------------------------------------------
3 |30 |1000 |1000 |aaaaa |
------------------------------------------------------------------
3 |40 |800 |null |null |
总数目:6
-- 右外连接
-- tab1 与 tab2 互换位置,达到与上面左外连接相同效果
SELECT a, b, tab1.c as c1, tab2.c as c2, d FROM tab2 RIGHT OUTER JOIN tab1 ON tab1.c = tab2.c ORDER BY a, b, c1, c2, d;
A(int) |B(int) |C1(int) |C2(int) |D(varchar) |
------------------------------------------------------------------
1 |10 |900 |900 |aa |
------------------------------------------------------------------
2 |20 |500 |500 |a |
------------------------------------------------------------------
2 |null |200 |200 |aaa |
------------------------------------------------------------------
3 |10 |600 |null |null |
------------------------------------------------------------------
3 |30 |1000 |1000 |aaaaa |
------------------------------------------------------------------
3 |40 |800 |null |null |
总数目:6
-- 删除表
DROP TABLE tab2;
DROP TABLE tab1;