SQL/PLSQL:日期函式總結
TO_DATE格式(以當前時間: 2017年2月9日11:25:38 為例)
1.年:
yy | 兩位年 | 顯示值:17 |
yyy | 三位年 | 顯示值:017 |
yyyy | 四位年 | 顯示值:2017 |
2.月:
mm | 兩位月 | 顯示值:11 |
3.日:
dd | 當月第幾天 | 顯示值:09 |
d | 當週第幾天 1~7 | 週日=1,週六=7 |
dy | 星期幾 Mon~Sun | |
day | 星期幾 Monday~Sunday | |
ddd | 一年中的第幾天 |
4.時
hh24 | 24小時制 | 顯示值:11 |
5.分
mi | 60進位制 | 顯示值:25 |
6.秒
ss | 60進位制 | 顯示值:38 |
日期函式
1、sysdate:得到資料庫伺服器的當前日期和時間
2、current_date:得到客戶端的當前日期和時間
因為資料庫把日期作為數字儲存,因此可以對日期進行加減運算,單位是天。
1 ) date + n : 加減幾天,n可以是負的
2) date + n/24 : 加減幾個小時
3) date - date : 相差的天數
例1:給當前日期分別加減3天 sysdate +/- 3
例2:給當前日期加1個小時
select to_char(sysdate + 1/24,'YYYYMMDD HH24:MI:SS')
from dual;
MONTHS_BETWEEN(date1, date2)
返回兩個日期差幾個月。 記住是 前date1 - 後date2
例如:
查詢僱員在公司工作的總月數
select last_name,months_between(sysdate,hire_date)
from employees;
ADD_MONTHS(date, n): 給日期加減N個月。N可以為負數, 加減12個月就是一年啦
例如: SELECT ADD_months(SYSDATE,-12) --一年前的今天 ADD_months(SYSDATE,+24) --兩年後的今天
FROM dual;
next_day(date,'char'): 找到從date開始的下一個星期幾的日期。char表示星期幾
NEXT_DAY(date,6) -->下個週五 (這裡6,代表星期5,因為美國日期是從星期天開始的,所以1代表的是星期天,2代表星期一,以此類推)
例如:
查詢今天之後的下一個星期一是幾月幾號? 注意字符集
select next_day(sysdate,'星期一') from dual;
ORA01846: 週中的日無效
select next_day(sysdate,'monday') from dual;
中文情況下"星期天"不識別, "星期日"才識別
ROUND(date[,'fmt']):
進位規則:秒=30,分=30,時=12,日=16,月=7; 超過上面分割線就向前一位進1
TRUNC(date [, 'fmt']): (常用,後面不接引數就是將日期的時分秒去掉,注意和round區分)
例如 :
-
selec trunc(sysdate,'month'), --按月進行截斷,直接截斷到給定日期的本月的1號
-
trunc(sysdate,'year') --按年進行截斷,直接截斷到給定日期的本年月的1月1號
-
from dual;
時間 & 時區
時區概念:地球分24個時區,東西各12個。一個時區代表1個小時。
時區值通常以絕對偏移量格式來表示:帶正負號的小時:分鐘。 東時區為正的,西時區為負的。時區一旦確定了,日期時間函式的返回值就參照該時區來返回。
1.檢視資料庫,會話時區:
SELECT DBTIMEZONE, --檢視資料庫所在時區
SESSIONTIMEZONE --檢視會話所在時區
FROM DUAL;
注意:
DBA通過指定手工建庫時CREATE DATABASE 語句的SET TIME_ZONE 子句
來設定資料庫的預設時區。如果省略,那麼預設資料庫時區是作業系統時區。
如果作業系統的時區格式是oracle不支援的,那麼就把資料庫的時區設為0時區。官方推薦資料庫的時區都使用0時區。
ALTER SESSION語句不能改變資料庫時區。
2.設定會話時區為西五區(美國東部時間)
alter session set time_zone = '-05:00'; --絕對偏移量,負為西
3.設定本會話使用資料庫的時區
alter session set time_zone = DBTIMEZONE;
4.把時區設定成本地
alter session set time_zone = local; --不同作業系統,可能不支援
5.時區設定成某地域的時區
alter session set time_zone = 'American/New_York'; --不同作業系統,可能不支援
和客戶端有關的日期時間函式:3個
current_date current_timestamp localtimestamp
三個都返回客戶端的當前日期和時間,區別在於值的資料型別不一樣
sessiontimezone:該函式返回客戶端的時區設定
檢視系統各個時間函式:
select sessiontimezone ,
current_date ,
current_timestamp ,
localtimestamp
from dual; ---(注意三個時間函式的精度)
資料庫的時區
返回資料庫的時區: 0時區
select dbtimezone from dual;
DBA通過指定手工建庫時CREATE DATABASE 語句的SET TIME_ZONE 子句
來設定資料庫的預設時區。如果省略,那麼預設資料庫時區是
作業系統時區。
如果作業系統的時區格式是oracle不支援的,那麼就把資料庫的時區設為0時區。官方推薦資料庫的時區都使用0時區。
ALTER SESSION語句不能改變資料庫時區。
TIMESTAMP型別:時間戳型別。3種
-TIMESTAMP資料型別是DATE資料型別的擴充套件:
1)TIMESTAMP (fractional_seconds_ precision)
2)TIMESTAMP (fractional_seconds_precision) WITH
TIME ZONE 帶時區的時間戳
3)TIMESTAMP (fractional_seconds_precision) WITH
LOCAL TIME ZONE 帶本地時區的時間戳
其中:fractional_seconds_precision小數秒精度取
值範圍是0-9。預設是6(微秒 ms)
特別注意:最後一種timestamp型別的列,它的值在儲存到表中時,會按照資料庫的時區進行自動轉換;當從表中把該型別的列值取出來時,有按照客戶端的時區做自動轉換。
前面兩種timestamp型別的列值不會做這樣的轉換。
例子:
--建立訂單表 CREATE TABLE web_orders ( order_date TIMESTAMP WITH TIME ZONE, --訂貨時間使用 帶時區的時間戳 delivery_time TIMESTAMP WITH local TIME ZONE --送貨時間使用 帶本地時區的時間戳 ); --美國客戶插入訂單 INSERT INTO web_orders VALUES (current_date, current_timestamp + 2); COMMIT; --美國客戶查詢。看到正確的日期(西五區的時間) SELECT * FROM web_orders; --在sqlplus中,國內的物流哥們查詢,看到正確的時間(東八區的時間) SELECT * FROM web_orders;
時間間隔型別
INTERVAL資料型別用來儲存兩個日期值之間的差值。有兩類INTERVAL:
INTERVAL YEAR(year_precision) TO MONTH
INTERVAL DAY(day_precision) TO SECOND(fractional_seconds_precision)
year_precision 是YEAR欄位的精度,取值範圍0—9,預設為2.
fractional_seconds_precision 是小數秒的精度,取值範圍0—9,預設為6.
day_precision 是DAY欄位的最大值(取值範圍0—9,預設為2. )
l=eg:
1、使用年到月的間隔
create table warranty(
prod_id number,產品編號
warranty_tiem interval year(3) to month --擔保時間,year(3)-年的部分最少有三位
);
注意間隔型別的字面量寫法:ansi語法
insert into warranty values(123,interval '8' month); --
SQL 錯誤: ORA01873: 間隔的前導精度太小
insert into warranty values(456,interval '200' year); --必須指定年的精度有3位
insert into warranty values(456,interval '200' year(3)); --正確寫法
注意間隔型別的字面量寫法,oracle簡單語法:'年-月'
insert into warranty values(789,'200-11'); 200年 零 11個月簡單寫法
2、使用天到秒的間隔
create table lab(
exp_id number,
test_time interval day to second --day不指定精度預設位2 秒精度預設為6
);
實驗123的測試時間是90天一次
insert into lab values(123,'90 00:00:00');
insert into lab values(456, interval '06 03:30:16' day to second);
select * from lab;
間隔型別的使用常用於日期的加減運算中
其它日期時間函式
1.EXTRACT 函式:從給定的日期中抽取出特定的部分
extract(.... from .....)
SELECT EXTRACT ([YEAR] [MONTH][DAY]
[HOUR] [MINUTE][SECOND]
FROM [datetime_value_expression] |
[interval_value_expression]);
例如:
select sysdate,extract(year from sysdate)
from dual;
查詢僱員入職的月份
select hire_date,extract(month from hire_date)
from employees;
2、tz_offset()
將命名地區形式的時區轉換成時區的絕對偏移量
select tz_offset('Asia/Shanghai'),
tz_offset('Canada/Yukon')
from dual;
要得到合法時區名的列表,可以查詢V$TIMEZONE_NAMES動態效能檢視。
SELECT * FROM V$TIMEZONE_NAMES;
3、to_timestamp(char,'fmt')
將字串以給定的日期格式模型轉換成時間戳
select to_timestamp('20071010 15:25:00','YYYYMMDD HH24:MI:SS')
from dual;
4、to_yminterval('year-month')
將字串轉成成年到月的間隔
將僱員的入職日期加上1年2個月
select hire_date,
hire_date + to_yminterval('01-02')
from employees;
5、to_dsinterval('day hh:mi:ss')
將字串轉成成天到秒的間隔
將僱員的入職日期加上100天10個小時
select to_char(hire_date,'YYYYMMDD HH24:MI:SS'),
to_char(hire_date + to_dsinterval('100 10:00:00'),
'YYYYMMDD HH24:MI:SS')
from employees;
MONTHS_BETWEEN(date1, date2)
返回兩個日期差幾個月。 記住是 前 - 後
ADD_MONTHS(date, n): 給日期加減幾個月。N是整數可以為負數 `注:加減12個月就是1年! SELECT ADD_months(SYSDATE,-12) FROM dual; --一年前的今天 SELECT ADD_months(SYSDATE,+24) FROM dual; --兩年後的今天next_day(date,'char'): 找到從date開始的下一個星期幾的日期。char表示星期幾 上面等價於:NEXT_DAY(date,'星期一') 例如:
例如:
查詢僱員在公司工作的總月數
select last_name,months_between(sysdate,hire_date) from employees;
NEXT_DAY(date,6) -->下個週五 (這裡6,代表星期5,因為美國日期是從星期天開始的,所以1代表的是星期天,2代表星期一,以此類推)
查詢今天之後的下一個星期一是幾月幾號? 注意字符集
select next_day(sysdate,'星期一') from dual;
ORA01846: 週中的日無效
select next_day(sysdate,'monday') from dual;
ROUND(date[,'fmt']):
進位規則:秒=30,分=30,時=12,日=16,月=7; 超過上面分割線就向前一位進1
TRUNC(date [, 'fmt']): (常用,後面不接引數就是將日期的時分秒去掉)
例如 :
規則:按月進行截斷,直接截斷到給定日期的本月的1號
按年進行截斷,直接截斷到給定日期的本年月的1月1號
select sysdate,trunc(sysdate,'month'), trunc(sysdate,'year') from dual;
時間 & 時區
時區概念:地球分24個時區,東西各12個。一個時區代表1個小時。
時區值通常以絕對偏移量格式來表示:帶正負號的小時:分鐘。 東時區為正的,西時區為負的。時區一旦確定了,日期時間函式的返回值就參照該時區來返回。
oracle中,時區分為客戶端的和伺服器的兩種,分別設定。
設定客戶端的時區使用會話引數:time_zone
1.檢視資料庫,會話時區:
select dbtimezone from dual;
select sessiontimezone from dual;
2.設定會話時區為西五區(美國東部時間)
alter session set time_zone = '-05:00'; (絕對偏移量,負為西)
3.設定本會話使用資料庫的時區
alter session set time_zone = dbtimezone;
4.把時區設定成本地
alter session set time_zone = local; -- (作業系統,可能不支援)
5.時區設定成某地域的時區
alter session set time_zone = 'American/New_York'; -- (作業系統,可能不支援)
和客戶端有關的日期時間函式:3個
current_date current_timestamp localtimestamp
三個都返回客戶端的當前日期和時間,區別在於值的資料型別不一樣
sessiontimezone:該函式返回客戶端的時區設定
檢視系統各個時間函式:
select sessiontimezone ,
current_date ,
current_timestamp ,
localtimestamp
from dual; ---(注意三個時間函式的精度)
資料庫的時區
返回資料庫的時區: 0時區
select dbtimezone from dual;
DBA通過指定手工建庫時CREATE DATABASE 語句的SET TIME_ZONE 子句
來設定資料庫的預設時區。如果省略,那麼預設資料庫時區是
作業系統時區。
如果作業系統的時區格式是oracle不支援的,那麼就把資料庫的時區設為0時區。官方推薦資料庫的時區都使用0時區。
ALTER SESSION語句不能改變資料庫時區。
TIMESTAMP型別:時間戳型別。3種
-TIMESTAMP資料型別是DATE資料型別的擴充套件:
1)TIMESTAMP (fractional_seconds_ precision)
2)TIMESTAMP (fractional_seconds_precision) WITH
TIME ZONE 帶時區的時間戳
3)TIMESTAMP (fractional_seconds_precision) WITH
LOCAL TIME ZONE 帶本地時區的時間戳
其中:fractional_seconds_precision小數秒精度取
值範圍是0-9。預設是6(微秒 ms)
特別注意:最後一種timestamp型別的列,它的值在儲存到表中時,會按照資料庫的時區進行自動轉換;當從表中把該型別的列值取出來時,有按照客戶端的時區做自動轉換。
前面兩種timestamp型別的列值不會做這樣的轉換。
例子:
--建立訂單表 CREATE TABLE web_orders ( order_date TIMESTAMP WITH TIME ZONE, --訂貨時間使用 帶時區的時間戳 delivery_time TIMESTAMP WITH local TIME ZONE --送貨時間使用 帶本地時區的時間戳 ); --美國客戶插入訂單 INSERT INTO web_orders VALUES (current_date, current_timestamp + 2); COMMIT; --美國客戶查詢。看到正確的日期(西五區的時間) SELECT * FROM web_orders; --在sqlplus中,國內的物流哥們查詢,看到正確的時間(東八區的時間) SELECT * FROM web_orders;
時間間隔型別
INTERVAL資料型別用來儲存兩個日期值之間的差值。有兩類INTERVAL:
INTERVAL YEAR(year_precision) TO MONTH
INTERVAL DAY(day_precision) TO SECOND(fractional_seconds_precision)
year_precision 是YEAR欄位的精度,取值範圍0—9,預設為2.
fractional_seconds_precision 是小數秒的精度,取值範圍0—9,預設為6.
day_precision 是DAY欄位的最大值(取值範圍0—9,預設為2. )
l=eg:
1、使用年到月的間隔
create table warranty(
prod_id number,產品編號
warranty_tiem interval year(3) to month --擔保時間,year(3)-年的部分最少有三位
);
注意間隔型別的字面量寫法:ansi語法
insert into warranty values(123,interval '8' month); --
SQL 錯誤: ORA01873: 間隔的前導精度太小
insert into warranty values(456,interval '200' year); --必須指定年的精度有3位
insert into warranty values(456,interval '200' year(3)); --正確寫法
注意間隔型別的字面量寫法,oracle簡單語法:'年-月'
insert into warranty values(789,'200-11'); 200年 零 11個月簡單寫法
2、使用天到秒的間隔
create table lab(
exp_id number,
test_time interval day to second --day不指定精度預設位2 秒精度預設為6
);
實驗123的測試時間是90天一次
insert into lab values(123,'90 00:00:00');
insert into lab values(456, interval '06 03:30:16' day to second);
select * from lab;
間隔型別的使用常用於日期的加減運算中
其它日期時間函式
1.EXTRACT 函式:從給定的日期中抽取出特定的部分
extract(.... from .....)
SELECT EXTRACT ([YEAR] [MONTH][DAY]
[HOUR] [MINUTE][SECOND]
FROM [datetime_value_expression] |
[interval_value_expression]);
例如:
select sysdate,extract(year from sysdate)
from dual;
查詢僱員入職的月份
select hire_date,extract(month from hire_date)
from employees;
2、tz_offset()
將命名地區形式的時區轉換成時區的絕對偏移量
select tz_offset('Asia/Shanghai'),
tz_offset('Canada/Yukon')
from dual;
要得到合法時區名的列表,可以查詢V$TIMEZONE_NAMES動態效能檢視。
SELECT * FROM V$TIMEZONE_NAMES;
3、to_timestamp(char,'fmt')
將字串以給定的日期格式模型轉換成時間戳
select to_timestamp('20071010 15:25:00','YYYYMMDD HH24:MI:SS')
from dual;
4、to_yminterval('year-month')
將字串轉成成年到月的間隔
將僱員的入職日期加上1年2個月
select hire_date,
hire_date + to_yminterval('01-02')
from employees;
5、to_dsinterval('day hh:mi:ss')
將字串轉成成天到秒的間隔
將僱員的入職日期加上100天10個小時
select to_char(hire_date,'YYYYMMDD HH24:MI:SS'),
to_char(hire_date + to_dsinterval('100 10:00:00'),
'YYYYMMDD HH24:MI:SS')
from employees;