最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SQL?中日期的特殊性總結(jié)(格式符嚴(yán)格要求全大寫(xiě))

 更新時(shí)間:2026年04月24日 09:42:37   作者:穆金秋  
文章總結(jié)了SQL中日期數(shù)據(jù)類型的特殊性,并詳細(xì)介紹了日期與字符串的轉(zhuǎn)換、日期比較和加減運(yùn)算的注意事項(xiàng),強(qiáng)調(diào)了索引使用與避免函數(shù)修飾篩選列的重要性,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友跟隨小編一起看看吧

SQL中日期的特殊性總結(jié)

在SQL中,日期是一種特殊的數(shù)據(jù)類型,既有數(shù)值的特性,又有字符串的表現(xiàn)形式,使用時(shí)有諸多需要注意的地方。

一、日期數(shù)據(jù)類型的特點(diǎn)

特性說(shuō)明示例
存儲(chǔ)格式內(nèi)部存儲(chǔ)為數(shù)字(從某個(gè)基準(zhǔn)日期開(kāi)始的天數(shù)/秒數(shù))Oracle: 4712-01-01 起的天數(shù)
顯示格式由數(shù)據(jù)庫(kù)參數(shù)控制,不一定是輸入時(shí)的格式Oracle: 17-12月-80
運(yùn)算能力支持加減運(yùn)算(天數(shù)/月數(shù)/年數(shù))HIREDATE + 30(30天后)
比較能力支持 <, >, =, BETWEEN 等比較操作HIREDATE > TO_DATE('1981-01-01')

二、日期與字符串的轉(zhuǎn)換(最重要)

核心函數(shù)

函數(shù)方向用途
TO_DATE(字符串, 格式)字符串 → 日期將字符串按指定格式解析為日期類型
TO_CHAR(日期, 格式)日期 → 字符串將日期按指定格式轉(zhuǎn)換為字符串

常用日期格式元素

格式符含義示例
YYYY四位年份1981
YY兩位年份81
MM兩位月份05
MON月份縮寫(xiě)(中文環(huán)境為'5月')'5月'
MONTH月份全稱'5月'
DD兩位日期01
DAY星期幾'星期三'
HH2424小時(shí)制14
MI分鐘30
SS秒鐘45

在SQL中,日期格式符是區(qū)分大小寫(xiě)的,這是一個(gè)非常重要的細(xì)節(jié),寫(xiě)錯(cuò)了會(huì)導(dǎo)致轉(zhuǎn)換失敗或結(jié)果錯(cuò)誤。

核心規(guī)則:格式符嚴(yán)格區(qū)分大小寫(xiě)

格式符含義正確示例錯(cuò)誤示例(大小寫(xiě)錯(cuò)誤)
MM月份(01-12)TO_CHAR(date, 'MM') → 04mm → ? 報(bào)錯(cuò)或無(wú)效
MI分鐘(00-59)TO_CHAR(date, 'MI') → 30Mi / mi → ?
HH2424小時(shí)制(00-23)TO_CHAR(date, 'HH24') → 14hh24 → ?
HH12 / HH12小時(shí)制(01-12)TO_CHAR(date, 'HH12') → 02hh12 → ?
YYYY四位年份TO_CHAR(date, 'YYYY') → 2026yyyy → ?
YY兩位年份TO_CHAR(date, 'YY') → 26yy → ?
MON月份縮寫(xiě)(如'4月')TO_CHAR(date, 'MON') → 4月Mon / mon → ?
MONTH月份全稱(如'4月')TO_CHAR(date, 'MONTH') → 4月Month → ?
DD日期(01-31)TO_CHAR(date, 'DD') → 23dd → ?
DY星期縮寫(xiě)(如'周三')TO_CHAR(date, 'DY') → 周三dy → ?
DAY星期全稱(如'星期三')TO_CHAR(date, 'DAY') → 星期三Day → ?

示例代碼

