[转]Oracle DB 使用连接显示多个表中的数据

? 编写SELECT语句,以使用等值联接和非等值联接访问多个表中的数据

? 使用自联接将表联接到自身

? 使用OUTER联接查看通常不满足联接条件的数据

? 生成两个或多个表中所有行的笛卡尔积

? JOIN的类型及其语法

? 自然联接:

– USING子句

– ON子句

? 自联接

? 非等值联接

? OUTER联接:

– LEFT OUTER联接

– RIGHT OUTER联接

– FULL OUTER联接

? 笛卡尔积

– 交叉联接

  • 获取多个表中的数据

有时需要使用多个表中的数据。如两个独立表中的数据:

? 雇员ID 在EMPLOYEES表中。

? 部门ID 在EMPLOYEES和DEPARTMENTS两个表中。

? 部门名称在DEPARTMENTS表中。

要生成该报表,需要将EMPLOYEES表和DEPARTMENTS表链接起来,然后访问这两个表中的数据。

  • 联接类型

符合SQL:1999 标准的联接包括:

? 自然联接:

– NATURAL JOIN子句

– USING子句

– ON子句

? OUTER联接:

– LEFT OUTER JOIN

– RIGHT OUTER JOIN

– FULL OUTER JOIN

? 交叉联接

要联接各个表,可以使用符合SQL:1999 标准的联接语法。

附注

? 在Oracle9i之前的发行版中,该联接语法与美国国家标准协会(ANSI) 的标准不同。

与以前发行版中的Oracle 专用联接语法相比,符合SQL:1999 的联接语法没有任何性能优势。

  • 使用SQL:1999 语法将表联接起来

使用联接可查询多个表中的数据:

SELECT table1.column, table2.column

FROM table1

[NATURAL JOIN table2] |

[JOIN table2 USING (column_name)] |

[JOIN table2 ON (table1.column_name =
table2.column_name)]|

[LEFT|RIGHT|FULL OUTER JOIN table2 ON (table1.column_name =
table2.column_name)]|

[CROSS JOIN table2];

在该语法中:

? table1.column表示从中检索数据的表和列

? NATURAL JOIN根据相同的列名联接两个表

? JOIN table2 USING column_name根据列名执行等值联接

? JOIN table2 ON table1.column_name =
table2.column_name根据ON子句中的条件执行等值联接

? LEFT/RIGHT/FULL OUTER用于执行OUTER联接

? CROSS JOIN用于返回两个表的笛卡尔积

  • 限定不确定的列名

? 使用表前缀可以限定多个表中的列名。

? 使用表前缀可以提高性能。

? 可以使用表别名来代替完整表名前缀。

? 表别名是表的短名称:

– 使SQL 代码变得更短,因而占用更少的内存

? 使用列别名可区分具有相同名称但位于不同表中的列。

联接两个或更多表时,需要使用表名来限定列的名称,以避免混淆。如果不使用表前缀,则SELECT列表中的DEPARTMENT_ID列可能来自DEPARTMENTS表,也可能来自EMPLOYEES表。因此需要添加表前缀来执行查询。如果两个表中没有相同的列名,则无需限定列。但是,使用表前缀可以提高性能,因为这等于告知Oracle
Server 查找这些列的确切位置。

但是,使用表名限定列名可能非常耗时,特别是当表名较长时。可改为使用表别名。就像列别名是列的另一个名称一样,表别名也是表的另一个名称。表别名有助于使SQL
代码变得更短,因而占用更少的内存。

先指定表全名,然后是一个空格,再后面是表别名。例如,EMPLOYEES表的别名可以是e,而DEPARTMENTS表的别名可以是d。

准则

? 表别名的长度最多为30 个字符,但越短越好。

? 如果在FROM子句中使用了某个特定表名的表别名,则必须在整个SELECT语句中使用该表别名代替该表名。

? 表别名应是有意义的名称。

? 表别名仅对当前的SELECT语句有效。

  • 创建自然联接

? NATURAL
JOIN子句以两个表中具有相同名称的所有列为基础

? 它从两个表中选择在所有相匹配列中具有相同值的那些行。

如果名称相同的列具有不同的数据类型,则返回一个错误。

