1. 程式人生 > >SQL/PLSQL:日期函式總結

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區分)

例如 :

  1. selec trunc(sysdate,'month'), --按月進行截斷,直接截斷到給定日期的本月的1號

  2. trunc(sysdate,'year') --按年進行截斷,直接截斷到給定日期的本年月的1月1號

  3. 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;