您的位置:首页 > 数据库

SQL/PLSQL:日期函数总结_20170822

2017-08-22 14:17 489 查看


首先是日期format 大小写意义不同! 大小写意义不同! 大小写意义不同!

日期格式含义补充说明
世纪CC两位数字例如:21
y一位年例如:7
yy两位年例如:17
yyy三位年例如:017
yyyy四位年例如:2017
mm两位数字两位数字
mon月份三位字符mon全小写 MON全大写 Mon首字母大写
month月份英文全拼同上
d本周中的第几天周日是第一天
dd本月中的第几天每月一号是第一天
ddd本年中的第几天每年一月一号是第一天
dy星期几(按字符集)英文环境显示缩写
day英文环境显示全拼 (day,DAY,Day)
季度Q季度一位数字 (1,2,3,4)
HH2424时制两位数字
HH1212时制
AM or PM上午 下午两位汉字或字母
mi60进制0 ~ 59
ss
例子:

1
SELECT SYSDATE as "当前日期",
2
--1.年
3
to_char(SYSDATE,'y') AS "一位年",
4
to_char(SYSDATE,'yy')AS "两位年",
5
to_char(SYSDATE,'yyy')   AS "三位年",
6
to_char(SYSDATE,'yyyy')  AS "四位年",
7
--2.月
8
to_char(SYSDATE,'mm')AS "月份" ,--月份,两位数字
9
to_char(SYSDATE,'mon')   AS "月份(缩写)",   --月份,如Jun
10
to_char(SYSDATE,'month') AS "月份(全拼)",   --月份,如JunJanuary
11
--3.日
12
to_char(SYSDATE,'d') AS "d 当周第几天", --一周中的第几天,一位数字,星期四=5
13
to_char(SYSDATE,'dd')AS "dd 当月第几天" ,   --一月中的第几天,两位数字,2月9日=9
14
to_char(SYSDATE,'ddd')   AS "ddd 当年第几天",   --一年中的第几天,三位数字,2月9日+一月31天=40
15
--4.星期几
16
to_char(SYSDATE,'dy')   AS "dy 星期几(缩写)",
17
to_char(SYSDATE,'day')  AS "dy 星期几(全拼)",   --跟字符集变化
18
--第几周
19
to_char(sysdate,'w')   AS "这个月第几周",  --取当前时间是一个月中的第几周(从1日开始算)
20
to_char(sysdate,'ww')  AS "今年第几周",--取当前时间是一年中的第几周(从1.1开始算)
21
--季度
22
to_char(SYSDATE,'q')   AS "季度" --季度,一位数字
23
FROM dual;



日期函数

1.add_months(date, n)
给日期加减n个月。返回日期类型. n可以为负数

2.last_day(date) 返回日期中最后一天的日期

返回date月份的最后一天, 如果没有trunc(带时分秒)则是date的时分秒例2.1 找出每个月倒数第三天入职的员工

1

SELECT * FROM EMP WHERE LAST_DAY(HIREDATE) - 2 = HIREDATE;  --倒数第n天的 就减n-1


例2.2

1
SQL> select sysdate, last_day(sysdate), last_day(trunc(sysdate, 'month')) from dual;
2
3
SYSDATE 本月最后一天   本月最后一天,无时分秒
4
----------- ----------------- ------------------------------
5
2017/8/21 1 2017/8/31 16:47:3 2017/8/31
例2.3

1

select trunc(trunc(sysdate, 'MONTH') - 1, 'MONTH') first_day_last_month


2

--或者to_date(extract(year from sysdate) ||extract(month from sysdate) -1,'yyyymm')


3

,trunc(sysdate, 'MONTH') - 1 / 86400 last_moment_of_last_month


4

,trunc(sysdate, 'MONTH') first_day_cur_month


5

,last_day(trunc(sysdate, 'MONTH')) + 1 - 1 / 86400 last_day_cur_month


6

from dual;




3 months_between(晚,早) 月份差 晚 - 早 = 正数

1
select ceil(months_between(sysdate,sysdate-365*2)) from dual;

4 next_day(date,day) 下一个星期几