-- TO_DATE:字符串轉(zhuǎn)日期
TO_DATE('1981-05-01', 'YYYY-MM-DD')     -- 返回日期:1981年5月1日
TO_DATE('19810501', 'YYYYMMDD')         -- 返回日期:1981年5月1日
TO_DATE('1981-05', 'YYYY-MM')           -- 返回日期:1981年5月1日(默認(rèn)當(dāng)月1號(hào))
-- TO_CHAR:日期轉(zhuǎn)字符串
TO_CHAR(HIREDATE, 'YYYY-MM-DD')         -- '1981-05-01'
TO_CHAR(HIREDATE, 'YYYYMM')             -- '198105'
TO_CHAR(HIREDATE, 'MON DD, YYYY')       -- '5月 01, 1981'

三、日期比較的特殊性

1. 不能直接用字符串比較日期

-- ? 錯(cuò)誤:字符串 '1981' 和日期類型不能直接比較
SELECT * FROM EMP WHERE HIREDATE = '1981';
-- ? 正確方式1:轉(zhuǎn)換日期為字符串比較
SELECT * FROM EMP WHERE TO_CHAR(HIREDATE, 'YYYY') = '1981';
-- ? 正確方式2:字符串轉(zhuǎn)日期比較
SELECT * FROM EMP WHERE HIREDATE >= TO_DATE('1981-01-01', 'YYYY-MM-DD')
                     AND HIREDATE < TO_DATE('1982-01-01', 'YYYY-MM-DD');

2. 日期比較的邊界問(wèn)題(重要??)

-- 查詢1981年入職的員工(錯(cuò)誤寫(xiě)法)
SELECT * FROM EMP 
WHERE TO_CHAR(HIREDATE, 'YYYY') = 1981;  -- ? 可行,但效率低
-- 查詢1981年入職的員工(正確寫(xiě)法 - 使用范圍)
SELECT * FROM EMP 
WHERE HIREDATE >= TO_DATE('1981-01-01', 'YYYY-MM-DD')
  AND HIREDATE <  TO_DATE('1982-01-01', 'YYYY-MM-DD');
-- 查詢1981年5月入職(錯(cuò)誤寫(xiě)法)
WHERE HIREDATE BETWEEN TO_DATE('1981-05-01', 'YYYY-MM-DD')
                   AND TO_DATE('1981-05-31', 'YYYY-MM-DD');  -- ?? 漏掉了5月31日23:59:59之后的數(shù)據(jù)
-- 查詢1981年5月入職(正確寫(xiě)法)
WHERE HIREDATE >= TO_DATE('1981-05-01', 'YYYY-MM-DD')
  AND HIREDATE <  TO_DATE('1981-06-01', 'YYYY-MM-DD');

邊界寫(xiě)法參考

需求TO_CHAR 寫(xiě)法TO_DATE 范圍寫(xiě)法
年份 = 1981TO_CHAR(HIREDATE,'YYYY') = 1981HIREDATE >= TO_DATE('1981-01-01','YYYY-MM-DD') AND HIREDATE < TO_DATE('1982-01-01','YYYY-MM-DD')
年份 < 1982TO_CHAR(HIREDATE,'YYYY') < 1982HIREDATE < TO_DATE('1982-01-01','YYYY-MM-DD')
年份 <= 1982TO_CHAR(HIREDATE,'YYYY') <= 1982HIREDATE < TO_DATE('1983-01-01','YYYY-MM-DD')
年份 > 1981TO_CHAR(HIREDATE,'YYYY') > 1981HIREDATE >= TO_DATE('1982-01-01','YYYY-MM-DD')
年份 >= 1982TO_CHAR(HIREDATE,'YYYY') >= 1982HIREDATE >= TO_DATE('1982-01-01','YYYY-MM-DD')

四、日期的加減運(yùn)算

運(yùn)算含義示例
日期 + 數(shù)字增加天數(shù)HIREDATE + 30(30天后)
日期 - 數(shù)字減少天數(shù)HIREDATE - 7(7天前)
日期1 - 日期2相差天數(shù)SYSDATE - HIREDATE(入職天數(shù))
ADD_MONTHS(日期, 數(shù)字)增加月份ADD_MONTHS(HIREDATE, 6)(6個(gè)月后)
MONTHS_BETWEEN(日期1, 日期2)相差月數(shù)MONTHS_BETWEEN(SYSDATE, HIREDATE)

