Sql 如何在Oracle中比较日期?
我认为这是一个简单的问题,但谷歌并没有帮上很大的忙。也许我不擅长我正在寻找的东西Sql 如何在Oracle中比较日期?,sql,oracle,date-arithmetic,Sql,Oracle,Date Arithmetic,我认为这是一个简单的问题,但谷歌并没有帮上很大的忙。也许我不擅长我正在寻找的东西 SELECT ORDER_NUMB, CUSTOMER_NUMB, ORDER_DATE FROM ORDERS WHERE FORMAT(ORDER_DATE, 'DD-MMM-YYYY') = '07-JUN-2000'; 它告诉我我使用的标识符无效。我试过使用MON而不是MMM,但这也没用 不确定它是否有任何区别,但我使用的是Oracle SQL Developer。我不认为格式是Oracle函数 我想你的
SELECT ORDER_NUMB, CUSTOMER_NUMB, ORDER_DATE
FROM ORDERS
WHERE FORMAT(ORDER_DATE, 'DD-MMM-YYYY') = '07-JUN-2000';
它告诉我我使用的标识符无效。我试过使用MON
而不是MMM
,但这也没用
不确定它是否有任何区别,但我使用的是Oracle SQL Developer。我不认为
格式
是Oracle函数
我想你的意思是到\u CHAR
SELECT ORDER_NUMB, CUSTOMER_NUMB, ORDER_DATE
FROM ORDERS
WHERE TO_CHAR(ORDER_DATE, 'DD-MMM-YYYY') = '07-JUN-2000';
尝试
到字符(订单日期,'DD-MON-YYYY')
与您的日期使用相关的多个问题:
其中格式(订单日期,'DD-MMM-YYYY')='07-JUN-2000'
To display : Use TO_CHAR
Any date arithmetic/comparison : Use TO_DATE
性能瓶颈:
假设在日期列上有一个常规的B树索引。现在,下面的过滤器谓词将永远不会使用索引,因为它是to_CHAR函数:
WHERE TO_CHAR(ORDER_DATE, 'DD-MM-YYYY') = '07-06-2000';
因此,在上述查询中使用TO_CHAR完全没有意义,因为它不比较日期,也不能提供良好的性能
正确的方法:
进行日期比较的正确方法是:
WHERE ORDER_DATE = TO_DATE('07-JUN-2000','DD-MON-YYYY','NLS_DATE_LANGUAGE=ENGLISH');
它将使用ORDER_DATE列上的索引,因此在性能方面会更好。此外,它还比较日期而不是字符串
正如我已经说过的,当您的日期中没有时间元素时,您可以使用ANSI date literal,它是NLS独立的,也不需要编写代码
WHERE ORDER_DATE = DATE '2000-06-07';
它使用固定格式'YYYY-MM-DD'尝试以下操作:
SELECT ORDER_NUMB, CUSTOMER_NUMB, ORDER_DATE
FROM ORDERS
WHERE trunc(to_date(ORDER_DATE, 'DD-MMM-YYYY')) = trunc(to_date('07-JUN-2000'));
为什么要将日期转换为字符串来进行比较?为什么不在订单日期为'2000-06-07'的地方执行
?订单日期的数据类型是什么?如果是日期,则需要其中订单日期=截止日期('07/06/2000','dd/mm/yyyy')
。这假设order_date列中没有存储时间元素(即存储的所有内容都在午夜)。您在Oracle手册中的何处找到了format()
函数?为什么您接受了完全错误的答案?@Siyual'2000-06-07'
是字符串,而不是日期。您的LHS是正确的,但是,您必须在RHSW上使用TO_DATE或ANSI DATE Literal转换右侧是否更好?(如果订单日期被编入索引…)一个更大的问题是,为什么要这么做?为什么不与标准日期格式进行比较呢?正如Siyual已经建议的那样。是的,比我建议的要好。老实说,我一直都是这样做的,所以我知道我可以直接比较日期字段。我猜很多人最终可能更喜欢转换成char,因为他们不知道数据库以何种格式存储数据,也不想费心去弄清楚(似乎我属于这样的群体:-)这是完全错误的,应该始终避免。永远不要将字符串与日期进行比较。始终使用TO_DATE或ANSI DATE Literal将字符串显式转换为日期。@Veverke首先,ANSI DATE Literal是NLS独立的,而且它没有时间部分。第二,TO_DATE倾向于NLS设置,我已经提到了这一点。你确定你建议的是Oracle而不是SQL Server上的内容吗?更好的方法是在参数中使用to_date
,而不是在列中使用to_char
。最好使用to_char(订单日期,'DD-MM-YYYY')='07-06-2000'
为了独立于会话NLS\u DATE\u LANGUAGE
@Wernfried,我真的很想看看证据。我从未在现实世界中听说过这种做法。@LalitKumarB,Wernfried,OP比较RHS中sring格式的日期,并询问为什么它抛出无效标识符。我觉得我的回答澄清了问题question@Lalit库马尔B:比较包含日期部分的字符串没有什么错。它通常非常可读(例如,to_char(mydate,'yyyyymm')='201510'
)。不过,Wernfried的评论很重要:在处理月份名称时,应该指定日期语言。所以这是对这个问题的正确答案,只是它本可以更好:——)@Wernfried你在哪里看到OP讲述了关于时间部分的事情?“ANSI日期文字不支持任何时间分数值,只支持日期。您在哪里看到我的答案没有关注ANSI日期文字的用法?我已经清楚地提到“当您只处理日期而不处理时间部分时,最好使用ANSI日期文字。”。“@Wernfried似乎你没有正确阅读我的答案。我在第3点中明确提到,“当只处理日期而不处理时间部分时,最好使用ANSI日期文字。”。那么,这有什么错呢?我愿意接受你的评论:-)是的,我错过了,对不起。但是,其中订单日期=截止日期('07-JUN-2000','DD-MON-YYYY')
依赖于会话NLS\u日期语言
@Wernfried没有问题。NLS与TO_DATE的依赖关系是另一回事。ANSI日期文字是完全独立于NLS的,因为它遵循标准格式。无论如何,我将编辑我的答案以添加到日期的NLS依赖项。它与数据类型无关,但与值有关。列上的常规索引将在索引结构中存储列值,而在列上应用函数不会命中常规索引,因为我们不再寻找这些索引值。此外,其中订单日期=截止日期('07-JUN-2000','DD-MON-YYYY','NLS\U日期语言=英语')代码>将使用订单日期列上的常规索引。因此,在性能方面也要好得多
WHERE ORDER_DATE = TO_DATE('07-JUN-2000','DD-MON-YYYY','NLS_DATE_LANGUAGE=ENGLISH');
WHERE ORDER_DATE = DATE '2000-06-07';
SELECT ORDER_NUMB, CUSTOMER_NUMB, ORDER_DATE
FROM ORDERS
WHERE trunc(to_date(ORDER_DATE, 'DD-MMM-YYYY')) = trunc(to_date('07-JUN-2000'));