我已经为我的同事编写了一个查询,其中涉及在给定日期从Oracle Express g11中提取数据。 查询使用的日期是上一个工作日(昨天或星期五)。
出于某种原因,同一查询会返回不同的数字来表示星期几。
示例:
SELECT TRUNC('13June2016') - TRUNC('13June2016', 'D')
FROM DUAL
在我的计算机上运行时,此查询返回0
,但在我的同事的计算机上,它返回1
。这种情况发生在我们可用的每个SQL客户端/接口上。
据我所知,我们在数据库中的计算机和用户设置相同,但显然有些设置已关闭。
坦率地说,我试图谷歌在哪里出现这种差异,但我收到了很多无关的结果。我迷路了,因为我甚至不知道在哪里寻找可以解释这种差异的设置(或者不确定)。
答案 0 :(得分:1)
D
格式修饰符依赖于会话的NLS设置:
alter session set nls_territory = 'America';
alter session set nls_date_format = 'YYYY-MM-DD';
select to_char(date '2016-06-13', 'D') char_d,
trunc(date '2016-06-13', 'D') trunc_d,
date '2016-06-13' - trunc(date '2016-06-13', 'D') diff1,
trunc(sysdate) - trunc(sysdate, 'D') diff2
from dual;
C TRUNC_D DIFF1 DIFF2
- ---------- ---------- ----------
2 2016-06-12 1 1
alter session set nls_territory = 'United Kingdom';
alter session set nls_date_format = 'YYYY-MM-DD';
select to_char(date '2016-06-13', 'D') char_d,
trunc(date '2016-06-13', 'D') trunc_d,
date '2016-06-13' - trunc(date '2016-06-13', 'D') diff1,
trunc(sysdate) - trunc(sysdate, 'D') diff2
from dual;
C TRUNC_D DIFF1 DIFF2
- ---------- ---------- ----------
1 2016-06-13 0 0
(有趣的是,我在使用trunc(date '2016-06-13')
时偶然发现错误14073795;截断是多余的,看起来非常不一致 - 更改列别名会使其显示或消失 - 所以我认为它不相关到你所看到的。)
因此,您和您的同事似乎将您的PC放在不同的区域设置中,并且您测试的客户端继承了区域设置或以不同方式明确设置区域。
要获得一致的结果,无论语言环境/ NLS设置如何,您都可以使用the 'IW' format element instead of 'D',因为这样做:
与ISO 8601标准(即星期一)定义的日历周的第一天相同的一周
alter session set nls_territory = 'America';
alter session set nls_date_format = 'YYYY-MM-DD';
select to_char(date '2016-06-13', 'IW') char_iw,
trunc(date '2016-06-13', 'IW') trunc_iw,
date '2016-06-13' - trunc(date '2016-06-13', 'IW') diff1,
trunc(sysdate) - trunc(sysdate, 'IW') diff2
from dual;
CH TRUNC_IW DIFF1 DIFF2
-- ---------- ---------- ----------
24 2016-06-13 0 0
alter session set nls_territory = 'United Kingdom';
alter session set nls_date_format = 'YYYY-MM-DD';
select to_char(date '2016-06-13', 'IW') char_iw,
trunc(date '2016-06-13', 'IW') trunc_iw,
date '2016-06-13' - trunc(date '2016-06-13', 'IW') diff1,
trunc(sysdate) - trunc(sysdate, 'IW') diff2
from dual;
CH TRUNC_IW DIFF1 DIFF2
-- ---------- ---------- ----------
24 2016-06-13 0 0
您可以详细了解how the format models are used in trunc()
and round()
functions,更一般地了解date format models。
依赖隐式转换也不是一个好主意; TRUNC('13June2016', 'D')
使用会话的NLS_DATE_FORMAT
设置隐式将字符串'13June2016'转换为日期。在具有不同设置的会话中运行该错误。并且TRUNC('13June2016')
是多余的,因为隐式转换的日期已经将其时间设置为午夜,如果它没有错误。
您应该始终显式转换字符串并指定格式模型,例如TRUNC(TO_DATE('13June2016', 'DDMonthYYYY', 'NLS_DATE_LANGUAGE=ENGLISH'), 'D')
(如果会话日期语言是其他内容,则需要第三个参数,这将停止6月被识别;或者更简单地使用ISO日期文字,如DATE '2016-06-13'
。您可能正在使用日期时间当然,你的真实代码中的变量。