示例代碼

-- 計(jì)算員工入職天數(shù)
SELECT ENAME, SYSDATE - HIREDATE AS 工作天數(shù) FROM EMP;
-- 計(jì)算員工入職月數(shù)
SELECT ENAME, MONTHS_BETWEEN(SYSDATE, HIREDATE) AS 工作月數(shù) FROM EMP;
-- 查詢?nèi)肼毘^(guò)30年的員工
SELECT * FROM EMP 
WHERE ADD_MONTHS(HIREDATE, 30*12) < SYSDATE;

五、日期函數(shù)對(duì)比(Oracle vs MySQL)

功能OracleMySQL
當(dāng)前日期時(shí)間SYSDATENOW() / CURDATE()
提取年份TO_CHAR(date, 'YYYY')YEAR(date)
提取月份TO_CHAR(date, 'MM')MONTH(date)
日期加減天數(shù)date + 10DATE_ADD(date, INTERVAL 10 DAY)
日期差(天數(shù))date1 - date2DATEDIFF(date1, date2)
增加月份ADD_MONTHS(date, 6)DATE_ADD(date, INTERVAL 6 MONTH)

六、常見(jiàn)陷阱與最佳實(shí)踐

? 常見(jiàn)錯(cuò)誤

-- 1. 直接比較字符串和日期
WHERE HIREDATE = '1981-05-01'           -- 隱式轉(zhuǎn)換可能失敗
-- 2. 使用 BETWEEN 包含結(jié)束日期(會(huì)丟失當(dāng)天23:59:59后的數(shù)據(jù))
WHERE HIREDATE BETWEEN '1981-05-01' AND '1981-05-31'
-- 3. TO_CHAR 寫(xiě)在 WHERE 條件的左邊(無(wú)法使用索引)
WHERE TO_CHAR(HIREDATE, 'YYYY') = '1981'
-- 4. 忽略時(shí)區(qū)問(wèn)題
WHERE CREATE_TIME = '2026-04-23'        -- 可能漏掉帶時(shí)分秒的記錄

? 最佳實(shí)踐

-- 1. 始終使用顯式轉(zhuǎn)換
WHERE HIREDATE >= TO_DATE('1981-05-01', 'YYYY-MM-DD')
  AND HIREDATE <  TO_DATE('1981-06-01', 'YYYY-MM-DD')
-- 2. 范圍查詢使用左閉右開(kāi)區(qū)間
WHERE HIREDATE >= TRUNC(SYSDATE - 30)   -- 30天前零點(diǎn)
  AND HIREDATE <  TRUNC(SYSDATE)        -- 今天零點(diǎn)
-- 3. 讓函數(shù)作用在常量上,保持索引有效
WHERE HIREDATE >= TO_DATE('1981-01-01', 'YYYY-MM-DD')  -- ? 索引有效
WHERE TO_CHAR(HIREDATE, 'YYYY') = '1981'                -- ? 索引失效
-- 4. 使用 TRUNC 去掉時(shí)間部分
WHERE TRUNC(HIREDATE) = TO_DATE('1981-05-01', 'YYYY-MM-DD')

使用 TRUNC 去掉時(shí)間部分是什么意思

TRUNC 是一個(gè)用于截?cái)?/strong>日期或數(shù)字的函數(shù)。在日期處理中,"去掉時(shí)間部分"是指將日期中的時(shí)、分、秒清零,只保留年、月、日。

為什么需要"去掉時(shí)間部分"?問(wèn)題場(chǎng)景:日期比較的陷阱
-- 假設(shè)表中有一條記錄,HIREDATE = 1981-05-01 14:30:00
-- ? 錯(cuò)誤:這條記錄會(huì)被漏掉!
SELECT * FROM EMP 
WHERE HIREDATE = TO_DATE('1981-05-01', 'YYYY-MM-DD');
-- 因?yàn)樽筮呌?14:30:00,右邊是 00:00:00,不相等
-- ? 解法1:使用 TRUNC 去掉時(shí)間部分
SELECT * FROM EMP 
WHERE TRUNC(HIREDATE) = TO_DATE('1981-05-01', 'YYYY-MM-DD');
-- ? 解法2:使用范圍查詢(更推薦,索引友好)
SELECT * FROM EMP 
WHERE HIREDATE >= TO_DATE('1981-05-01', 'YYYY-MM-DD')
  AND HIREDATE < TO_DATE('1981-05-02', 'YYYY-MM-DD');

