在 Oracle SQL 中比较日期

Posted

技术标签:

【中文标题】在 Oracle SQL 中比较日期【英文标题】:Comparing Dates in Oracle SQL 【发布时间】:2012-04-28 00:41:37 【问题描述】:

我试图让它显示 1994 年 6 月 20 日之后雇用的员工人数,

Select employee_id, count(*)
From Employee
Where to_char(employee_date_hired, 'DD-MON-YY') > 31-DEC-95; 

但我收到一个错误提示

"JUN' 无效标识符。

请帮忙,谢谢!

【问题讨论】:

请注意,您可以使用> <BETWEEN '' AND '' 【参考方案1】:

31-DEC-95 不是字符串,20-JUN-94 也不是。它们是最后添加了一些额外内容的数字。这应该是 '31-DEC-95''20-JUN-94' - 请注意单引号 '。这将使您能够进行字符串比较。

但是,您没有进行字符串比较; 您正在进行日期比较。您应该将字符串转换为日期。通过使用内置的TO_DATE() 函数或date literal。

TO_DATE()

select employee_id
  from employee
 where employee_date_hired > to_date('31-DEC-95','DD-MON-YY')

这个方法有一些不必要的陷阱

正如 cmets 中指出的 a_horse_with_no_name,DEC 不一定表示 12 月。这取决于您的 NLS_DATE_LANGUAGENLS_DATE_FORMAT 设置。为了确保您与任何语言环境中的工作进行比较,您可以改用 datetime format model MM 95 年不准确。你知道你的意思是 1995 年,但如果是 50 年,那是 1950 年还是 2050 年?最好是明确的
select employee_id
  from employee
 where employee_date_hired > to_date('31-12-1995','DD-MM-YYYY')

日期文字

日期文字是 ANSI 标准的一部分,这意味着您不必使用 Oracle 特定的函数。使用文字时,必须YYYY-MM-DD 格式指定日期,并且不能包含时间元素。

select employee_id
  from employee
 where employee_date_hired > date '1995-12-31'

请记住,Oracle 日期数据类型包含时间元素,因此没有时间部分的日期等同于 1995-12-31 00:00:00

如果要包含时间部分,则必须使用时间戳文字,其格式为 YYYY-MM-DD HH24:MI:SS[.FF0-9]

select employee_id
  from employee
 where employee_date_hired > timestamp '1995-12-31 12:31:02'

更多信息

NLS_DATE_LANGUAGE 派生自 NLS_LANGUAGENLS_DATE_FORMAT 派生自 NLS_TERRITORY。这些是在您最初创建数据库时设置的,但可以通过更改初始化参数文件(仅在确实需要时)或在会话级别使用ALTER SESSION 语法来更改它们。例如:

alter session set nls_date_format = 'DD.MM.YYYY HH24:MI:SS';

这意味着:

DD 数字日期,1 - 31 MM 一年中的数字月份,01 - 12(一月是 01) YYYY 4 位数年份 - 在我看来,这总是优于 2 位数年份 YY,因为与您所指的世纪没有混淆。 HH24 一天中的小时,0 - 23 MI 分钟,0 - 59 SS 秒,0-59

您可以通过查询V$NLS_PARAMETERSs 找到您当前的语言和日期语言设置,并通过查询V$NLS_VALID_VALUES 找到所有有效值。

进一步阅读

Format models

顺便说一句,如果你想要count(*),你需要按employee_id分组

select employee_id, count(*)
  from employee
 where employee_date_hired > date '1995-12-31'
 group by employee_id

这会给你计数 per employee_id

【讨论】:

+1 用于在 to_date() 中使用格式掩码。请注意,由于语言设置不同,这仍然可能在不同的环境中失败。 DEC 不一定总是有效的月份。通常最好使用数字而不是名称 可以使用 ANSI 文字指定时间 - 您只需指定 timestamp 文字而不是 date 文字:timestamp '2015-01-30 19:42:04'(因为在 ANSI SQL a date 数据类型没有时间,只有timestamp 数据类型有)。 ANSI 日期文字确实是一种比较每次都必须键入 TO_DATE 和 Date-Format 的简洁方式。适合像我这样的 LAZY 开发人员。需要注意的一件事是DATE 2016-04-01 真的意味着2016-04-01 00:00:00。我认为这种语法从 Oracle 9i 开始就有效,因为这是将 ANSI-SQL 语法引入 Oracle 的地方。 我的想法在过去 4 年中发生了显着变化@Leon :-)' 我已经更新了答案。我曾提到日期文字不包含时间元素,但正如您所说,我已经更明确地指出了这一点。 9i 扩展支持大约在 6 年前结束……并在 14 年前发布。对于绝大多数用户来说,它应该不再相关。 不,这是非常不同的@Alireza。 define is a SQL*Plus command that substitutes whatever you've defined into all substitution variables with that name。 ALTER SESSION is a statement that allows you to modify some database parameters or settings for the duration of that session【参考方案2】:

单引号必须在那里,因为日期转换为字符。

选择employee_id,count(*) 来自员工 其中 to_char(employee_date_hired, 'DD-MON-YY') > '31-DEC-95';

【讨论】:

此 SQL 使用隐式日期格式,它并不总是有效。 它只适用于您的特定 NLS_* 设置,它可能不适用于其他客户端或服务器。接受的答案解释了为什么明确的日期格式很重要。 此方法是比较字符串,而不是日期。第二个字符串以“3”开头,因此比较的工作方式类似于“字母顺序”。有趣的是,如果您使用像 YYYY-MM-DD 这样的格式,这种类型的比较实际上是有效的(有点意外)。但是,当然,最好将日期与日期进行比较......【参考方案3】:

结论,

to_char 以自己的方式工作

所以,

始终使用这种格式 YYYY-MM-DD 进行比较 而不是 MM-DD-YYDD-MM-YYYY 或任何其他格式

【讨论】:

【参考方案4】:

您可以按如下方式使用 trunc 和 to_date:

select TO_CHAR (g.FECHA, 'DD-MM-YYYY HH24:MI:SS') fecha_salida, g.NUMERO_GUIA, g.BOD_ORIGEN, g.TIPO_GUIA, dg.DOC_NUMERO, dg.* 
from ils_det_guia dg, ils_guia g
where dg.NUMERO_GUIA = g.NUMERO_GUIA and dg.TIPO_GUIA = g.TIPO_GUIA and dg.BOD_ORIGEN = g.BOD_ORIGEN
and dg.LAB_CODIGO = 56 
and trunc(g.FECHA) > to_date('01/02/15','DD/MM/YY')
order by g.FECHA;

【讨论】:

【参考方案5】:

来自您的查询:

Select employee_id, count(*) From Employee 
Where to_char(employee_date_hired, 'DD-MON-YY') > '31-DEC-95' 

我认为它不显示 1994 年 6 月 20 日之后雇用的员工人数。如果要显示员工人数,可以使用:

Select count(*) From Employee 
Where to_char(employee_date_hired, 'YYYMMMDDD') > 19940620 

我认为最佳做法是比较您可以使用的日期:

employee_date_hired > TO_DATE('20-06-1994', 'DD-MM-YYYY');
or
to_char(employee_date_hired, 'YYYMMMDDD') > 19940620;

【讨论】:

以上是关于在 Oracle SQL 中比较日期的主要内容,如果未能解决你的问题,请参考以下文章

如果仅按日和月将两个日期与 Oracle SQL 进行比较

oracle sql日期比较

日期比较返回异常结果 - SQL Oracle

在 oracle 中比较日期与 sysdate

Oracle SQL - 比较多行与日期

Oracle两个日期类型字段怎么比较大小