2016-04-18 31 views
0

我正在查看一些SQL並試圖瞭解它試圖做什麼。我被告知它返回昨天在午夜和今天之間的數據。有人能爲我翻譯簡單的英文摘錄嗎?兩個日期之間的Oracle SQL數據

SELECT ... 
FROM ... 
WHERE CREATEDATE >=TO_DATE(TRUNC(SYSDATE-1) || ' 00:00:00', 'DD-MON-YY HH24:MI:SS') 
AND CREATEDATE <=TO_DATE(TRUNC(SYSDATE-1) || ' 23:59:59', 'DD-MON-YY HH24:MI:SS') 

這似乎並沒有工作,除非我改變底線:

AND CREATEDATE <=TO_DATE(TRUNC(SYSDATE) || ' 23:59:59', 'DD-MON-YY HH24:MI:SS') 

與理解任何幫助,這個代碼可以理解的。

+0

oracle文檔將告訴您每個函數的功能。 –

+0

如果CREATEDATE被聲明爲VARCHAR而不是DATE,那麼Mary Stigmata姐妹也應該與統治者一起挑戰自己。 – spencer7593

+0

我笑了。幸運的是,對於這段SQL的作者,CREATEDATE確實是DATE類型的。 –

回答

5

謂詞看起來比它們需要的更加複雜。

爲什麼不會返回您要返回的結果?

WHERE CREATEDATE >= TRUNC(SYSDATE-1) 
    AND CREATEDATE < TRUNC(SYSDATE) 

說明一下,在「簡單的英語」,這三個由SELECT語句返回的表達式:

SELECT SYSDATE 
     , TRUNC(SYSDATE) 
     , TRUNC(SYSDATE-1) 
    FROM DUAL 

返回日期值(值是甲骨文的數據類型爲DATE)。

------------------- ------------------- ------------------- 
    2016-04-16 13:59:26 2016-04-16 00:00:00 2016-04-15 00:00:00 

我們沒有看到的是CREATEDATE的數據類型。顯然,我們期望它被定義爲DATE。但是如果你已經聲明它爲VARCHAR並且以'16 -APR-2016 13:59:26'的格式存儲字符串,那麼「除非」你觀察的問題只是冰山一角,否則「似乎不起作用。

(你所觀察的行爲可以很容易地如果CREATEDATE被聲明爲VARCHAR,而不是DATE解釋。)


如果你的SQL 工作,因爲它是寫的,它依賴於當前的設置的NLS_DATE_FORMAT。也就是說,你的SQL可以很容易地用relataively無害的聲明打破,如:

ALTER SESSION SET NLS_DATE_FORMAT='YYYY-MM-DD' ; 

的一些在當前查詢表達式的組件的破舊......

  • SYSDATE返回當前日期和時間作爲DATE

  • SYSDATE-1減去從當前日期和時間1天,並返回一個DATE

  • TRUNC(<dateexpr>) 「LOPS關」 從DATE值的時間分量,只返回與時間的日期部分設置爲午夜

  • ||在串並置運算符

:使用DATE表達式執行字符串連接需要Oracle執行隱式TO_CHAR轉換。 Oracle使用NLS_DATE_FORMAT作爲默認格式模型。)

  • '單引號括字符串文字

TO_DATE功能的第二個參數是一個格式模型。

  • DD是兩位數日(如07或16)
  • MON爲月
  • YY三個字母的縮寫一年兩個字符表示,與隱含世紀(
  • HH24是二(24小時制),00到23
  • MI是兩位數分鐘,00到59
  • SS是兩個d igit秒,00直通59

注:沒有我們已經修復 Y2K問題?爲什麼我們重新創造它)


我認爲最重要的事情,瞭解有關當前SQL:它使用比需要更多的令人費解的表情。而我看到的表達式,以三種方式被打破:

  • 取決於NLS_DATE_FORMAT的隱TO_CHAR功能明確的業態模式在to_date函數適當匹配

  • 沒有任何藉口使用兩性格年,我們可以輕鬆使用四位數年份。特別是當不需要首先將DATE值轉換爲字符串時。

  • 使用< =比較而不是<比較,取決於日期時間類型的最大精度爲一秒,當我們可以輕鬆地指定第二天的「小於」午夜時,使用模式處理小數秒。

如果將CREATEDATE聲明爲VARCHAR,則會以另一種方式破壞...比較正在作爲字符串比較執行。對於比較右側的表達式,存在隱式TO_CHAR轉換。這些轉換(再次)依賴於NLS_DATE_FORMAT設置。使用歷史悠久的Oracle默認設置DD-MON-YY,字符串比較將在某種意義上起作用,即語法不是無效的,但根據返回日期值在兩個其他日期值之間的比較,這些比較是中斷

+0

感謝您的詳盡解答。這很有幫助。 –

2

所以發生了什麼是一種奇怪的。 這裏的轉換有點令人困惑,但讓我們深入瞭解它。

TRUNC(SYSDATE-1)在這種情況下被翻譯爲VARCHAR2,並基於默認的NLS參數翻譯爲昨天的日期。
今天是2016年4月18日,所以它會返回字符串'17 -APR-16'(基於默認的NLS格式)。

接下來,你連接到這個字符串,「時間」字符串 - 00:00:00。
這建立了字符串'17-APR-16 00:00:00' - 昨天的午夜。
這包含在「To_date」中,其格式爲「DD-MON-YY HH24:MI:SS」,使其成爲實際日期(數據爲DATE)。

,其構造是昨天的最後一分鐘的第二次約會 - '17 -APR-16 23:59:59' ......

所以,你正在尋找這是昨天在此查詢創建的所有記錄。

這有點令人困惑,因爲日期的「TRUNC」返回一個日期,但串連到一個字符串會強制隱式轉換。

讓我知道,如果你有更多的問題在那裏發生了什麼。

P.S.我建議只用日期重寫查詢,因爲查詢將以不同的NLS設置失敗......

+1

謝謝。我希望我可以選擇兩個正確答案,因爲這也非常有幫助。 –

相關問題