TRUNC 的常用格式

用法結(jié)果說(shuō)明
TRUNC(SYSDATE)2026-04-24 00:00:00截?cái)嗟疆?dāng)天開(kāi)始(默認(rèn))
TRUNC(SYSDATE, 'DD')2026-04-24 00:00:00同上,DD表示天
TRUNC(SYSDATE, 'MM')2026-04-01 00:00:00截?cái)嗟疆?dāng)月第一天
TRUNC(SYSDATE, 'Q')2026-04-01 00:00:00截?cái)嗟疆?dāng)季第一天
TRUNC(SYSDATE, 'YYYY')2026-01-01 00:00:00截?cái)嗟疆?dāng)年第一天
TRUNC(SYSDATE, 'HH24')2026-04-24 14:00:00截?cái)嗟疆?dāng)前小時(shí)開(kāi)始

對(duì)比總結(jié)

函數(shù)作用示例輸入示例輸出
TRUNC(date)去掉時(shí)間部分(歸零)2026-04-24 14:35:282026-04-24 00:00:00
TO_CHAR(date, 'YYYY-MM-DD')轉(zhuǎn)為字符串(丟失時(shí)間)2026-04-24 14:35:28'2026-04-24'
ROUND(date)四舍五入到天2026-04-24 14:35:282026-04-25 00:00:00

TRUNC 會(huì)讓索引失效(類似 TO_CHAR)

-- ? 索引失效
WHERE TRUNC(HIREDATE) = TO_DATE('1981-05-01', 'YYYY-MM-DD')
-- ? 推薦:范圍查詢(索引有效)
WHERE HIREDATE >= TO_DATE('1981-05-01', 'YYYY-MM-DD')
  AND HIREDATE < TO_DATE('1981-05-02', 'YYYY-MM-DD')

原則:能不用 TRUNC 在 WHERE 條件中就不用,除非數(shù)據(jù)量很小或沒(méi)有時(shí)間精度要求。

TRUNC 常用于 GROUP BY 分組

-- 按天統(tǒng)計(jì)(即使數(shù)據(jù)庫(kù)存了時(shí)分秒)
SELECT TRUNC(HIREDATE) AS 入職日期, COUNT(*) AS 人數(shù)
FROM EMP
GROUP BY TRUNC(HIREDATE);

一句話總結(jié)

TRUNC 去掉時(shí)間部分 = 把 14:35:28 變成 00:00:00
用于忽略時(shí)分秒的干擾,讓日期比較只看年月日。
但在 WHERE 中要小心使用,因?yàn)樗?nbsp;TO_CHAR 一樣會(huì)讓索引失效,大數(shù)據(jù)量時(shí)建議用范圍查詢替代。

七、快速參考卡片

需求SQL寫(xiě)法
當(dāng)前系統(tǒng)日期SYSDATE(Oracle)/ CURDATE()(MySQL)
年月日格式'YYYY-MM-DD'
字符串→日期TO_DATE('1981-05-01', 'YYYY-MM-DD')
日期→字符串TO_CHAR(HIREDATE, 'YYYY-MM-DD')
提取年份TO_CHAR(HIREDATE, 'YYYY')
提取年月TO_CHAR(HIREDATE, 'YYYYMM')
某月第一天TRUNC(HIREDATE, 'MM')
某年第一天TRUNC(HIREDATE, 'YYYY')
月底最后一天LAST_DAY(HIREDATE)
下個(gè)月同一天ADD_MONTHS(HIREDATE, 1)

八、你在作業(yè)中的日期問(wèn)題總結(jié)