其中英文环境下星期几支持的格式为:'DAY' = Monday ~ Sunday'DY' = Mon-Sun'D' = 1-7 (1为星期日!)例如:



1

alter SESSION set NLS_DATE_LANGUAGE='SIMPLIFIED CHINESE'; --中文环境使用 : 星期日 ~ 星期一


2

select next_day(sysdate, '星期日') 下周日,


3

next_day(sysdate, 1) 下周日


4

from dual;


5



6

alter SESSION set NLS_DATE_LANGUAGE=AMERICAN ;  --英文环境使用 : Sun ~ Mon 或者 Sunday ~ Monday


7

select next_day(sysdate,'Sun'), next_day(sysdate,'Sunday'),


8

next_day(sysdate, 1) 下周日


9

from dual;


10



11

/*


12

无论中文/英文环境 next_day(date,1) 都好使!


13

*/


5,round() 舍入到最接近的日期 )

1
select sysdate
2
  ,round(sysdate) 不加参数默认四舍五入到天
3
  ,round(sysdate, 'day') 四舍五入到本周day --舍入到星期日 而不是星期一!!!
4
  ,round(sysdate, 'month') 四舍五入到本月month
5
  ,round(sysdate, 'year') 四舍五入本到year
6
from dual;



6 trunc() 截断到最接近的日期,单位为天 ,返回的是日期类型

select sysdate ,trunc(sysdate) 截断当前日期 --返回当前日期,无时分秒 ,trunc(sysdate, 'day') 截断到本周day --返回当前星期的星期天,无时分秒 ,trunc(sysdate, 'month') 截断到本月1号month --返回当前月的1日,无时分秒 ,trunc(sysdate, 'year') 截断到year --返回当前年的1月1日,无时分秒from dual;


其它日期函数

1.extract()

函数:从给定的日期中抽取出特定的部分 , 返回类型是number

SELECT EXTRACT ([YEAR] | [MONTH] | [DAY] | [HOUR] | [MINUTE] | [SECOND] ...还可以取出时间戳 不常用略了FROM [datetime_value_expression] |[interval_value_expression]);


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;

6.new_time() 不同时区的处理

用法: select new_time(date, timezone1, timezone2) from dual;功效: 把timezone1时区的日期转换为timezone2时区的日期例如:select to_char( NEW_TIME( sysdate, 'GMT','EST'), 'dd/mm/yyyy hh:mi:ss') ,sysdatefrom dual;

7,greatest()返回日期列表中最晚日期

select greatest('01-1月-04','04-1月-04','10-2月-04') from dual;

时间 & 时区

概念:地球分24个时区,东西各12个。一个时区代表1个小时。时区值通常以绝对偏移量格式来表示:带正负号的小时:分钟。
东时区为正的,西时区为负的。时区一旦确定了,日期时间函数的返回值就参照该时区来返回。
oracle中,时区分为客户端的和服务器的两种,分别设置。1.查看数据库,会话时区:SELECT DBTIMEZONE, --查看数据库所在时区 SESSIONTIMEZONE --查看会话所在时区 FROM DUAL;

DB所在时区 +00:00 -->意味着当前的数据库使用OS所设置的时区,它在本人的计算机上设置为PST

注意:设置客户端的时区使用会话参数:time_zoneDBA通过指定手工建库时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'; --不同操作系统,可能不支持ALTER DATABASE SET TIME_ZONE = 'PST'; --本地的时区设置为太平洋标准时间
6.获取时区的时差 tz_offset()select tz_offset('PST') from dual;

7.获取时区名select tzname,tzabbrev from v$timezone_names;

8.将时间从时区1转换到时区2new_time(date,time_zone1,time_zone2)

TIMESTAMP类型

是DATE数据类型的扩展,有3种:TIMESTAMP(n) 时间精确到秒的小数点后n位(四舍五入)

TIMESTAMP(n) WITH TIME ZONE 带时区的时间戳

TIMESTAMP(n) WITH LOCAL TIME ZONE 带本地时区的时间戳

其中n:小数秒精度取值范围是0-9。默认是6(微秒 ms)

