我在T-SQL工作,但已获得一些Oracle PL-SQL供项目审核。
在代码中有多个WHERE子句,它们将DataType = DATE字段与保存" date"的字符串进行比较。
前:
WHERE to_date(mytable.mydatefield) > '23-OCT-2015'
OR
WHERE mytable.mydatefield > '23-OCT-2015'
Q1:因为" mydatefield"已被定义为DATA类型,并未进行" to_date"不必要?
第二季度:甲骨文将在' 23-OCT-2015'上进行隐式转换。并将其转换为比较日期?我似乎记得在此之前遇到过这种情况并将DATES与STRINGS比较造成问题? 我错了吗?如果没有,有人可以给我一个例子,我可以作为证据证明它不起作用吗?答案 0 :(得分:3)
A1:一般情况下是,但请考虑Oracle处理隐式类型转换的方式。 To_Date
列周围的mydatefield
函数需要输入字符串,因此Oracle隐式地将mydatefield
转换为格式与NLS_DATE_FORMAT
会话设置匹配的字符串(默认为DD- MON-RR)。转换为字符串后,To_Date
函数会使用当前的NLS_DATE_FORMAT设置将其转换回日期。然后将新重构的日期与字符串'23 -OCT-2015'进行比较,但由于日期和字符串不能直接比较,因此使用当前NLS_DATE_FORMAT
设置将字符串值隐式转换为日期。根据{{1}}设置的值,第一次隐式转换可能会丢失特定于任何时间部分和原始世纪的信息,因为默认NLS_DATE_FORMAT
仅使用两位数的年份NLS_DATE_FORMAT
没有时间成分。
由于几个原因,这两种关系都很糟糕。首先,它们都受到从日期到字符串的隐式类型转换的影响(反之亦然)。其次,他们都试图用非规范形式比较日期和字符串。因此,10-DEC-15小于23-OCT-2015,因为1小于2.另请注意,自默认RR
使用两位数年以来,代表年份的位数差异。
正确的方法是将日期列(可能是截断的)与显式转换为日期的日期字符串进行比较
NLS_DATE_FORMAT
OR与截断:
WHERE mytable.mydatefield > TO_DATE('23-OCT-2015', 'DD-MON-YYYY')
删除日期字段的时间部分。
答案 1 :(得分:0)
Q1:根据Oracle,to_date()的第一个参数是char值。像to_date(date_value)一样使用它会强制将date_value隐式转换为char,然后将其再次包装在日期值中。
Q2:服务器将从字符串' 23-OCT-2015'进行隐式转换。到日期值但是基于数据库参数可能与各种服务器不同(例如DEV与PROD),所以你不应该依赖它们。正确使用的示例是WHERE mytable.mydatefield > to_date('23-OCT-2015','dd-MON-yyyy')
您应始终使用to_date / to_char以确保使用正确的格式。请参阅此答案以获取更详细的说明:Comparing Dates in Oracle SQL