-- 第3題 ? 正確
WHERE TO_CHAR(HIREDATE, 'YYYYMM') < 198210
-- 第5題 ?? 缺少括號(hào)(結(jié)果正確但不規(guī)范)
WHERE DEPTNO=20 AND TO_CHAR(HIREDATE,'YYYY')<1982
   OR DEPTNO=30 AND TO_CHAR(HIREDATE,'YYYY')<1985
-- 第11題 ? 完全遺漏WHERE條件
-- 應(yīng)該加:WHERE TO_CHAR(HIREDATE, 'YYYY') > 1981

核心要點(diǎn)

  • 日期比較時(shí),優(yōu)先使用范圍查詢(左閉右開(kāi))
  • TO_CHAR 會(huì)讓索引失效,大數(shù)據(jù)量時(shí)慎用
  • 始終用 顯式轉(zhuǎn)型,不要依賴隱式轉(zhuǎn)換
  • 注意邊界值,BETWEEN 可能丟失最后一天的末尾時(shí)間

TO_CHAR 會(huì)讓索引失效,大數(shù)據(jù)量時(shí)慎用。是什么意思?

索引就像一本書(shū)的"目錄",它能幫你快速翻到需要的頁(yè)碼。但如果對(duì)"目錄"里的文字做了修改(比如加了格式),那原來(lái)的目錄就失效了,你只能一頁(yè)一頁(yè)地翻完整本書(shū)來(lái)找內(nèi)容。

1. 為什么TO_CHAR會(huì)讓索引失效?

SQL的執(zhí)行順序決定了索引的生效機(jī)制。

當(dāng)你執(zhí)行 WHERE TO_CHAR(HIREDATE, 'YYYY') = '1981' 時(shí),數(shù)據(jù)庫(kù)的處理過(guò)程是這樣的:

  • 讀取一條數(shù)據(jù):數(shù)據(jù)庫(kù)從硬盤(pán)或內(nèi)存中取出第一行員工的數(shù)據(jù)。
  • 執(zhí)行函數(shù):對(duì)這行數(shù)據(jù)的 HIREDATE 列執(zhí)行 TO_CHAR 函數(shù),把日期類型(如 1981-05-01 的內(nèi)部存儲(chǔ)值)轉(zhuǎn)換成字符串類型(如 '1981')。
  • 條件比對(duì):判斷這個(gè)轉(zhuǎn)換后的字符串 '1981' 是否等于你指定的 '1981'。
  • 重復(fù):對(duì)表中的每一行重復(fù)第1到第3步。

索引為什么沒(méi)起作用?

因?yàn)樗饕锎娴氖窃嫉?、未?jīng)過(guò)任何處理的 HIREDATE 值,而你在查詢時(shí)使用的是 TO_CHAR(HIREDATE) 這個(gè)函數(shù)的返回值。數(shù)據(jù)庫(kù)沒(méi)法用原始的日期值去匹配一個(gè)函數(shù)的返回值,所以只能放棄索引,從頭到尾把整張表的數(shù)據(jù)都處理一遍。

這正是你在筆記中看到的高級(jí)查詢優(yōu)化問(wèn)題。

2. 另一種寫(xiě)法:為什么索引能生效?

如果你換一種寫(xiě)法,比如 WHERE HIREDATE >= TO_DATE('1981-01-01', 'YYYY-MM-DD'),過(guò)程完全不同:

  • 函數(shù)執(zhí)行一次:數(shù)據(jù)庫(kù)首先執(zhí)行 TO_DATE('1981-01-01', 'YYYY-MM-DD'),把字符串 '1981-01-01' 轉(zhuǎn)換成一個(gè)日期值(比如 1981-01-01 的內(nèi)部存儲(chǔ)數(shù)字)。
  • 索引快速定位:數(shù)據(jù)庫(kù)拿著這個(gè)日期值,直接去索引(書(shū)的目錄)里查找。
  • 直接找到數(shù)據(jù):通過(guò)索引快速定位到滿足條件的數(shù)據(jù)在磁盤(pán)上的物理位置,然后直接讀取。

索引生效的關(guān)鍵在于:
列本身HIREDATE)沒(méi)有被任何函數(shù)、計(jì)算所改變,數(shù)據(jù)庫(kù)可以直接用你在 WHERE 里給的值去跟索引里的值做比對(duì)。