特别注意:最后一种带本地时间戳的timestamp类型的列,它的值在保存到表中时,会按照数据库的时区进行自动转换;当从表中把该类型的列值取出来时,有按照客户端的时区做自动转换。前两种时间戳不会做这样的转行简单说:保存时 => 按照DB服务器的时区存数(不变了)
取数时 => 按照客户端的时区做自动
例子:



1

--创建订单表


2

CREATE TABLE web_orders


3

  (  order_dateTIMESTAMP WITH TIME ZONE, --订货时间使用 带时区 的时间戳


4

 delivery_time TIMESTAMP WITH local TIME ZONE--送货时间使用 带本地时区 的时间戳


5

);


6



7

--美国客户插入订单


8

INSERT INTO web_orders VALUES (current_date, current_timestamp + 2); COMMIT;


9



10

--国内的物流哥们查询,看到正确的时间(东八区的时间)


11

SELECT * FROM   web_orders;


12



13

--美国客户查询。自动转到西五区的日期


14

SELECT * FROM   web_orders;



时间戳有关函数:

函数名含义返回类型
localtimestamp会话当前的时间戳TIMESTAMP
current_timestamp会话当前的时间戳+时区TIMESTAMP WITH TIME ZONE
systimestampDB当前的时间戳+时区 TIMESTAMP WITH TIME ZONE
from_tz(timestamp,time_zone)将时间和时区合并,返回一个TIMESTAMP WITH TIME ZONE
sys_extract_utc(x)将x的时区去掉转换成UTC的时间TIMESTAMP
to_timestamp(x[,fmt])将x转换为时间戳TIMESTAMP
to_timestamp_tz(x[,fmt])将x转换为时间戳+时区TIMESTAMP WITH TIME ZONE
cast('22-8月-17' as timestamp)将串转成时间戳三种都可以


时间间隔类型(略)

INTERVAL数据类型用来存储两个日期值之间的差值。有两类INTERVAL:

INTERVAL YEAR(year_precision) TO MONTH

INTERVAL DAY(day_precision) TO SECOND(fractional_seconds_precision)

说明:

year_precision是YEAR字段的精度,取值范围0—9,默认为2.

day_precision 是DAY字段的最大值(取值范围0—9,默认为2. )

fractional_seconds_precision 是小数秒的精度,取值范围0—9,默认为6.

例子

1、使用年到月的间隔

1
create table warranty(
2
prod_id number,产品编号
3
  warranty_tiem interval year(3) to month   --担保时间,year(3)   --年的部分最少有三位
4
);
5
注意间隔类型的字面量写法:ansi语法
6
insert into warranty values(123,interval '8' month);
7
SQL 错误: ORA01873: 间隔的前导精度太小
8
insert into warranty values(456,interval '200' year);  --必须指定年的精度有3位
9
insert into warranty values(456,interval '200' year(3));   --正确写法
10
11
注意间隔类型的字面量写法,oracle简单语法:'年-月'
12
insert into warranty values(789,'200-11');  --200年 零 11个月简单写法
2、使用天到秒的间隔

1

create table lab(


2

exp_id number,


3

test_time interval day to second  --day不指定精度默认位2 秒精度默认为6


4

);


5

实验123的测试时间是90天一次


6

insert into lab values(123,'90 00:00:00');


7

insert into lab values(456, interval '06 03:30:16' day to second);


8

select * from lab;


9

间隔类型的使用常用于日期的加减运算中


时间应用举例

0 显示数字的英文拼写:

select to_char( to_date(222,'J'),'Jsp') from dual ; --Two Hundred Twenty-Two

这个是oracle的特殊用法,也不常用,就是显示数字的英文读法就是固定这么用的,没有其他用法。不要钻这个牛角尖

1 设定语言环境

1
select id, active_date from table1
2
UNION
3
select 1, TO_DATE(null) from dual;
4
select to_char(sysdate, 'day') 星期几
5
  ,to_char(sysdate, 'dy', 'NLS_DATE_LANGUAGE = American') 英文缩写
