【问题标题】:Oracle: is it possible to create a copy of a IOT using CTAS without specifying columns?Oracle:是否可以在不指定列的情况下使用 CTAS 创建 IOT 的副本?
【发布时间】:2019-07-22 12:38:11
【问题描述】:

我使用 CTAS (Create Table As Select) 语法来创建表的副本,以这种方式:

CREATE TABLE TABLE2 AS SELECT * FROM TABLE1;

所以 TABLE2 是 TABLE1 的完整副本,包括它的所有列。

我想用 IOT 表做同样的事情。

但如果我尝试执行以下操作:

CREATE TABLE IOT_TABLE2 ORGANIZATION INDEX AS SELECT * FROM IOT_TABLE1;

我得到:

ORA-25175: no PRIMARY KEY constraint found

有一些技巧可以做到这一点,或者根本不可能在不指定所有列的情况下创建副本?

【问题讨论】:

  • 问题是,CTAS 创建表的副本,但不创建其约束(不是索引、触发器等)。一个 IOT 必须有一个主键,并且不能从创建的表的投影中推断出来。因此 ORA-25175。
  • 您真的喜欢创建表格的副本还是尝试重新组织表格?
  • @WernfriedDomscheit 我的环境需要创建表的副本,而不是重新组织现有的表。如果您不知道目的,请避免批评有效的解决方案。谢谢
  • @AlessandroC,我没有批评任何事情,也没有否决任何事情我只是问了一个问题,因为您的要求看起来很特别。 .
  • 对不起@WernfriedDomscheit

标签: oracle oracle12c


【解决方案1】:

如下尝试

CREATE TABLE IOT_TABLE2(id, col1, col2 .... , CONSTRAINT pk PRIMARY KEY (id)) 
ORGANIZATION INDEX AS SELECT * FROM IOT_TABLE1;

db小提琴here

【讨论】:

    【解决方案2】:

    感谢@a_horse_with_no_name 提示,我找到了合适的解决方案。

    鉴于此示例 IOT DDL:

    CREATE TABLE "IOT_TABLE1" 
       (    "COLUMN1" VARCHAR2(50) NOT NULL ENABLE, 
        "COLUMN2" VARCHAR2(50) NOT NULL ENABLE, 
        "COLUMN3" NUMBER(18,0) NOT NULL ENABLE, 
        "COLUMN4" BINARY_DOUBLE, 
         CONSTRAINT "TABLE1_IOT_PK" PRIMARY KEY ("COLUMN1", "COLUMN2", "COLUMN3") ENABLE
       ) ORGANIZATION INDEX NOCOMPRESS;
    

    这是可以完美复制IOT的SQL语句:

    DECLARE 
        stmt VARCHAR2(4000);
    BEGIN 
        DBMS_METADATA.set_transform_param(DBMS_METADATA.session_transform, 'SQLTERMINATOR', false);
        DBMS_METADATA.set_transform_param(DBMS_METADATA.session_transform, 'PRETTY', true);
        DBMS_METADATA.set_transform_param(DBMS_METADATA.session_transform, 'SEGMENT_ATTRIBUTES', false);
        DBMS_METADATA.set_transform_param(DBMS_METADATA.session_transform, 'STORAGE', false);
        SELECT TO_CHAR(DBMS_METADATA.get_ddl('TABLE','IOT_TABLE1')) INTO stmt FROM DUAL;
        stmt := REPLACE(stmt, 'TABLE1_IOT_PK', 'TABLE2_IOT_PK');
        stmt := REPLACE(stmt, 'TABLE1', 'TABLE2');
        stmt := regexp_replace(stmt, '^\s+(\()*\s*"(\w+).+$',chr(9)||'\1"\2",',1,0,'m');
        stmt := stmt || 'AS SELECT * FROM TABLE1';
        dbms_output.put_line(stmt);
        EXECUTE IMMEDIATE STMT;
    END;
    

    有3个替换:

    1. PK 名称
    2. 表名称
    3. 必须消除 TYPE 信息,否则会失败并出现 ORA-01773

    Heredb小提琴

    【讨论】:

      猜你喜欢
      • 2021-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-17
      • 1970-01-01
      • 2010-09-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多