※五種日期
sessiontimezone:Asia/Taipei current_date:20-3月 -16 sysdate:20-3月 -16 current_timestamp:20-3月 -16 05.43.14.965000000 下午 ASIA/TAIPEI localtimestamp:20-3月 -16 05.43.14.965000000 下午 systimestamp:20-3月 -16 05.43.14.965000000 下午 +08:00
※可以使用「+」和「-」來加減天數
※如果想改變顯示的效果,可用(DD、MON…等格式,下面的to_char(日期)會說明)
ALTER SESSION SET NLS_DATE_FORMAT = 'DD-MON-YYYY HH24:MI:SS';
ALTER SESSION SET TIME_ZONE = '-5:0';
※日期相減
SELECT CURRENT_DATE-hiredate, -- 12877.7442592592592592592592592592592593 SYSDATE-hiredate, -- 12877.7442592592592592592592592592592593 CURRENT_TIMESTAMP-hiredate, -- 12877 17:51:44.996 LOCALTIMESTAMP-hiredate, -- 12877 17:51:44.996 SYSTIMESTAMP-hiredate -- 12877 17:51:44.996 FROM emp where empno = 7369;
※只能相減,不能相加,左邊減右邊可得到天數
※日期相減 INTERVAL
SELECT sysdate - 30 FROM dual; SELECT sysdate - INTERVAL '30' day FROM dual; SELECT sysdate - INTERVAL '30' month FROM dual; SELECT sysdate - INTERVAL '30' year FROM dual;
※直接減其是就是 INTERVAL '天數' DAY,但如果是要減年月就要完整的寫出來
※時分秒也可以,分別是 HOUR、MINUTE、SECOND
※trunc
trunc(CURRENT_DATE):20-3月 -16 trunc(SYSDATE):20-3月 -16 trunc(CURRENT_TIMESTAMP):20-3月 -16 trunc(LOCALTIMESTAMP):20-3月 -16 trunc(SYSTIMESTAMP):20-3月 -16 trunc(CURRENT_DATE-hiredate):12877 trunc(SYSDATE-hiredate):12877
※trunc可以只留年月日,所以五種日期都一樣
※注意:假設有個欄位叫 xxx_date,格式是年月日時分秒
下 xxx_date BETWEEN to_date('2016-03-15', 'yyyy-mm-dd') AND to_date('2016-03-20', 'yyyy-mm-dd')
此時會搜尋315~319的資料如上剛好是320零點零分零秒的資料,此時將 xxx_date,加上 trunc 就可以搜尋到320的資料
※日期相減必需注意格式要一樣,像我的hiredate只有年月日,所以有時分秒的timestamp相減就會出錯
※增加月份、兩個月份相差的天數
add_months(sysdate, 3):左邊日期增加3個月 SELECT months_between(sysdate, hiredate) FROM emp where empno=7369;
※左邊減右邊的月數(會有小數點),所以可以用trunc去除(上一篇的trunc也能處理數字)
※這個方法會幫我們解決潤年的事
※轉日期和數字、求每月最後一天
to_number('101.25') to_date('2013-05-25','yyyy-mm-dd') to_timestamp('2013-05-25 20:20:20','yyyy-mm-dd hh24:mi:ss') last_day(sysdate)--每月最後一天
※hh24…等格式,後面的to_char(日期)會說明
※to_char(數字)
to_char(1234.5678, '9999.9999'),-- 1234.5678 to_char(1234.5678, '0000.0000'),-- 1234.5678 to_char(0, '9999.9999'),-- .0000 to_char(0, '0000.0000'),-- 0000.0000 to_char(0, '9'),-- 0 to_char(0, '0'),-- 0 to_char(1234.5678, '9990.9999'),-- 1234.5678 to_char(10, '0')-- ##
※右邊是給格式,只要給的不夠,就會出現「#」,至於給幾個#要看第一個參數
※to_char(日期)
官網格式說明to_char(SYSTIMESTAMP, 'yyyy'),-- 年 to_char(SYSTIMESTAMP, 'mm'),-- 月01~12 to_char(SYSTIMESTAMP, 'dd'),-- 日01~31 to_char(SYSTIMESTAMP, 'hh'),-- 時(12小時制)等同「hh12」 to_char(SYSTIMESTAMP, 'hh24'),--時(24小時制) to_char(SYSTIMESTAMP, 'mi'),-- 分0~59 to_char(SYSTIMESTAMP, 'ss'),-- 秒0~59 to_char(SYSTIMESTAMP, 'sssss'),-- 0-86399 to_char(SYSTIMESTAMP, 'ww'),-- 一年當中的第幾個星期 to_char(SYSTIMESTAMP, 'w'),-- 一個月份當中的第幾個星期 to_char(SYSTIMESTAMP, 'ddd'),-- 001~366 一年當中的第幾天 to_char(SYSTIMESTAMP, 'd'),-- 回傳1~7,星期日是1,星期六是7 to_char(SYSTIMESTAMP, 'month'),-- 顯示幾月,如「3月」 to_char(SYSTIMESTAMP, 'day')-- 顯示星期幾,如「星期日」
※大小寫沒差
※有七個符號可以直接在格式裡面使用(第二個參數)
「-」「/」「,」「.」「;」「:」「"text"」
其中text表示隨便打,因為前面六種不夠用就要使用「"」包起來,然後隨個人發揮
※取得下一個星期的日期
to_char(sysdate,'day') next_day(sysdate, '星期日')
※範例的「星期日」也有可能是要打「sunday」,所以可用第一行的to_char看一下
※此範例表示依今天的日期,顯示出下一個星期日是哪一天,回傳的是date
※Extract
EXTRACT(year FROM systimestamp)-- 截取年 EXTRACT(month FROM systimestamp) EXTRACT(day FROM systimestamp) EXTRACT(hour FROM systimestamp) EXTRACT(minute FROM systimestamp) EXTRACT(second FROM systimestamp)--秒+3位的毫秒 EXTRACT(year FROM date '2001-03-05'), EXTRACT(month FROM date '2001-03-05'), EXTRACT(day FROM date '2001-03-05'), EXTRACT(hour FROM timestamp '2001-03-05 12:34:56'), EXTRACT(minute FROM timestamp '2001-03-05 12:34:56'), EXTRACT(second FROM timestamp '2001-03-05 12:34:56')
※用to_char時,大部份格式不到10的,譬如8好了,會顯示「08」,而extract不會出現0
※要注意systimestamp是有時分秒的,所以可以截取,但sysdate沒有時分秒,截取就會出錯
※如果傳進來的日期是個變數,就用date或timestamp
※date截取方式和sysdate一樣;timestamp截取方式和systimestamp一樣
※NULL判斷
nvl(null,0),-- 0 nvl(23,0),-- 23 nvl2(23,0,1),-- 0 nvl2(null,0,1),-- 1 nullif(23,23),-- null nullif(23,null)-- 23 -- nullif(null,23)編譯錯誤
※nvl第一個參數是null就回傳第二個參數,否則就回傳第一個參數
※nvl2第一個參數是null就回傳第二個參數,否則就回傳第三個參數
※nullif第一和第二個參數一樣就回傳null,否則就回傳第一個參數,第一個參數不能是null
※LNNVL
SELECT * FROM emp WHERE comm < 500; SELECT * FROM emp WHERE lnnvl(comm < 500);
※使用在where條件
※LNNVL會將條件變成相反,以上面的例子會變成「>=」,並且將NULL顯示
※NANVL
用法和NVL一樣,但用在型態是BINARY_FLOAT 或 BINARY_DOUBLE,如果不是這個型態也不會報錯,結果是有沒有用NANVL都一樣,這個我還沒試過,因為我在工作時還沒遇到這些型態※COALESCE
coalesce('a','1','2','3'),-- a coalesce(null,1,2,3),-- 1 coalesce(null,null,2,3),-- 2 coalesce(null,null,null,3),-- 3 coalesce(null,null,null,null)-- null
※除了null外,全部的參數型態都要一樣,如第一行後面的123,如果不用「'」包起來會出錯
※可以有很多參數,第一個參數是null,就判斷第二個參數是不是null,如果是,再繼續判斷第三個參數是不是null,以此類推,如果到最後都是null,就回傳null
官方一直到12c,判斷null的就這6個,而還有兩個常用的方法也能判斷null,decode和case when then else end,看這篇
※ROWID
是每一條紀錄的唯一地址,如果刪除一條記錄又新增一樣的記錄也是會不一樣※刪除多餘的記錄
-- 1. CREATE TABLE xxx AS SELECT * FROM dept; -- 2. SELECT x.*, x.ROWID FROM xxx x; -- 3. INSERT INTO xxx VALUES (10, 'ACCOUNTING', 'NEW YORK'); INSERT INTO xxx VALUES (20, 'RESEARCH', 'DALLAS'); INSERT INTO xxx VALUES (30, 'SALES', 'CHICAGO'); INSERT INTO xxx VALUES (40, 'OPERATIONS', 'BOSTON'); -- 4. SELECT MIN(ROWID) FROM xxx x GROUP BY deptno; -- 5. DELETE FROM xxx WHERE ROWID NOT IN( SELECT MIN(ROWID) FROM xxx x GROUP BY deptno );
※以下的測試是認為新增的資料,ROWID一定會比較大測試的
※1.複製dept來練習 ,之前有講過複製不會複製constraint
※2.看看目前的ROWID長什麼樣子
※3.複製一樣的資料到xxx,因為xxx沒有複製到constraint,所以可以新增多筆一樣的資料,複製個兩、三次以後,再回第2步看目前的ROWID長什麼樣子
※4.這一步是看一下最小的ROWID是和第2步是相同的,因為dept只有四筆而且每個欄位都不一樣,所以group by 哪個欄位都可以
※5.這一步就可以將大於原本的ROWID刪除了
※ROWNUM
可以顯示行號,本身和記錄沒有關係,可以把它想成資料全部都搜完後,再加上的行號所以想要有和記錄挷在一起的錯覺,就要看下SQL的功力了
SELECT ROWNUM, e.* FROM emp e WHERE ROWNUM = 1; SELECT ROWNUM, e.* FROM emp e WHERE ROWNUM <= 3; SELECT * FROM( SELECT ROWNUM r, e.* FROM emp e WHERE ROWNUM <= 10 ) t WHERE t.r >= 6;
※第一條SQL是取第一筆記錄的,但要注意只能取到第一筆和第一筆之後的記錄
※第二條SQL是取前三條記錄,ROWNUM一定要包含第一筆的記錄,和第一條SQL的道理是一樣的,所以取不到非第一筆之後的記錄,如第6到第10筆
※如果想取得第一筆之後的記錄,如第6到第10筆可以用第三條SQL的下法
先取出前10筆,然後用SELECT包起來,這樣子就可以取得到了,算是一種運用吧!
沒有留言:
張貼留言