1. 程式人生 > >Oracle DB 使用連接顯示多個表中的數據

Oracle DB 使用連接顯示多個表中的數據

RKE line 列表 ini 就會 type 運算 在一起 num

? 編寫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語法將導致產生一個錯誤。
  • 使用自然聯接檢索記錄
hr@TEST0924> 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) hr@TEST0924> 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) hr@TEST0924> 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 的那些行: hr@TEST0924> 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子句檢索記錄
hr@TEST0924> 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子句中使用表別名
hr@TEST0924> 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 語句的任何位置使用限定詞(表名或別名)。 例如,下面的語句是有效的: hr@TEST0924> 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(定義的列含糊不清)”錯誤。 下面的語句是有效的: hr@TEST0924> 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子句檢索記錄
hr@TEST0924> 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子句創建三向聯接
hr@TEST0924> 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子句實現: hr@TEST0924> 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://www.captainbed.net

Oracle DB 使用連接顯示多個表中的數據