将硬编码时间戳添加到 Oracle sql 中的列

Add hardcoded timestamp to a column in Oracle sql

提问人:Tech_Girl7819 提问时间:11/18/2023 更新时间:11/18/2023 访问量:44

问:

我有一个列的时间戳如下

select grade_date from grades_vs

将给出输出

grade_date
2023-11-18T00:00:00.000+00:00

我想更改时间戳部分并将其硬编码为 .2023-11-18T04:36:16.000+00:00

主要是添加,使时间完全采用这种格式,而不是'T04:36:16.000+00:00'

00:00:00

我为此使用 to_timestamp,但它给了我一个字面字符串错误。如何对此值进行硬编码并将列转换为时间戳?

SQL Oracle-SQLD开发商

评论

0赞 Alex Poole 11/18/2023
列是什么数据类型 - varchar2、时间戳或带时区的时间戳?此外,您是否总是希望将所有行的时间设置为相同的值 04:36:16,而不考虑日期部分;即使时区偏移量不是 +00:00?)您使用的是哪个版本的 Oracle?
0赞 Tech_Girl7819 11/18/2023
数据类型为“DATE”,是的,它应该始终是 04:36:16,无论日期部分和时区如何
1赞 MT0 11/18/2023
A 没有时区。DATE

答:

0赞 Alex Poole 11/18/2023 #1

如果您的列是 DATE,则它没有小数秒或时区;或任何固有的人类可读格式。因此,格式(包括那些额外的元素)在数据表示中被硬编码,可能在您的 NLS 设置中:

alter session set nls_date_format = 'YYYY-MM-DD"T"HH24:MI:SS".000+00:00"'

或者可能直接由客户端(或在 SQL Developer 中设置的 NLS 设置,在标记该客户端时)进行。

无论如何。。。由于它是 DATE 而不是 VARCHAR2 数据类型,因此您可以通过添加表示所需小时、分钟和秒的间隔来直接设置时间。如果只想在查询中查看修改后的值,则:

select grade_date + interval '04:36:16' hour to second as grade_date
from grade_vs
GRADE_DATE
2023-11-18T04:36:16.000+00:00

或者将任何具有非午夜时间的值重置为“先午夜”:

select trunc(grade_date) + interval '04:36:16' hour to second as grade_date
from grade_vs
GRADE_DATE
2023-11-18T04:36:16.000+00:00

如果要更改表中的值,可以使用相同的计算进行更新:

update grade_vs
set grade_date = grade_date + interval '04:36:16' hour to second;

或者将任何具有非午夜时间的值重置为“先午夜”:

update grade_vs
set grade_date = trunc(grade_date) + interval '04:36:16' hour to second;

它为您提供了,使用上面的 NLS 格式:

select * from grade_vs
GRADE_DATE
2023-11-18T04:36:16.000+00:00

小提琴


日期和时间戳存储在内部二进制表示形式中,您通常不需要担心,但它们不会在您看到它们显示时存储。

如果你从一个字符串值开始(幸运的是,你不是),那么你可以将其转换为日期(忽略小数秒和时区偏移量;假设它们始终为零):

alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS'
select to_date('2023-11-18T04:36:16.000+00:00', 'YYYY-MM-DD"T"HH24:MI:SS."000+00:00"') as result
from dual
结果
2023-11-18 04:36:16

或时间戳(忽略时区偏移):

alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS.FF3'
select to_timestamp('2023-11-18T04:36:16.000+00:00', 'YYYY-MM-DD"T"HH24:MI:SS.FF3"+00:00"') as result
from dual
结果
2023-11-18 04:36:16.000

或设置为带有时区的时间戳:

alter session set nls_timestamp_tz_format = 'YYYY-MM-DD HH24:MI:SS.FF3TZR'
select to_timestamp_tz('2023-11-18T04:36:16.000+00:00', 'YYYY-MM-DD"T"HH24:MI:SS.FF3TZH:TZM') as result
from dual
结果
2023-11-18 04:36:16.000+00:00
-- only in recent versions of Oracle
select to_utc_timestamp_tz('2023-11-18T04:36:16.000+00:00') as result
from dual
结果
2023-11-18 04:36:16.000+00:00

小提琴

但同样,这只是当你从一个字符串开始时,你不是。

