我刚刚审核了OCA认证问题,我意识到有些事情是不正确的。他们问:
请提供所有用户的招聘时间(HR用户) 升序
所以我写了下一个查询:
SELECT employee_id, first_name, last_name, hire_date
FROM employees
WHERE hire_date BETWEEN '01/01/80' AND '01/01/99'
ORDER BY hire_date;
并且instructoe说这是不正确的,因为数据时间不正确!应该是'01 -JAN-80'。什么?这太不可思议了!
我的笔记本电脑上没有安装数据库,但我确信我上次工作时多次运行此查询,数据格式为/
而不是-
。
欢迎提出任何建议。
更新
我刚用xe 10g进行了测试,肯定是/
而不是-
:
答案 0 :(得分:4)
你和教练都不正确。你们中的任何一个偶尔都可能是正确的。
如果将日期与字符串进行比较,Oracle必须将字符串转换为日期。为此,它使用会话的当前NLS_DATE_FORMAT
。不同的客户端将具有不同的默认值NLS_DATE_FORMAT
- 不同的区域使用不同的默认格式,不同的个人将更喜欢不同的格式。如果您依赖隐式转换,只要会话的NLS_DATE_FORMAT
与您的期望不符,您的代码就会失败。并且,不可避免地,这意味着代码将在最不合适的时刻失败。
您应该始终将日期与日期进行比较,而不是将日期与字符串进行比较。在Oracle中有两种方法可以做到这一点。首先,您可以使用带有适当格式字符串的显式TO_DATE
,即
SELECT employee_id, first_name, last_name, hire_date
FROM employees
WHERE hire_date BETWEEN to_date('01/01/80','mm/dd/rr') AND to_date('01/01/99','mm/dd/rr')
ORDER BY hire_date;
其次,您可以使用ANSI日期文字。 ANSI日期文字始终使用格式YYYY-MM-DD
SELECT employee_id, first_name, last_name, hire_date
FROM employees
WHERE hire_date BETWEEN date '1980-01-01' AND date '1999-01-01'
ORDER BY hire_date;
答案 1 :(得分:3)
就个人而言,我不依赖隐式转换。这常常导致意外的悲伤。如果要求在日期范围之间提供过滤器,我会明确的。选择你想要的任何格式,但如果它可能令人困惑,那么尽量消除尽可能多的混淆:
SELECT employee_id, first_name, last_name, hire_date
FROM employees
WHERE hire_date BETWEEN TO_DATE('JAN-01-1980', 'MON-DD-YYYY')
AND TO_DATE('JAN-01-1999', 'MON-DD-YYYY')
ORDER BY hire_date;