我有表systemproperties
,其中存储了propertyname (varchar)
和propertyvalue (clob)
。根据其中一个属性,
propertyname - RowDate
propertyvalue - 12-MAY-17 04.00.06.883000 PM
另一个表activity
,我正在使用timestamp(6)
存储日志数据。
查询从activity
表中获取日志数据,
select type,startdate from activity where startdate > ?
此处startdate
为timestamp(6)
类型。我使用的是实际值,结果一无所获。但是,如果我使用如下:
select type,startdate from activity
where startdate > (select to_char(propertyvalue)
from systemproperties where propertyname='RowDate')
我的行数大于时间。我无法理解这里的区别。任何人都可以在这里指导我。我可以用什么来解决这个问题?
以下是我的NLS设置:
NLS_LANGUAGE AMERICAN
NLS_TERRITORY AMERICA
NLS_CURRENCY $
NLS_ISO_CURRENCY AMERICA
NLS_NUMERIC_CHARACTERS .,
NLS_CALENDAR GREGORIAN
NLS_DATE_FORMAT DD-MON-RR
NLS_DATE_LANGUAGE AMERICAN
NLS_SORT BINARY
NLS_TIME_FORMAT HH.MI.SSXFF AM
NLS_TIMESTAMP_FORMAT DD-MON-RR HH.MI.SSXFF AM
NLS_TIME_TZ_FORMAT HH.MI.SSXFF AM TZR
NLS_TIMESTAMP_TZ_FORMAT DD-MON-RR HH.MI.SSXFF AM TZR
NLS_DUAL_CURRENCY $
NLS_COMP BINARY
NLS_LENGTH_SEMANTICS BYTE
NLS_NCHAR_CONV_EXCP FALSE
提前致谢。
答案 0 :(得分:1)
您的财产定义如下:
propertyvalue - 12-MAY-17 04.00.06.883000 PM
现在您认为这意味着2017年5月12日,但这不是您所说的。因此,当将字符串12-MAY-17 04.00.06.883000 PM
转换为Oracle执行通常所做的日期时,将该世纪默认为00
。
演示:
SQL> alter session set nls_date_format='yyyy-mm-dd hh24:mi:ss';
Session altered.
SQL> select sysdate from dual;
SYSDATE
-------------------
2017-05-14 23:50:09
SQL> select to_date('17-05-14 00:00:00') my_date from dual;
MY_DATE
-------------------
0017-05-14 00:00:00
SQL>
这就是你得到结果的原因。显然你有很多记录startdate > date '0017-05-12'
"我可以使用哪些解决方案?"
最佳解决方案是正确定义日期。这是 2017 ,现在还为时已晚,无法对Y2K错误进行编码。
propertyvalue - 12-MAY-2017 04.00.06.883000 PM
或者,您可以在引用属性时使用显式日期掩码:
startdate > to_date(propertyvalue, 'DD-MON-YY HH.MI.SS.FF6 AM')
在这种情况下,Oracle将用当前世纪20
替换掩码的缺失元素。它仍然是一个等待发生的错误,但20
比00
更有可能是正确答案。
" startdate是时间戳(6)"
没关系,Oracle在这方面对它们都是一样的:
SQL> alter table t23 add ts timestamp;
Table altered.
SQL> update t23 set ts = systimestamp;
4 rows updated.
SQL> select count(*) from t23 where ts > to_date('17-05-16 00:00:00');
COUNT(*)
----------
4
SQL> select count(*) from t23 where ts > to_date('17-05-16 00:00:00', 'yy-mm-dd hh24:mi:ss');
COUNT(*)
----------
0
SQL>
答案 1 :(得分:1)
当您比较startdate > your_property_string
时,Oracle将使用适当的TIMESTAMP
参数作为格式掩码隐式尝试将属性字符串转换为匹配的数据类型(即NLS_SESSION
)。因此WHERE
子句将隐式转换为等效于:
WHERE startdate > TO_TIMESTAMP(
your_property_string,
( SELECT value
FROM SYS.NLS_SESSION_PARAMETERS
WHERE parameter = 'NLS_TIMESTAMP_FORMAT' )
)
因此,Oracle可以为您的属性字符串提供不同的值,具体取决于您NLS_TIMESTAMP_FORMAT
的设置值。即如果是YYYY-MON-DD HH12:MI:SS.FF6 AM
,那么您的日期将被解析为0015-05-17T16:00:06.883000
,如果是DD-MON-YY HH12:MI:SS.FF6 AM
,那么它将是2017-05-15T16:00:06.883000
。
如果要在转换字符串时保持一致,则必须在查询中明确指定格式掩码(以及NLS_DATE_LANGUAGE
):
SELECT type,
startdate
FROM activity
WHERE startdate > TO_TIMESTAMP(
?,
'DD-MON-YY HH12.MI.SS.FF6 AM',
'NLS_DATE_LANGUAGE=ENGLISH'
)