Oracle 用虚拟列创建表
Posted
技术标签:
【中文标题】Oracle 用虚拟列创建表【英文标题】:Oracle create table with virtual column 【发布时间】:2013-03-14 08:12:43 【问题描述】:我正在 Oracle 上运行此 SQL(Oracle 数据库 11g 企业版版本 11.1.0.7.0 - 64 位生产):
CREATE TABLE R_SEQUENCES_COUNT1
(
DS_ID NUMBER,
LINE_TIME TIMESTAMP(6),
DAY_ID DATE GENERATED ALWAYS AS (TRUNC(LINE_TIME)),
HOUR_ID DATE GENERATED ALWAYS AS (TRUNC(LINE_TIME,'HH24')) ,
MINUTE_ID DATE GENERATED ALWAYS AS (TRUNC(LINE_TIME,'MI')) ,
SECOND_ID DATE GENERATED ALWAYS AS (LINE_TIME),
R_ID NUMBER,
SEQUENCE_ID NUMBER
)NOLOGGING
TABLESPACE TWC_DATA_SPACE
PARTITION BY LIST (DS_ID)
SUBPARTITION BY LIST(DAY_ID)
(PARTITION DS_ID_OTHER VALUES (DEFAULT)
(SUBPARTITION DS_ID_OTHER_DAY_ID_OTHER VALUES (DEFAULT)))
并得到这个错误:
Error at Command Line:8 Column:40
Error report:
SQL Error: ORA-54016: Invalid column expression was specified
怎么了?
【问题讨论】:
【参考方案1】:您希望它作为日期使用:
SECOND_ID DATE GENERATED ALWAYS AS (cast(LINE_TIME as date)),
否则你可以这样做:
SECOND_ID TIMESTAMP GENERATED ALWAYS AS (LINE_TIME + numtodsinterval(0, 'day')),
虽然在这种情况下不确定您为什么需要该列的精确副本?
例如第二个:
SQL> CREATE TABLE R_SEQUENCES_COUNT1
2 (
3 DS_ID NUMBER,
4 LINE_TIME TIMESTAMP(6),
5 DAY_ID DATE GENERATED ALWAYS AS (TRUNC(LINE_TIME)),
6 HOUR_ID DATE GENERATED ALWAYS AS (TRUNC(LINE_TIME,'HH24')) ,
7 MINUTE_ID DATE GENERATED ALWAYS AS (TRUNC(LINE_TIME,'MI')) ,
8 SECOND_ID TIMESTAMP GENERATED ALWAYS AS (LINE_TIME+numtodsinterval(0, 'day')),
9 R_ID NUMBER,
10 SEQUENCE_ID NUMBER
11 )NOLOGGING
12 /
Table created.
SQL> insert into R_SEQUENCES_COUNT1 (ds_id, line_time) values (1, systimestamp);
1 row created.
SQL> @print_Table "select * from R_SEQUENCES_COUNT1"
DS_ID : 1
LINE_TIME : 14-mar-2013 09:56:31.104921
DAY_ID : 14-mar-2013 00:00:00
HOUR_ID : 14-mar-2013 09:00:00
MINUTE_ID : 14-mar-2013 09:56:00
SECOND_ID : 14-mar-2013 09:56:31.104921
R_ID :
SEQUENCE_ID :
-----------------
【讨论】:
演员阵容是个问题,因为它会围绕日期,而我需要没有圆形的日期。 @igreen 然后使用第二种解决方案。DATE
只有第二个分辨率。所以实际上你想要line_time
属性的精确副本?
在 second_id 中我想去掉毫秒数。
@igreen 这是第一个选项,即cast
,尽管你说你不想要(它将时间戳四舍五入到最接近的秒数)。
我希望 exec 秒不四舍五入。【参考方案2】:
在你的创作中
//set condition is invalid
SECOND_ID DATE GENERATED ALWAYS AS (LINE_TIME)
// change to this...
SECOND_ID DATE GENERATED ALWAYS AS (TIMESTAMP)
数据类型TIMESTAMP
允许几分之一秒。如果将其转换为 DATE,则会删除小数秒 - 例如
所以在选择秒..
select cast(systimestamp as date) from dual;
我认为的另一种方式是......
TRUNC()
是一个时间戳到秒,你可以将它转换为一个日期
CAST( timestamp AS DATE)
然后像这样执行 TRUNC:
TRUNC(CAST(timestamp AS DATE), 'YEAR')
【讨论】:
但我希望 second_id 与 line_time 列相同,没有秒数,那么它是怎么发生的?正如我在演员表之前评论的那样不好,因为它围绕日期。以上是关于Oracle 用虚拟列创建表的主要内容,如果未能解决你的问题,请参考以下文章