Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
带有本地时区值的Oracle时间戳透明转换_Oracle_Session_Timezone_Timestamp With Timezone - Fatal编程技术网

带有本地时区值的Oracle时间戳透明转换

带有本地时区值的Oracle时间戳透明转换,oracle,session,timezone,timestamp-with-timezone,Oracle,Session,Timezone,Timestamp With Timezone,据我所知,带有本地时区的时间戳值是透明的 转换到用户会话时区或从用户会话时区转换。但我的价值观是从 数据库与以前插入的数据库不同。有数据库或会话吗 我可以调整参数来解决这个问题吗 以下是我的测试用例: select systimestamp(0) from dual; -- SYSTIMESTAMP 15/03/2017 19:01:13 +03:00 select dbtimezone from dual; -- DBTIMEZONE -07:00 create table

据我所知,
带有本地时区的时间戳
值是透明的 转换到用户会话时区或从用户会话时区转换。但我的价值观是从 数据库与以前插入的数据库不同。有数据库或会话吗 我可以调整参数来解决这个问题吗

以下是我的测试用例:

select systimestamp(0) from dual;

-- SYSTIMESTAMP   15/03/2017 19:01:13 +03:00

select dbtimezone from dual;

-- DBTIMEZONE     -07:00

create table test_timestamps
(
    id number generated by default on null as identity,
    systimestamp_col timestamp(0) with local time zone default on null systimestamp,
    sysdate_col timestamp(0) with local time zone default on null sysdate,
    current_timestamp_col timestamp(0) with local time zone default on null current_timestamp(0),
    date_col timestamp(0) with local time zone
);

alter session set time_zone='0:00';

insert into test_timestamps(date_col)
values (timestamp '2017-03-15 19:02:00');

select * from test_timestamps;

-- ID                                 1
-- SYSTIMESTAMP_COL                   15/03/2017 9:02:19
-- SYSDATE_COL                        15/03/2017 12:02:18
-- CURRENT_TIMESTAMP_COL              15/03/2017 9:02:19
-- DATE_COL                           15/03/2017 12:02:00

delete from test_timestamps;

alter session set time_zone='+3:00';

insert into test_timestamps(date_col)
values (timestamp '2017-03-15 19:05:00');

select * from test_timestamps;

-- ID                                 2
-- SYSTIMESTAMP_COL                   15/03/2017 12:05:43
-- SYSDATE_COL                        15/03/2017 12:05:43
-- CURRENT_TIMESTAMP_COL              15/03/2017 12:05:43
-- DATE_COL                           15/03/2017 12:05:00
我对
DATE\u COL
值特别困惑。据我所知,无论当前会话的
时区是什么,我从
DATE\u COL
读取的值都应该与我插入的值相同(只要在插入和选择之间没有更改)

我还对
SYSTIMESTAMP
默认值感到困惑

SELECT SYSTIMESTAMP FROM DUAL
始终返回带有“+3:00”时区的服务器时间戳,而不管当前用户会话的时区如何。但是如果我使用
SYSTIMESTAMP
作为列的默认值,它会被转换

我想看到的是:

-- for a user in my time zone
alter session set time_zone='+3:00';

insert into test_timestamps(date_col)
values (timestamp '2017-03-15 19:15:00');

select id, systimestamp_col, date_col from test_timestamps;

-- ID                                 3
-- SYSTIMESTAMP_COL                   15/03/2017 19:15:00
-- DATE_COL                           15/03/2017 19:15:00

-- same data from a GMT user's point of view
alter session set time_zone='+0:00';

select id, systimestamp_col, date_col from test_timestamps;

-- ID                                 3
-- SYSTIMESTAMP_COL                   15/03/2017 16:15:00
-- DATE_COL                           15/03/2017 16:15:00
这是可能的还是我遗漏了什么


UPD。这是我的名片。它看起来应该像我描述的那样工作,所以我猜我的数据库设置可能有问题。

带有本地时区的时间戳
工作原理如下:当您必须在应用程序中使用时区时,通常的方法是

将所有时间在内部存储为UTC,并在应用程序级别将其转换为当前用户本地时区

这正是本地时区的时间戳的工作原理-唯一的区别是

在内部将所有时间存储为DBTIMEZONE,并在应用程序级别将其转换为当前用户本地时区