可以根据两个表中具有相匹配的数据类型和名称的那些列,对表执行自动联接。使用NATURAL
JOIN关键字可以完成此操作。

注:只能对两个表中具有相同名称和数据类型的那些列执行联接。如果列的名称相同但数据类型不同,那么NATURAL
JOIN语法将导致产生一个错误。

  • 使用自然联接检索记录

[email protected]> DESC departments

Name                  
                     
         Null?    Type

----------------------------------------------------- --------
------------------------------------

DEPARTMENT_ID                
                     
  NOT NULL NUMBER(4)

DEPARTMENT_NAME              
                     
  NOT NULL VARCHAR2(30)

MANAGER_ID                
                     
              NUMBER(6)

LOCATION_ID                
                     
             NUMBER(4)

[email protected]> DESC locations

Name                  
                     
         Null?    Type

----------------------------------------------------- --------
------------------------------------

LOCATION_ID                
                     
    NOT NULL NUMBER(4)

STREET_ADDRESS              
                     
            VARCHAR2(40)

POSTAL_CODE                
                     
             VARCHAR2(12)

CITY                  
                     
         NOT NULL VARCHAR2(30)

STATE_PROVINCE              
                     
            VARCHAR2(25)

COUNTRY_ID                
                     
              CHAR(2)

 

[email protected]> SELECT department_id,department_name,
location_id, city FROM departments NATURAL JOIN locations

 

DEPARTMENT_ID DEPARTMENT_NAME          
     LOCATION_ID CITY

------------- ------------------------------ -----------
------------------------------

           60 IT    
                     
         1400 Southlake

           50 Shipping  
                     
     1500 South San Francisco

           10 Administration  
                     1700
Seattle

...

28 rows selected.

在示例中,通过LOCATION_ID列将LOCATIONS表和DEPARTMENT表联接起来,LOCATION_ID列是两个表中具有相同名称的唯一列。如果存在其它通用列,联接

也会使用所有这些列。

使用WHERE子句的自然联接

可以使用WHERE子句对自然联接施加其它限制。以下示例将输出行限制为部门ID 等于20 或50 的那些行:

[email protected]> SELECT department_id, department_name,
location_id, city FROM departments NATURAL JOIN locations WHERE department_id IN
(20, 50); 

 

DEPARTMENT_ID DEPARTMENT_NAME          
     LOCATION_ID CITY

------------- ------------------------------ -----------
------------------------------

           20 Marketing  
                     
    1800 Toronto

           50 Shipping  
                     
     1500 South San Francisco

  • 使用USING子句创建联接

? 如果多个列具有相同的名称,但数据类型不匹配,请使用USING子句指定等值联接的列。

? 当有多个列相匹配时,使用USING子句可仅与一列相匹配。

? NATURAL JOIN和USING语句是互相排斥的。

自然联接使用具有匹配的名称和数据类型的所有列来联接表。可以使用USING子句仅指定等值联接应使用的那些列。

  • 联接列名

要确定雇员的部门名称,应将EMPLOYEES表中DEPARTMENT_ID列的值与DEPARTMENTS表中DEPARTMENT_ID列的值进行比较。EMPLOYEES表和

DEPARTMENTS表之间的关系就是等值联接关系,即这两个表中DEPARTMENT_ID列的值必须相等。通常,这种类型的联接涉及到主键和外键补码。

注:等值联接也称为简单联接或内部联接。

  • 使用USING子句检索记录

[email protected]> SELECT employee_id, last_name, location_id,
department_id FROM employees JOIN departments USING (department_id)

 

EMPLOYEE_ID LAST_NAME            
    LOCATION_ID DEPARTMENT_ID

----------- ------------------------- -----------
-------------

        200 Whalen      
                    1700
           10

        201 Hartstein      
                 1800    
       20

...

106 rows selected.

在示例中,由于EMPLOYEES表和DEPARTMENTS表中的DEPARTMENT_ID列已联接起来,因此会显示雇员所在部门的LOCATION_ID。

  • 在USING子句中使用表别名

[email protected]> SELECT l.city, d.department_name FROM locations l JOIN
departments d USING (location_id) WHERE d.location_id = 1400;

SELECT l.city, d.department_name FROM locations l JOIN departments d USING
(location_id) WHERE d.location_id = 1400

*

ERROR at line 1:

ORA-25154: column part of USING clause cannot have qualifier

? 不要对USING子句中使用的列加以限定。

? 如果在SQL
语句的另一个位置使用了同一列,则不要对其设置别名。

使用USING子句进行联接时,不能对USING子句自身中使用的列加以限定。此外,如果在SQL
语句的任何位置使用了该列,则不能对其设置别名。例如,在示例提及的查询中,不能对WHERE子句中的location_id列设置别名,因为在USING子句中已使用该列。

USING子句中引用的那些列不能在SQL 语句的任何位置使用限定词(表名或别名)。

例如,下面的语句是有效的:

[email protected]> SELECT l.city, d.department_name FROM locations l
JOIN departments d USING (location_id) WHERE location_id =
1400; 

 

CITY                
          DEPARTMENT_NAME

------------------------------
------------------------------

Southlake                
     IT

这两个表中通用但未在USING子句中使用的列必须以表别名为前缀,否则会出现“column ambiguously
defined(定义的列含糊不清)”错误。

在下面的语句中,manager_id既在employees表中又在departments表中,如果manager_id不以表别名为前缀,则会收到“column
ambiguously defined(定义的列含糊不清)”错误。

下面的语句是有效的:

[email protected]> SELECT first_name, d.department_name,
d.manager_id FROM employees e JOIN departments d USING (department_id) WHERE
department_id = 50; 

 

FIRST_NAME           DEPARTMENT_NAME
             
 MANAGER_ID

-------------------- ------------------------------
----------

Donald               Shipping
                     
       121

Douglas              Shipping
                     
       121

...

45 rows selected.

  • 使用ON子句创建联接

? 自然联接的基本联接条件是对具有相同名称的所有列进行等值联接。

? 使用ON子句可指定任意条件或指定要联接的列。

? 联接条件独立于其它搜索条件。

? 使用ON子句可使代码易于理解。

使用ON子句可指定联接条件。这样,便可以在WHERE子句中指定独立于任何搜索条件或过滤条件的联接条件。

  • 使用ON子句检索记录

[email protected]> SELECT e.employee_id, e.last_name,
e.department_id, d.department_id, d.location_id 

  2  FROM employees e JOIN departments d ON
(e.department_id = d.department_id); 

 

EMPLOYEE_ID LAST_NAME            
    DEPARTMENT_ID DEPARTMENT_ID LOCATION_ID

----------- ------------------------- ------------- -------------
-----------

        200 Whalen      
                     
  10            10      
 1700

        201 Hartstein      
                     20
           20      
 1800

...

106 rows selected.

在此示例中,EMPLOYEES表和DEPARTMENTS表中的DEPARTMENT_ID列已使用ON子句联接起来。只要EMPLOYEES表中的部门ID
等于DEPARTMENTS表中的部门ID,就返回相应的行。要限定相匹配的column_names,表别名是必需的。还可以使用ON子句来联接名称不相同的列。示例所示的联接列

(e.department_id = d.department_id)两边的圆括号是可选的。因此,即便是ON
e.department_id = d.department_id效果也一样。

  • 使用ON子句创建三向联接

[email protected]> SELECT employee_id, city, department_name FROM
employees e JOIN departments d 

  2  ON d.department_id = e.department_id JOIN
locations l ON d.location_id = l.location_id; 

 

EMPLOYEE_ID CITY              
            DEPARTMENT_NAME

----------- ------------------------------
------------------------------

        100 Seattle      
               
 Executive

        101 Seattle      
               
 Executive

        102 Seattle      
               
 Executive

...

 

106 rows selected.

三向联接是指三个表的联接。在符合SQL:1999 的语法中,从左至右执行联接。这样,要执行的第一个联接是EMPLOYEES JOIN
DEPARTMENTS。第一个联接条件可以引用EMPLOYEES和DEPARTMENTS中的列,但不能引用LOCATIONS中的列。第二个联接条件可以引用全部三个表中的列。

注:示例也可以使用USING子句实现:

[email protected]> SELECT e.employee_id, l.city, d.department_name
FROM employees e JOIN departments d USING (department_id) JOIN locations l USING
(location_id) 

  2  ;

 

EMPLOYEE_ID CITY              
            DEPARTMENT_NAME

