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 用虚拟列创建表的主要内容,如果未能解决你的问题,请参考以下文章

ORACLE 创建一个表

Oracle中用子查询创建临时表 并赋值数据

是否可以在 HSQLDB 中有虚拟列

PL/SQ连接oracle,L 新建表的时候, virtual那一列是啥意思

oracle中如何根据多个表创建表

Oracle(创建视图)