6
  ,to_char(sysdate, 'day', 'NLS_DATE_LANGUAGE = American') 英文全拼
7
from dual;



设置日期语言:
ALTER SESSION SET NLS_DATE_LANGUAGE='AMERICAN';
或者
TO_DATE ('2002-08-26', 'YYYY-mm-dd', 'NLS_DATE_LANGUAGE = American')

时间为null的用法



1

select id, active_date from table1


2

UNION


3

select 1, TO_DATE(null) from dual;


注意要用TO_DATE(null)



计算时间差

注:oracle时间差是以天数为单位,所以换算成年月,日

select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))/365) as spanYears from dual //时间差-年
select ceil(moths_between(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))) as spanMonths from dual //时间差-月
select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))) as spanDays from dual //时间差-天
select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))*24) as spanHours from dual //时间差-时
select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))*24*60) as spanMinutes from dual //时间差-分
select floor(to_number(sysdate-to_date('2007-11-02 15:55:03','yyyy-mm-dd hh24:mi:ss'))*24*60*60) as spanSeconds from dual //时间差-秒

更新时间

注:oracle时间加减是以天数为单位,设改变量为n,所以换算成年月,日
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n*365,'yyyy-mm-dd hh24:mi:ss') as newTime from dual //改变时间-年
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),add_months(sysdate,n) as newTime from dual //改变时间-月
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n,'yyyy-mm-dd hh24:mi:ss') as newTime from dual //改变时间-日
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n/24,'yyyy-mm-dd hh24:mi:ss') as newTime from dual //改变时间-时
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n/24/60,'yyyy-mm-dd hh24:mi:ss') as newTime from dual //改变时间-分
select to_char(sysdate,'yyyy-mm-dd hh24:mi:ss'),to_char(sysdate+n/24/60/60,'yyyy-mm-dd hh24:mi:ss') as newTime from dual //改变时间-秒

计算今年总共有多少天



select add_months(trunc(sysdate,'year'), 12) - trunc(sysdate,'year') from dual;
结果= 365闰年366天

查找2002-02-28至2002-02-01间除星期一和七的天数



1

网上方法:


2

select count(*)


3

from (select rownum - 1 rnum


4

   from all_objects  --> 不太稳吧老哥...


5

  where rownum <= to_date('2002-02-28', 'yyyy-mm-dd') - to_date('2002-02-01','yyyy-mm-dd') + 1)


6

where to_char(to_date('2002-02-01', 'yyyy-mm-dd') + rnum - 1, 'D') not in ('7', '1');


7



8

我的方法:


9

select count(*)


10

from (select to_char(to_date('2002-02-01', 'yyyy-mm-dd') + level - 1, 'D') as xqj --取第一天的星期几开始迭代


11

  from dual  --> 很稳


12

connect by level <= to_date('2002-02-28', 'yyyy-mm-dd') - to_date('2002-02-01', 'yyyy-mm-dd') + 1)


13

where xqj not in (7, 1);


14



计算小时,分,秒,毫秒
select
Days,
A,
TRUNC(A*24) Hours,
TRUNC(A*24*60 - 60*TRUNC(A*24)) Minutes,
TRUNC(A*24*60*60 - 60*TRUNC(A*24*60)) Seconds,
TRUNC(A*24*60*60*100 - 100*TRUNC(A*24*60*60)) mSeconds
from
(
select
trunc(sysdate) Days,
sysdate - trunc(sysdate) A
from dual
)
select * from tabname
order by decode(mode,'FIFO',1,-1)*to_char(rq,'yyyymmddhh24miss');

floor((date2-date1) /365) 作为年
floor((date2-date1, 365) /30) 作为月
d(mod(date2-date1, 365), 30)作为日.

和客户端有关的日期时间函数:3个

current_date current_timestamp localtimestamp
三个都返回客户端的当前日期和时间,区别在于值的数据类型不一样

sessiontimezone:该函数返回客户端的时区设置

查看系统各个时间函数:

select sessiontimezone ,
current_date ,
current_timestamp ,
localtimestamp
from dual; ---(注意三个时间函数的精度)

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息