----------- ------------------------------
------------------------------

        100 Seattle      
               
 Executive

        101 Seattle      
               
 Executive

        102 Seattle      
               
 Executive

...

 

106 rows selected.

  • 对联接应用附加条件

使用AND子句或WHERE子句可应用附加条件:

SELECT e.employee_id, e.last_name,
e.department_id, 

d.department_id, d.location_id 

FROM employees e JOIN departments d 

ON (e.department_id = d.department_id) 

AND e.manager_id = 149 ; 

SELECT e.employee_id, e.last_name,
e.department_id, 

d.department_id, d.location_id 

FROM employees e JOIN departments d 

ON (e.department_id = d.department_id) 

WHERE e.manager_id = 149 ; 

可以对联接应用附加条件。

所示示例对EMPLOYEES和DEPARTMENTS表执行联接,另外,还仅显示经理ID
为149 的雇员。要对ON子句添加附加条件,可以添加AND子句。或者,可以使用WHERE子句应用附加条件。

  • 将表联接到自身

有时需要将表联接到自身。要查找每位雇员的经理的姓名,需要将EMPLOYEES表联接到自身,即执行自联接。例如,要查找Lorentz
的经理的姓名,需要执行以下操作:

? 在EMPLOYEES表中通过搜索LAST_NAME列来查找Lorentz。

? 通过搜索MANAGER_ID列查找Lorentz 的经理编号。Lorentz 的经理编号为103。

? 通过搜索LAST_NAME列查找EMPLOYEE_ID为103
的经理的姓名。Hunold的雇员编号为103,因此Hunold是Lorentz 的经理。

在这一过程中,对表进行了两次搜索。第一次是在表中LAST_NAME列中查找Lorentz,得知其MANAGER_ID值为103。第二次是搜索EMPLOYEE_ID列以查找103,然后在LAST_NAME列中找到了Hunold。

  • 使用ON子句进行自联接

SELECT worker.last_name emp, manager.last_name
mgr FROM employees worker JOIN employees
manager 

ON (worker.manager_id =
manager.employee_id); 

ON子句还可以用于联接同一表内或者不同表中具有不同名称的列。

所示示例为EMPLOYEES表基于EMPLOYEE_ID和MANAGER_ID列进行自联接。

注:示例所示的联接列(e.manager_id = m.employee_id)两边的圆括号是可选的。因此,即便是ON
e.manager_id = m.employee_id效果也一样。

  • 非等值联接

非等值联接是一个包含非等号运算符的联接条件。

EMPLOYEES表和JOB_GRADES表之间的关系就是一个非等值联接的示例。EMPLOYEES表中的SALARY列的范围介于JOB_GRADES表的LOWEST_SAL和HIGHEST_SAL列中的值之间。因此,可以根据每位雇员的薪金划分其等级。通过使用等号(=)
以外的运算符可以实现这一关系。

  • 使用非等值联接检索记录

SELECT e.last_name, e.salary, j.grade_level FROM
employees e JOIN job_grades j ON
e.salary BETWEEN j.lowest_sal AND
j.highest_sal; 

示例中创建了一个非等值联接来评估雇员的薪金等级。薪金必须介于任何一对最低薪金和最高薪金之间。

值得注意的是,在执行这一查询时,所有雇员只能出现一次。雇员不能在列表中重复出现。

这有以下两个原因:

?
JOB_GRADES表中的任何一行都不包含重叠的等级。也就是说,每位雇员的薪金值只能介于薪金等级表中某一行的最低薪金值和最高薪金值之间。

?
所有雇员的薪金都在职务等级表提供的限额之内。也就是说,任何雇员的薪金都不低于LOWEST_SAL列中的最低值,也不高于HIGHEST_SAL列中的最高值。

注:可以使用其它条件,如<=和>=,但最简单的方法是使用BETWEEN。请记住,在使用BETWEEN条件时,应先指定最低值,后指定最高值。Oracle
Server
将BETWEEN条件解释为一对AND条件。因此,使用BETWEEN没有性能优势,只是为了简化逻辑才使用它。

示例中指定了表别名,这是考虑到性能原因,而不是因为可能出现的混淆。

  • 使用OUTER联接返回没有直接匹配的记录