3. “大數(shù)據(jù)量時(shí)慎用”是什么意思?

數(shù)據(jù)量影響程度說(shuō)明
小數(shù)據(jù)量 (幾十、幾百條)影響極微即便沒(méi)有索引,逐行掃描也快如閃電,用戶完全感受不到差異。
中等數(shù)據(jù)量 (幾萬(wàn)、幾十萬(wàn)條)影響顯著逐行掃描開(kāi)始變慢,可能需要幾秒甚至更久,用戶能明顯感覺(jué)到"卡"。
大數(shù)據(jù)量 (百萬(wàn)、千萬(wàn)條以上)災(zāi)難性影響逐行掃描會(huì)讓查詢耗時(shí)從毫秒級(jí)(有索引)變成分鐘甚至小時(shí)級(jí)(無(wú)索引,全表掃描)

舉個(gè)生活化的例子:

  • 小數(shù)據(jù)量:在一個(gè)五六個(gè)座位的家庭餐桌上找一個(gè)人,掃一眼就行,不需要名片索引。
  • 大數(shù)據(jù)量:在鳥(niǎo)巢(容納9萬(wàn)人)里找一個(gè)座位號(hào)是 '1981' 的人。如果不用座位索引,每個(gè)座位都去核對(duì),會(huì)累到崩潰。

4. 優(yōu)化建議與最佳實(shí)踐

核心原則永遠(yuǎn)不要讓函數(shù)去修飾被篩選的列本身。

要避免的寫(xiě)法 (? 索引失效)推薦寫(xiě)法 (? 索引生效)說(shuō)明
WHERE TO_CHAR(HIREDATE, 'YYYY') = '1981'WHERE HIREDATE >= TO_DATE('1981-01-01', 'YYYY-MM-DD') AND HIREDATE < TO_DATE('1982-01-01', 'YYYY-MM-DD')用范圍查詢代替函數(shù)
WHERE TO_CHAR(HIREDATE, 'YYYYMM') = '198105'WHERE HIREDATE >= TO_DATE('1981-05-01', 'YYYY-MM-DD') AND HIREDATE < TO_DATE('1981-06-01', 'YYYY-MM-DD')同上
WHERE SAL * 12 > 50000WHERE SAL > 50000 / 12讓函數(shù)作用在常量上
WHERE SUBSTR(ENAME, 1, 1) = 'S'WHERE ENAME LIKE 'S%'使用 LIKE 前綴匹配(也能利用索引)

總結(jié)一句話:

寫(xiě) WHERE 條件時(shí),讓“列”自己待著,別碰它。如果需要處理,去處理等號(hào)右邊的“值”。 這樣你的查詢才能在大數(shù)據(jù)量下保持高效。

你之前寫(xiě)的 WHERE TO_CHAR(HIREDATE, 'YYYY') = 1981 在小數(shù)據(jù)量練習(xí)時(shí)完全沒(méi)問(wèn)題,但在真正的企業(yè)生產(chǎn)環(huán)境中(數(shù)據(jù)量可能上千萬(wàn)),這種寫(xiě)法幾乎是被明令禁止的。

初學(xué)階段掌握規(guī)則即可,但養(yǎng)成好習(xí)慣會(huì)很有幫助。

到此這篇關(guān)于SQL 中日期的特殊性總結(jié)(格式符嚴(yán)格要求全大寫(xiě))的文章就介紹到這了,更多相關(guān)sql日期特殊性內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

高台县| 文水县| 根河市| 斗六市| 舞阳县| 银川市| 辰溪县| 巴里| 南阳市| 多伦县| 云梦县| 出国| 南平市| 来宾市| 抚宁县| 通州市| 封丘县| 惠水县| 乌鲁木齐市| 安塞县| 罗山县| 怀化市| 潢川县| 云梦县| 全椒县| 石城县| 深圳市| 从化市| 庐江县| 佳木斯市| 南溪县| 武汉市| 上高县| 宁武县| 东丽区| 酉阳| 绥棱县| 出国| 揭阳市| 陆丰市| 正镶白旗|