评论

0赞 Tech_Girl7819 11/18/2023
我无法更改 NLS 设置,也无法使用 DML,在这种情况下,此更改将不可行(因为我使用的是 Oracle 云)
0赞 Alex Poole 11/18/2023
你是什么意思?您已经看到数据的格式化。也不确定您对 DML 的意思 - 只是想在查询中查看修改后的值,但不想更新表?这是相同的计算。
0赞 Tech_Girl7819 11/18/2023
是的,它应该使用函数在选择查询中完成,因为我无法执行更新、删除等
0赞 MT0 11/18/2023 #2

在 Oracle 中,是一种二进制数据类型,存储为 14-20 个字节,包括 1 个字节表示世纪、世纪年、月、日、小时、分钟和秒,然后是 0-6 个字节表示小数秒(取决于您需要的精度)和 7 个字节表示时区。它始终具有这些组件,并且永远不会以任何特定的人类可读格式存储。TIMESTAMP WITH TIME ZONE

主要是添加,使时间正好采用此格式'T04:36:16.000+00:00'

由于 a(和 和 )是二进制数据类型,并且它们永远不会以任何特定的人类可读格式存储,因此您所要求的是不可能的,因为您无法存储格式。TIMESTAMP WITH TIME ZONEDATETIMESTAMP

如果要以特定格式显示(而不是存储)时间戳,请使用将其转换为格式化字符串,并使用双引号对格式模型的一部分进行硬编码:TO_CHAR

SELECT TO_CHAR(grade_date, 'YYYY-MM-DD"T04:36:16.000"TZR') AS grade_date
FROM   grades_vs

其中,对于示例数据:

CREATE TABLE grades_vs (grade_date) AS
SELECT TIMESTAMP '2023-11-18 00:00:00.000+00:00' FROM DUAL;

输出:

GRADE_DATE
2023-11-18T04:36:16.000+00:00

如果要返回(而不是字符串),则可以减去当前时间部分并添加 an 以设置新的时间部分:TIMESTAMP WITH TIME ZONEINTERVAL DAY TO SECOND

SELECT grade_date
         - (grade_date - TRUNC(grade_date))       -- Current time component
         + INTERVAL '04:36:16.000' HOUR TO SECOND -- New time component
       AS grade_date
FROM   grades_vs

这将修改时间组件,同时保持日期和时区组件不变。但是,您随后依赖于客户端应用程序(即 .SQL 开发人员)为您(而不是数据库)格式化值。

如果客户端设置为使用该格式显示数据类型,则输出为:TIMESTAMP WITH TIME ZONEYYYY-MM-DD"T"HH24:MI:SS.FF3TZR

GRADE_DATE
2023-11-18T04:36:16.000+00:00

但这取决于您使用正确的格式设置客户端应用程序。

使用 SQL Developer,可以使用以下任一方法在客户端设置中更改日期和时间戳格式设置选项TIMESTAMP WITH TIME ZONE

ALTER SESSION SET NLS_TIMESTAMP_TZ_FORMAT = 'YYYY-MM-DD"T"HH24:MI:SS.FF3TZR';

或者通过菜单更改首选项和设置。Database > NLS > Timestamp TZ Format


如果您的列是 (而不是 ),那么它也是一种二进制数据类型,使用 7 个字节存储 1 个字节,分别表示世纪、世纪年、月、日、小时、分钟和秒。同样,它始终包含所有这些组件,并且从不以任何特定格式存储。DATETIMESTAMP WITH TIME ZONE

A 将不包含时区,因此您可以使用与以前相同的查询,但还必须对时区进行硬编码:DATE

SELECT TO_CHAR(grade_date, 'YYYY-MM-DD"T04:36:16.000+00:00"') AS grade_date
FROM   grades_vs

如果你想要一个(不是字符串),那么,同样,你可以重复前面的查询(稍作修改):DATE

SELECT grade_date
         - (grade_date - TRUNC(grade_date)) DAY TO SECOND
         + INTERVAL '04:36:16.000' HOUR TO SECOND
       AS grade_date
FROM   grades_vs

但您可以将其简化为:

SELECT TRUNC(grade_date) + INTERVAL '04:36:16' HOUR TO SECOND
       AS grade_date
FROM   grades_vs

小提琴