如果某一行不满足联接条件,则查询结果中就不会出现该行。

针对EMPLOYEES和DEPARTMENTS表使用简单等值联接来返回右侧的结果。结果集不包含以下内容:

? 部门ID 190,因为EMPLOYEES表中不存在具有该部门ID 的雇员

? 姓氏为Grant 的雇员,因为没有为该雇员分配部门ID

要返回没有任何雇员部门记录,或者返回没有分配部门的雇员,您可以使用OUTER联接。

  • INNER联接与OUTER联接

? 在SQL:1999 中,如果两个表的联接只返回相匹配的行,则称该联接为INNER联接。

?
如果两个表之间的联接不仅返回INNER联接的结果,还返回左(或右)表中不匹配的行,则称该联接为左(或右)OUTER联接。

?
如果两个表之间的联接不仅返回INNER联接的结果,还返回左和右联接的结果,则称该联接为完全OUTER联接。

使用NATURAL
JOIN、USING或ON子句对表进行联接时会生成INNER联接。输出中不会显示任何不匹配的行。要返回不匹配的行,可以使用OUTER联接。OUTER联接将返回满足联接条件的所有行,还会返回一个表在另一表中没有满足联接条件的对应行的部分或全部行。

有三种OUTER联接类型:

? LEFT OUTER

? RIGHT OUTER

? FULL OUTER

  • LEFT OUTER JOIN

SELECT e.last_name, e.department_id,
d.department_name FROM employees e LEFT OUTER JOIN departments
d ON (e.department_id = d.department_id)
;

此查询将检索EMPLOYEES表(它是左表)中的所有行,即使DEPARTMENTS表中没有匹配项也是如此。

  • RIGHT OUTER JOIN

SELECT e.last_name, d.department_id,
d.department_name FROM employees e RIGHT OUTER JOIN departments
d ON (e.department_id =
d.department_id); 

此查询将检索DEPARTMENTS表(它是右表)中的所有行,即使EMPLOYEES表中没有匹配项也是如此。

  • FULL OUTER JOIN

SELECT e.last_name, d.department_id, d.department_name FROM
employees e FULL OUTER JOIN departments d ON (e.department_id
= d.department_id) ;

此查询将检索EMPLOYEES表中的所有行,即使DEPARTMENTS表中没有匹配项也是如此。它还检索DEPARTMENTS表中的所有行,即使EMPLOYEES表中没有匹配项也是如此。

  • 笛卡尔积

? 出现以下情况时将形成笛卡尔积:

– 联接条件被忽略

– 联接条件无效

– 第一个表中的所有行被联接到第二个表中的所有行

? 如果要避免生成笛卡尔积,请始终包括有效的联接条件。

当一个联接条件无效或被完全忽略时,就会生成笛卡尔积。此时会显示行的所有组合。第一个表中的所有行会被联接到第二个表中的所有行。

笛卡尔积往往会生成大量的行,这种结果几乎没有任何用处。因此,应始终包括有效的联接条件,除非有特定需求需要组合所有表中的所有行。

如果某些测试需要生成大量的行来模拟合理的数据量,则笛卡尔积非常有用。

  • 生成笛卡尔积

如果某个联接条件被忽略,则会生成笛卡尔积。由于没有指定联接条件,EMPLOYEES表中的所有行(20
行)与DEPARTMENTS表中的所有行(8 行)联接在一起,因此在输出中生成了160 行。

  • 创建交叉联接

? CROSS JOIN子句可生成两个表的叉积。

? 这也称为两个表间的笛卡尔积。

SELECT last_name, department_name FROM
employees CROSS JOIN departments

示例生成EMPLOYEES表和DEPARTMENTS表的笛卡尔积。

CROSS JOIN方法非常有用,可以应用于许多情况。例如,要按月按办公室返回总人工成本,即使X
月没有人工成本,也可以执行所有月的表与办公室表的交叉联接。

如果要创建笛卡尔积,最佳做法是在SELECT中显式说明CROSS
JOIN。因此,可以非常清楚表明要生成笛卡尔积,而不是缺少联接的结果。

来源:http://blog.csdn.net/rlhua/article/details/12877591

[转]Oracle DB 使用连接显示多个表中的数据

时间: 2024-10-19 17:46:21

