SQL- TIMESTAMP,DATE和TIMESTAMP与TIMEZONE之间的区别?

时间:2016-01-15 15:43:57

标签: sql oracle date timestamp

TIMESTAMPDATETIMESTAMP with TIMEZONE之间有什么区别?

例如,如果我想搜索01-JAN-199001-JAN-2000之间的所有条目,我将如何以每种格式进行搜索?

我一直在寻找时间戳:

SELECT COUNT(*) FROM TABLE_NAME WHERE DATE BETWEEN '01-JAN-1990' AND '01-JAN-2000;

但我不确定用于搜索DATETIMESTAMP WITH TIMEZONE的格式。

2 个答案:

答案 0 :(得分:2)

它们之间的数据类型和差异为in the documentation。简短版本是:

  • DATE具有精确到一秒的时间,没有时区支持;
  • TIMESTAMP的精确度低至几分之一秒(最多九位小数,但您的操作系统也会影响到这一点),仍然没有时区支持;
  • TIMESTAMP WITH TIME ZONE与TIMESTAMP具有相同的精度,但也有tome zone支持,顾名思义;
  • TIMESTAMP WITH LOCAL TIME ZONE调整存储值与创建/查询会话的本地时区。

您可能会发现this article也很有趣。

每当您比较存储在数据库中的日期时间值时,您应该使用相同数据类型的值进行比较。您不希望必须转换列中的每个值以进行比较,尤其是在列已编制索引的情况下。如果您有DATE列,则与DATE进行比较 - 不要比较为字符串,也不要依赖字符串的隐式conversion。当你这样做时:

BETWEEN

您依赖的是NLS_DATE_FORMAT为DD-MON-YYYY且您的NLS_DATE_LANGUAGE为英语。如果其他人在另一个会话中运行相同的查询,他们的设置可能会导致查询失败(或者在某些情况下,会给出错误的结果,这可能会更糟)。为避免语言问题,最好使用月份数而不是名称。如果你有一个要比较的字符串变量,你应该使用TO_DATE()使用固定的已知格式掩码将字符串转换为DATE - 不要依赖于NLS。如果你有一个固定值,你也可以这样做,或者你可以使用date literal,它更短,更明确。

使用您使用的格式,您还包括在2000年1月1日将列设置为午夜的任何行,但不包括当天的任何行。这可能是你想要的,但要确保你理解WHERE date_col >= DATE '1990-01-01' AND date_col < DATE '2000-01-01' 的工作原理。如果你真的在那个十年内寻找日期,包括1999年12月31日的任何时间,你可以使用:

WHERE ts_col >= TIMESTAMP '1990-01-01 00:00:00'
AND ts_col < TIMESTAMP '2000-01-01 00:00:00'

对于时间戳,您可以使用TO_TIMESTAMP()或时间戳文字:

WHERE tstz_col >= TIMESTAMP '1990-01-01 00:00:00 America/New_York'
AND tstz_col < TIMESTAMP '2000-01-01 00:00:00 America/New_York'

对于带时区的时间戳,您可以使用TO_TIMESTAMP_TZ()或时间戳文字,并使用名称时区区域:

var ngTemplateLoader = (
    'ngtemplate?relativeTo=' + path.resolve(__dirname, './src/') +
    '!html'
);

module.exports = {
    ...
    module: {
        loaders: [
            {test: /\.html$/, loader: ngTemplateLoader},
        ],
    },
    ...
}

答案 1 :(得分:1)

不要将日期与字符串进行比较。如果您的会话nls_date_format恰好与您正在使用的字符串格式匹配,则它可以正常工作。但是,对于具有不同配置的人,您的查询将立即失败。比较日期与日期,时间戳和时间戳等。

对于日期,您可以使用ANSI日期文字

SELECT COUNT(*)
  FROM your_table
 WHERE date_column BETWEEN date '1900-01-01' AND date '2000-01-01'

或者您可以使用带有显式格式掩码的to_date

SELECT COUNT(*)
  FROM your_table
 WHERE date_column BETWEEN to_date('1900-01-01', 'YYYY-MM-DD') 
                       AND to_date('2000-01-01', 'YYYY-MM-DD')

请注意,Oracle中的date始终具有日期和时间组件。如果您未在to_date中指定时间,则默认为午夜。如果使用显式to_date,只要它与您传入的格式掩码匹配为第二个参数,就可以使用任何格式的字符串。

对于时间戳,您可以使用ANSI时间戳文字

SELECT COUNT(*)
  FROM your_table
 WHERE timestamp_column BETWEEN timestamp '1900-01-01 00:00:00.000' 
                            AND timestamp '2000-01-01 00:00:00.000'

或者您可以使用带有显式格式掩码的to_timestamp

SELECT COUNT(*)
  FROM your_table
 WHERE timestamp_column BETWEEN to_timestamp('1900-01-01 00:00:00.000', 'YYYY-MM-DD HH24:MI:SS.FFF') 
                            AND to_timestamp('2000-01-01 00:00:00.000', 'YYYY-MM-DD HH24:MI:SS.FFF') 

如果使用显式to_timestamp,只要它与您传入的格式掩码匹配为第二个参数,就可以使用任何格式的字符串。

对于带有时区的时间戳,正如您可能已经猜到的那样,您可以使用ANSI时间戳文字

SELECT COUNT(*)
  FROM your_table
 WHERE timestamp_column BETWEEN timestamp '1900-01-01 00:00:00.000 -05:00' 
                            AND timestamp '2000-01-01 00:00:00.000 -05:00'

或者您可以使用带有显式格式掩码的to_timestamp_tz函数

SELECT COUNT(*)
  FROM your_table
 WHERE timestamp_column BETWEEN to_timestamp('1900-01-01 00:00:00.000 -05:00', 'YYYY-MM-DD HH24:MI:SS.FFF TZH:TZM') 
                            AND to_timestamp('2000-01-01 00:00:00.000 -05:00', 'YYYY-MM-DD HH24:MI:SS.FFF TZH:TZM') 

如果使用显式to_timestamp_tz,只要它与您传入的格式掩码匹配为第二个参数,就可以使用任何格式的字符串。