Oracle 在連線條件裡處理和比較 NULL 值
當進行表連線時,希望把 NULL 值對映到一個預設值上,這樣就可以避免使用外連線了。可以用 NVL 函式把待連線表的外來鍵列上的 NULL 值進行轉換。
SQL> select employee_id, first_name, last_name, department_id
2 from hr.employees
3 where employee_id = 178;
EMPLOYEE_ID FIRST_NAME LAST_NAME DEPARTMENT_ID
----------- -------------------- ------------------------- -------------
178 Kimberely Grant
使用外連線的方式處理
SQL> select employee_id, first_name, last_name, d.department_id, department_name
2 from hr.employees e
3 left join hr.departments d
4 on e.department_id = d.department_id;
EMPLOYEE_ID FIRST_NAME LAST_NAME DEPARTMENT_ID DEPARTMENT_NAME
----------- -------------------- ------------------------- ------------- ------------------------------
112 Jose Manuel Urman 100 Finance
111 Ismael Sciarra 100 Finance
110 John Chen 100 Finance
109 Daniel Faviet 100 Finance
108 Nancy Greenberg 100 Finance
206 William Gietz 110 Accounting
205 Shelley Higgins 110 Accounting
178 Kimberely Grant
以下查詢把所有部門為 NULL 的 EMPLOYEE 轉換到編碼位 110 的部門
SQL> select employee_id, first_name, last_name, d.department_id, department_name
2 from hr.employees e
3 join hr.departments d
4 on nvl(e.department_id, 110) = d.department_id;
EMPLOYEE_ID FIRST_NAME LAST_NAME DEPARTMENT_ID DEPARTMENT_NAME
----------- -------------------- ------------------------- ------------- ------------------------------
109 Daniel Faviet 100 Finance
110 John Chen 100 Finance
111 Ismael Sciarra 100 Finance
112 Jose Manuel Urman 100 Finance
113 Luis Popp 100 Finance
178 Kimberely Grant 110 Accounting
205 Shelley Higgins 110 Accounting
206 William Gietz 110 Accounting
在條件連線中,把 NULL 對映到非 NULL 值來避免使用 OUTER JOIN 可能會存在效能方面的問題,因為不會用到 EMPLOYEES.DEPARTMENT_ID 上的索引(主要是因為 NULL 列沒有索引)。我們可以用基於函式的索引來解決這個問題。
建立索引前的執行計劃
SQL> explain plan for select employee_id, first_name, last_name, d.department_id, department_name
2 from hr.employees e
3 join hr.departments d
4 on nvl(e.department_id, 110) = d.department_id;
已解釋。
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 1343509718
--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 106 | 4028 | 6 (17)| 00:00:01 |
| 1 | MERGE JOIN | | 106 | 4028 | 6 (17)| 00:00:01 |
| 2 | TABLE ACCESS BY INDEX ROWID| DEPARTMENTS | 27 | 432 | 2 (0)| 00:00:01 |
| 3 | INDEX FULL SCAN | DEPT_ID_PK | 27 | | 1 (0)| 00:00:01 |
|* 4 | SORT JOIN | | 107 | 2354 | 4 (25)| 00:00:01 |
| 5 | TABLE ACCESS FULL | EMPLOYEES | 107 | 2354 | 3 (0)| 00:00:01 |
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("D"."DEPARTMENT_ID"=NVL("E"."DEPARTMENT_ID",110))
filter("D"."DEPARTMENT_ID"=NVL("E"."DEPARTMENT_ID",110))
建立索引
SQL> create index hr.employees_dpet_fbi on hr.employees(nvl(department_id,110));
索引已建立。
建立索引後的執行計劃
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 2904398956
---------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 107 | 5136 | 6 (0)| 00:00:01 |
| 1 | NESTED LOOPS | | 107 | 5136 | 6 (0)| 00:00:01 |
| 2 | TABLE ACCESS FULL | DEPARTMENTS | 27 | 432 | 3 (0)| 00:00:01 |
| 3 | TABLE ACCESS BY INDEX ROWID| EMPLOYEES | 4 | 128 | 1 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | EMPLOYEES_DPET_FBI | 4 | | 0 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------------
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access(NVL("DEPARTMENT_ID",110)="D"."DEPARTMENT_ID")
已選擇16行。
SQL> select employee_id, first_name, last_name, department_id
2 from hr.employees
3 where employee_id = 178;
EMPLOYEE_ID FIRST_NAME LAST_NAME DEPARTMENT_ID
----------- -------------------- ------------------------- -------------
178 Kimberely Grant
使用外連線的方式處理
SQL> select employee_id, first_name, last_name, d.department_id, department_name
2 from hr.employees e
3 left join hr.departments d
4 on e.department_id = d.department_id;
EMPLOYEE_ID FIRST_NAME LAST_NAME DEPARTMENT_ID DEPARTMENT_NAME
----------- -------------------- ------------------------- ------------- ------------------------------
112 Jose Manuel Urman 100 Finance
111 Ismael Sciarra 100 Finance
110 John Chen 100 Finance
109 Daniel Faviet 100 Finance
108 Nancy Greenberg 100 Finance
206 William Gietz 110 Accounting
205 Shelley Higgins 110 Accounting
178 Kimberely Grant
以下查詢把所有部門為 NULL 的 EMPLOYEE 轉換到編碼位 110 的部門
SQL> select employee_id, first_name, last_name, d.department_id, department_name
2 from hr.employees e
3 join hr.departments d
4 on nvl(e.department_id, 110) = d.department_id;
EMPLOYEE_ID FIRST_NAME LAST_NAME DEPARTMENT_ID DEPARTMENT_NAME
----------- -------------------- ------------------------- ------------- ------------------------------
109 Daniel Faviet 100 Finance
110 John Chen 100 Finance
111 Ismael Sciarra 100 Finance
112 Jose Manuel Urman 100 Finance
113 Luis Popp 100 Finance
178 Kimberely Grant 110 Accounting
205 Shelley Higgins 110 Accounting
206 William Gietz 110 Accounting
在條件連線中,把 NULL 對映到非 NULL 值來避免使用 OUTER JOIN 可能會存在效能方面的問題,因為不會用到 EMPLOYEES.DEPARTMENT_ID 上的索引(主要是因為 NULL 列沒有索引)。我們可以用基於函式的索引來解決這個問題。
建立索引前的執行計劃
SQL> explain plan for select employee_id, first_name, last_name, d.department_id, department_name
2 from hr.employees e
3 join hr.departments d
4 on nvl(e.department_id, 110) = d.department_id;
已解釋。
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 1343509718
--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 106 | 4028 | 6 (17)| 00:00:01 |
| 1 | MERGE JOIN | | 106 | 4028 | 6 (17)| 00:00:01 |
| 2 | TABLE ACCESS BY INDEX ROWID| DEPARTMENTS | 27 | 432 | 2 (0)| 00:00:01 |
| 3 | INDEX FULL SCAN | DEPT_ID_PK | 27 | | 1 (0)| 00:00:01 |
|* 4 | SORT JOIN | | 107 | 2354 | 4 (25)| 00:00:01 |
| 5 | TABLE ACCESS FULL | EMPLOYEES | 107 | 2354 | 3 (0)| 00:00:01 |
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access("D"."DEPARTMENT_ID"=NVL("E"."DEPARTMENT_ID",110))
filter("D"."DEPARTMENT_ID"=NVL("E"."DEPARTMENT_ID",110))
建立索引
SQL> create index hr.employees_dpet_fbi on hr.employees(nvl(department_id,110));
索引已建立。
建立索引後的執行計劃
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------------------------------
Plan hash value: 2904398956
---------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 107 | 5136 | 6 (0)| 00:00:01 |
| 1 | NESTED LOOPS | | 107 | 5136 | 6 (0)| 00:00:01 |
| 2 | TABLE ACCESS FULL | DEPARTMENTS | 27 | 432 | 3 (0)| 00:00:01 |
| 3 | TABLE ACCESS BY INDEX ROWID| EMPLOYEES | 4 | 128 | 1 (0)| 00:00:01 |
|* 4 | INDEX RANGE SCAN | EMPLOYEES_DPET_FBI | 4 | | 0 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------------
PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
4 - access(NVL("DEPARTMENT_ID",110)="D"."DEPARTMENT_ID")
已選擇16行。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26506993/viewspace-2018523/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Oracle 排序中常用的NULL值處理方法Oracle排序Null
- 關於外連線和where條件
- MySQL中的NULL和空串比較MySqlNull
- Oracle 連線條件中帶有OR的測試Oracle
- 條款 11:在 operator= 中處理“自我賦值”賦值
- FastJson 序列化處理 null 值ASTJSONNull
- JavaScript 字串連線效能比較JavaScript字串
- Oracle空串與null的處理OracleNull
- 運輸計劃和處理的前提條件
- ORACLE SQL過濾條件是IS NULL or !=的優化OracleSQLNull優化
- 檢視oracle資料庫中,哪些表的欄位是null值比較多Oracle資料庫Null
- 比較優雅的後臺條件查詢
- Spark2 Dataset DataFrame空值null,NaN判斷和處理SparkNullNaN
- 【C#】-對於Null值的處理方法C#Null
- ORACLE的count與空值比較Oracle
- 關於NULL值在索引裡的兩個疑惑Null索引
- 【NULL】Oracle null值介紹NullOracle
- Mysql關於長連線短連線優劣比較MySql
- 用decode和nvl處理null值時需要注意的地方Null
- doxygen 宏定義/宏編譯/條件編譯/預處理/預編譯 不處理、忽略條件、分析所有條件、滿足所有條件的方法編譯
- Oracle date 型別比較和String比較Oracle型別
- 麒麟659和麒麟710處理器引數比較
- [Oracle] minus 和 not exists比較Oracle
- ORACLE 中IN和EXISTS比較Oracle
- Effective c++條款11:在operator=中處理“自我賦值”C++賦值
- hive表連線和oracle測試對比HiveOracle
- 用PHP連mysql和oracle資料庫效能比較(轉)PHPMySqlOracle資料庫
- 資料庫外連線,自然連線,內連線,條件連線,等值連線關係及詳解資料庫
- CHECK約束中的NULL條件Null
- MySQL 儲存過程定義條件和異常處理MySql儲存過程
- 華為麒麟659和麒麟710處理器引數比較
- T-SQL——關於Join on的的連線條件和where的篩選條件的區分SQL
- 連線條件字元型別不一樣。字元型別
- Oracle唯一約束中NULL的處理OracleNull
- (11)mysql 中的條件定義、處理MySql
- Oracle OCP(02):條件和排序Oracle排序
- 【開發篇sql】 條件和表示式(三) Null詳解SQLNull
- ORACLE和MSSQL中行鎖比較OracleSQL