[转]Oracle DB 使用连接显示多个表中的数据的相关文章

Oracle DB 使用连接显示多个表中的数据

? 编写SELECT语句,以使用等值联接和非等值联接访问多个表中的数据 ? 使用自联接将表联接到自身 ? 使用OUTER联接查看通常不满足联接条件的数据 ? 生成两个或多个表中所有行的笛卡尔积 ? JOIN的类型及其语法 ? 自然联接: – USING子句 – ON子句 ? 自联接 ? 非等值联接 ? OUTER联接: – LEFT OUTER联接 – RIGHT OUTER联接 – FULL OUTER联接 ? 笛卡尔积 – 交叉联接 获取多个表中的数据 有时需要使用多个表中的数据.如两个独立

XtraTreeList直接显示Access数据库表中的数据

1.新建WinForm项目,添加“新建项”,选DataSet,打开*.xsd文件,在界面中右击,添加“TableAdapter”,在新控件中右击链接数据库(*.mdb),添加Sql语句.编译工程(F6) 2.打开对话框,选择工具栏,在工具栏中打开工程名自定义的控件,将DataSet控件.DepartmentsTableAdapter控件拖入对话框,在_Load函数中添加: this.departmentsTableAdapter1.Fill(this.dataSet1.Departments);

Vusual C++连接Mysql和从MySql中取出数据的API介绍

.1 mysql_real_connect() 2.1.1 函数原型: MYSQL *mysql_real_connect(MYSQL *mysql, const char *host, const char *user, const char *passwd, const char *db, unsigned int port, const char *unix_socket, unsigned int client_flag) 2.1.2 参数说明: • 第一个参数应该是一个现存MYSQL结

从远程oracle上导入到本地同一张表中不存在的记录的方法

场景:在远程oracle上存在一张表A,在本地同样存在一张相同表结构的表B.由于本地表B中保存了业务系统操作产生的几条记录,同时原来导入了A中的部分记录,但是并没有保存A中全部的记录.A中有15条记录,B中保存了A中3条记录同时B中还有本地业务系统产生的4条记录,不能删除B中的业务系统产生的4条记录.现在想将A中的另外的12条记录导入B中,同时有能保留B中原来的由业务系统产生的4条记录. 解决sql: 1.先在A中获得在B中出现过的记录. select * from [email protect

java实现将oracle表中的数据导出到excel表里

1.数据库连接类:Dbutil package sql2excel; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; public class Dbutil { /* * 功能

Oracle中 如何用一个表的数据更新另一个表中的数据

建表语句: create table table1( idd varchar2(10) , val varchar2(20) ); create table table2( idd varchar2(10), val varchar2(20) ); 插入数据: insert into table1 values ('01','1111'); insert into table1 values ('02','222'); insert into table1 values ('02','2222'

delete表1条件是另一个表中的数据,多表连接删除(转)

DELETE删除多表数据,怎样才能同时删除多个关联表的数据呢?这里做了深入的解释:1. delete from t1 where 条件2.delete t1 from t1 where 条件3. delete t1 from t1,t2 where 条件4.delete t1,t2 from t1,t2 where 条件前 3者是可行的,第4者不可行.也就是简单用delete语句无法进行多表删除数据操作,不过可以建立级联删除,在两个表之间建立级联删除关系,则可以实现删除一个表的数据时,同时删除另

【ORACLE】删除表中重复数据

原因 在对数据库进行操作过程中我们可能会遇到这种情况,表中的数据可能重复出现,使我们对数据库的操作过程中带来读诸多不便,那么怎么删除这些重复没有用的数据呢? 平时工作中可能会遇到当试图对库表中的某一列或几列创建唯一索引时,系统提示 ORA-01452 :不能创建唯一索引,发现重复记录. 处理方法 重复的数据可能有这样两种情况: 第一种:删除表中所有重复的数据 第二种:只保留重复数据中最新记录的一条记录[工作中常用] 删除重复数据的想法 每一行数据所对应的rowid都是独一无二的,及时表中两个数据

oracle如何清空一个用户下的所有表中的数据?

-- 大概 这个样子,如果没有 FK 的话,一下子就都删掉了. begin for x in (select table_name from user_tables) loop execute immediate 'delete ' || x.table_name ;  end loop ;  end ;