因此,如果数据库包含带有带有本地时区
列的
时间戳的表,并且该列包含数据,则不能再更改数据库上的
DBTIMEZONE
(使用
ALTER DATABASE SET TIME_ZONE='…';

SYSTIMESTAMP
在数据库服务器操作系统的时区中返回
DBTIMEZONE
不是
SYSTIMESTAMP
SYSDATE
的时区

DBTIMEZONE
定义带有本地时区的
时间戳的内部存储格式
数据类型列。忘了这一点吧,我无法想象您需要它的任何用例

实际上,您的表相当于此选择:

select 
   CAST(systimestamp AS timestamp(0) with local time zone) as SYSTIMESTAMP_COL,
   CAST(sysdate AS timestamp(0) with local time zone) as SYSDATE_COL,
   CAST(current_timestamp AS timestamp(0) with local time zone) as CURRENT_TIMESTAMP_COL,
   CAST(timestamp '2017-03-15 19:02:00' AS timestamp(0) with local time zone) as DATE_COL
from dual;
当您进行
CAST({time without timezone}with local timezone)
时,您将尝试将不带任何时区信息的日期/时间值转换为带时区的日期/时间值。原则上这是不可能的,因为Oracle缺少时区信息,所以Oracle假定为时区。如果您进行这样的转换,Oracle将始终考虑{time without timezone},如
SESSIONTIMEZONE
中所示(在转换时)

因此
CAST(sysdate作为时间戳(0)和本地时区)
相当于

CAST(FROM_TZ(TO_TIMESTAMP(SYSDATE), SESSIONTIMEZONE) AS TIMESTAMP(0) WITH LOCAL TIME ZONE)` 
分别<代码>强制转换(时间戳“2017-03-15 19:02:00”为带有本地时区的时间戳(0)
表示

CAST(FROM_TZ(TIMESTAMP '2017-03-15 19:02:00', SESSIONTIMEZONE) AS TIMESTAMP(0) WITH LOCAL TIME ZONE)
对于
SYSDATE
这实际上是错误的,因为
SYSDATE
是在数据库服务器操作系统的时区中给出的,而不是在SESSIONTIMEZONE中。对于第二个,这取决于你的意图,结果是否正确

SYSTIMESTAMP
返回带时区的值
时间戳
,它始终独立于当前的
会话时区
。但是,如果您转换为带有本地时区的时间戳,它当然会转换为您当前的本地时区。您还可以使用
CURRENT\u TIMESTAMP
SYSTIMESTAMP AT LOCAL
,其作用大致相同

此代码

似乎是错的。结果应该是

-- SYSTIMESTAMP_COL                   15/03/2017 16:01:14
-- SYSDATE_COL                        15/03/2017 19:01:14
-- CURRENT_TIMESTAMP_COL              15/03/2017 16:01:14
-- DATE_COL                           15/03/2017 19:02:00

差异看起来是应该的,但绝对值似乎是“伪造的”(或者您的数据库存在实际问题)。

我们的DBA已经找到了这种行为的原因。 我们使用一个多租户容器数据库(Oracle 12c CDB)。 当根数据库的
DBTIMEZONE
与可插拔数据库(PDB)
DBTIMEZONE
不同时,会出现此问题

就我们而言,我们有:

  • root
    DBTIMEZONE
    -“0:00”
  • PDB
    DBTIMEZONE
    -“-7:00”
一旦DBA将所有
DBTIMEZONE
s设置为相同的值,问题就消失了。 据我所知,他已将根
DBTIMEZONE
更改为“-7:00”。
现在,我的测试用例与沙箱上的运行完全相同,所选时间戳与插入的时间戳相同。

感谢您的回答!我包括了
DBTIMEZONE
,因为我的
SELECT
返回的值关闭了10个小时,看起来像+7+3(我的服务器的时区加上DBTIMEZONE值)。尽管如此,我仍然不知道如何在我的数据库实例上对时间戳值进行简单的往返。如果我在我的
DATE\u COL
列中插入时间戳文字(甚至转换为带有本地时区的
timestamp
),select将返回偏移10小时的值。在其他Oracle实例上,例如在livesql.Oracle.com上,它的行为与此不同,这就是我怀疑某些配置问题的原因。当我的会话时区设置为
0:00
时,我插入
19:00
,然后返回
9:00
,这将关闭10小时。当我的会话时区为
+3:00
(与数据库服务器的机器相同)时,我会得到
12:00
,这会被关闭7小时。也许这是巧合,
DBTIMEZONE
-7:00
,但我怀疑这可能是相关的,这就是为什么我认为值得一提的原因。谢谢Wernfried,非常感谢您的帮助!这些值不是伪造的,我按原样发布了所有内容。我无法在新创建的Oracle数据库上重现这个问题,这就是为什么我如此困惑的原因。幸运的是,我们的DBA刚刚找到了这种行为的原因,我将
-- SYSTIMESTAMP_COL                   15/03/2017 16:01:14
-- SYSDATE_COL                        15/03/2017 19:01:14
-- CURRENT_TIMESTAMP_COL              15/03/2017 16:01:14
-- DATE_COL                           15/03/2017 19:02:00