【问题标题】:Oracle create table with virtual columnOracle 用虚拟列创建表
【发布时间】: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

怎么了?

【问题讨论】:

    标签: sql oracle


    【解决方案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 列相同,没有秒数,那么它是怎么发生的?正如我在演员表之前评论的那样不好,因为它围绕日期。
    猜你喜欢
    • 1970-01-01
    • 2015-08-11
    • 1970-01-01
    • 2012-12-26
    • 2014-08-19
    • 1970-01-01
    • 1970-01-01
    • 2014-11-13
    • 1970-01-01
    相关资源
    最近更新 更多