1. 程式人生 > >ORACLE中DATE自動轉化為TIMESTAMP

ORACLE中DATE自動轉化為TIMESTAMP

今天在寫SELECT語句的時候發現始終差不出來等於某個日期的資料,後來才發現是ORACLE內部發生的轉化。

廢話不多說,直接看示例。

1、構建資料

show parameter nls_date_format

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
nls_date_format                      string      YYYY-MM-DD

DROP TABLE t PURGE;
CREATE TABLE t
AS
SELECT (SYSDATE + LEVEL) AS t_date
FROM dual
CONNECT BY LEVEL < 10;

CREATE INDEX idx_t ON t(t_date);

SELECT * FROM t;
T_DATE
----------
2014-11-28
2014-11-29
2014-11-30
2014-12-01
2014-12-02
2014-12-03
2014-12-04
2014-12-05
2014-12-06

SELECT table_name, column_name, data_type FROM USER_TAB_COLUMNS WHERE table_name = 'T';
TABLE_NAME                     COLUMN_NAME                    DATA_TYPE
------------------------------ ------------------------------ --------------------
T                              T_DATE                         DATE
由上面可以看出建立了一個表T,其中有一個型別為DATE的T_DATE欄位

2、困擾怎麼沒有資料出來

SELECT * FROM t WHERE t_date='2014-11-28';
no rows selected
難道是沒有將2014-11-28轉換成DATE型別的原因?
SELECT * FROM t WHERE t_date=TO_DATE('2014-11-28', 'yyyy-mm-dd');
no rows selected
還是沒有,真奇怪!
3、像碰到這樣的問題,我首先想到的是檢視執行計劃

以上兩種查詢方法建議使用第二種,它使用了顯示型別轉化,更具有可讀性,等讓人明白。

SET AUTOTRACE ON EXPLAIN
SELECT * FROM t WHERE t_date=TO_DATE('2014-11-28', 'yyyy-mm-dd');

no rows selected

Execution Plan
----------------------------------------------------------
Plan hash value: 2296882198

--------------------------------------------------------------------------
| Id  | Operation        | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT |       |     1 |     9 |     1   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| IDX_T |     1 |     9 |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("T_DATE"=TO_DATE(' 2014-11-28 00:00:00', 'syyyy-mm-dd
              hh24:mi:ss'))

Note
-----
   - dynamic sampling used for this statement (level=2)
通過上面的執行計劃,可以看到ORACLE自動發生了DATE -> TIMESTAMP的轉化:
"T_DATE"=TO_DATE(' 2014-11-28 00:00:00', 'syyyy-mm-dd hh24:mi:ss')

4、所以我們要查詢出相關時間只能是另尋他法了。

SELECT * FROM t 
WHERE t_date >= TO_DATE('2014-11-28', 'yyyy-mm-dd') AND
	t_date < TO_DATE('2014-11-29', 'yyyy-mm-dd');

T_DATE
----------
2014-11-28

Execution Plan
----------------------------------------------------------
Plan hash value: 2296882198

--------------------------------------------------------------------------
| Id  | Operation        | Name  | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT |       |     1 |     9 |     1   (0)| 00:00:01 |
|*  1 |  INDEX RANGE SCAN| IDX_T |     1 |     9 |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("T_DATE">=TO_DATE(' 2014-11-28 00:00:00', 'syyyy-mm-dd
              hh24:mi:ss') AND "T_DATE"<TO_DATE(' 2014-11-29 00:00:00', 'syyyy-mm-dd
              hh24:mi:ss'))

Note
-----
   - dynamic sampling used for this statement (level=2)
由上看到資料終於查出來了