首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >有日期的Dbeaver和OSD客户端的不同行为

问有日期的Dbeaver和OSD客户端的不同行为
EN

Stack Overflow用户
提问于 2022-01-18 09:23:39
回答 2查看 254关注 0票数 1

我使用Oracle数据库11g版本11.2.0.4.0

执行此查询时:

代码语言:javascript
复制
SELECT 
    CASE WHEN (DATE '2005-11-25') IN ('25/11/05') THEN
        'TRUE'
    ELSE
        'FALSE'
    END
FROM DUAL;

FALSE来自Oracle 21.4.1.349 (法语版本),TRUE来自DBeaver 21.1.4.202108020335 (法语版本)。

我知道我将日期与字符串进行比较,所以我认为结果应该是FALSE,但这可能依赖于实现。

在这些情况下,Oracle的回答是如何不同的呢?DBeaver是否在提交请求之前对日期进行预处理?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-01-18 09:37:25

由于要将日期与字符串进行比较,因此将使用会话的NLS设置将字符串隐式转换为日期。这些数据可以从您的地区派生出来,也可以由您的客户显式设置,例如通过首选项。

如果NLS_DATE_FORMAT被设置为'DD/MM/YYYY‘,那么'25/11/05’被转换为0005-11-25,所以比较是假的。如果将其设置为“DD/MM/YY”(或“DD/MM/RR”或“DD/MM/RRRR”),则将其转换为2005-11-25,因此比较是正确的。

db<>fiddle

您不应该依赖于隐式转换或NLS设置,因为您无法控制运行代码的人的环境。

票数 1
EN

Stack Overflow用户

发布于 2022-01-18 09:37:35

这取决于会话使用的NLS_DATE_FORMAT。

Oracle将隐式地将查询转换为相当于:

代码语言:javascript
复制
SELECT CASE WHEN DATE '2005-11-25' IN (
              TO_DATE(
                '25/11/05',
                (SELECT VALUE FROM NLS_SESSION_PARAMETERS WHERE PARAMETER = 'NLS_DATE_FORMAT')
              )
            )
       THEN 'TRUE'
       ELSE 'FALSE'
       END
FROM   DUAL;

由于它依赖于从字符串到日期的隐式转换,因此Oracle将在转换中使用会话的日期格式。

例如:

代码语言:javascript
复制
ALTER SESSION SET NLS_DATE_FORMAT = 'DD/MM/RR';

SELECT CASE WHEN DATE '2005-11-25' IN ('25/11/05')
       THEN 'TRUE'
       ELSE 'FALSE'
       END
FROM   DUAL;

产出:TRUE

但是:

代码语言:javascript
复制
ALTER SESSION SET NLS_DATE_FORMAT = 'DD/MM/YYYY HH24:MI:SS';

SELECT CASE WHEN DATE '2005-11-25' IN ('25/11/05')
       THEN 'TRUE'
       ELSE 'FALSE'
       END
FROM   DUAL;

产出:FALSE

您可以理解为什么使用:

代码语言:javascript
复制
SELECT TO_CHAR(CAST('25/11/05' AS DATE), 'YYYY-MM-DD HH24:MI:SS') FROM DUAL;

它输出0005-11-25 00:00:00,是第一个世纪,而不是21世纪,因为隐式转换使用DD/MM/YYYY HH24:MI:SS格式模型,并期望有一个4位数的年份,并获得输入05,并假定它是一个正确的值为5 AD,而不是当前世纪的第5年(您可以使用YY格式模型得到该值)。

最好的解决方案是不依赖于隐式字符串到日期转换。

要么使用日期文字:

代码语言:javascript
复制
SELECT CASE WHEN DATE '2005-11-25' IN (DATE '2005-11-25')
       THEN 'TRUE'
       ELSE 'FALSE'
       END
FROM   DUAL;

或者,为转换提供显式格式模型:

代码语言:javascript
复制
SELECT CASE WHEN DATE '2005-11-25' IN (TO_DATE('25/11/05', 'DD/MM/RR'))
       THEN 'TRUE'
       ELSE 'FALSE'
       END
FROM   DUAL;

db<>fiddle https://dbfiddle.uk/?rdbms=oracle_21&fiddle=49005d1bb671c324c3819b84a1dd1378

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70753122

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档