oracle - ORA-01741 用于带有不可见字段和隐式约束的 DBMS_REDEFINITION

标签 oracle plsql oracle12c redefinition ora-01741

我最近注意到一个数据库 (12cR1) 在使用 DBMS_REDEFINITION 时出现了一种奇怪的故障模式。 CAN_REDEF_TABLE 完成得很好,START_REDEF_TABLE 也是如此,但是 COPY_TABLE_DEPENDENTS 失败并令人困惑:

ORA-01741: illegal zero-length identifier

经过一些调试,异常似乎与ORIG_TABLE 携带both INVISIBLEand 隐式系统命名约束。我将在下面包含一个示例来演示该问题,但我希望对行为有一些了解,并且没有看到关于在 docs 中调用的 INVISIBLE 有任何值得注意的地方 | .

我想更好地理解系统生成的约束的创建似乎有些细微差别。对“为什么”的问题表示歉意,但是,为什么隐式系统约束在重新定义期间的行为与显式定义的约束有任何不同?我原以为在分配了一个系统生成的名称后,约束就只是一个约束。系统生成的对象是否在其他方面不同于其名称之外的客户端命名约束?

除了重命名隐式约束或在重新定义之前取消隐藏列之外,我还希望看看是否有人可以推荐其他解决方法。

谢谢

例子: 下面是相同的 ORIG_TABLE 的三个版本,用于重新定义。前两个都使用给定的 INT_TABLE 进行远低于重新定义,但第三个在 COPY_TABLE_DEPENDENTS 期间抛出 ORA-01741

版本 1:所有列可见,隐式系统生成的约束:

CREATE TABLE REDEF_TARGET (
  THE_KEY  INTEGER NOT NULL PRIMARY KEY ,
  THE_DATE DATE    NOT NULL
);

版本 2:存在 INVISIBLE 列,显式约束(如果 DBMS_REDEFINITION 正在检测现有名称,请在此处给出一个荒谬的名称)

CREATE TABLE REDEF_TARGET (
  THE_KEY  INTEGER NOT NULL PRIMARY KEY ,
  THE_DATE DATE INVISIBLE ,
  CONSTRAINT SYS_C02583271 CHECK (THE_DATE IS NOT NULL)
);

版本 3:INVISIBLE 列和隐式约束均存在

CREATE TABLE REDEF_TARGET (
  THE_KEY  INTEGER NOT NULL PRIMARY KEY ,
  THE_DATE DATE INVISIBLE NOT NULL
);

针对以下运行第一个中的任何一个都可以,而第三个将在 copy-deps 期间失败。

CREATE TABLE REDEFINER (
  THE_KEY  INTEGER ,
  THE_DATE DATE
);

DECLARE
  V_NUM INTEGER;
BEGIN
  DBMS_REDEFINITION.CAN_REDEF_TABLE(UNAME => USER , TNAME => 'REDEF_TARGET');
  DBMS_REDEFINITION.START_REDEF_TABLE(UNAME => USER , ORIG_TABLE => 'REDEF_TARGET' , INT_TABLE => 'REDEFINER');
  DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS(UNAME => USER , ORIG_TABLE => 'REDEF_TARGET' , INT_TABLE => 'REDEFINER' , NUM_ERRORS => V_NUM);
  DBMS_REDEFINITION.FINISH_REDEF_TABLE(UNAME => USER , ORIG_TABLE => 'REDEF_TARGET' , INT_TABLE => 'REDEFINER');
END;
/

最佳答案

首先,您不需要将 NOT NULLPRIMARY KEY 子句一起使用。摆脱这样的 NOT NULL

让我们按照您的情况在 DB version 12cR1 上运行版本 3 的语句:

Connected to Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 
Connected as hr

SQL> CREATE TABLE REDEF_TARGET (
  2    THE_KEY  INTEGER PRIMARY KEY ,
  3    THE_DATE DATE INVISIBLE NOT NULL
  4  );

Table created

SQL> CREATE TABLE REDEFINER(
  2    THE_KEY  INTEGER,
  3    THE_DATE DATE
  4  );

Table created

SQL> DECLARE
  2    V_NUM INTEGER;
  3  BEGIN
  4    DBMS_REDEFINITION.CAN_REDEF_TABLE(UNAME => USER , TNAME => 'REDEF_TARGET');
  5    DBMS_REDEFINITION.START_REDEF_TABLE(UNAME => USER , ORIG_TABLE => 'REDEF_TARGET' , INT_TABLE => 'REDEFINER');
  6    DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS(UNAME => USER , ORIG_TABLE => 'REDEF_TARGET' , INT_TABLE => 'REDEFINER' , NUM_ERRORS => V_NUM);
  7    DBMS_REDEFINITION.FINISH_REDEF_TABLE(UNAME => USER , ORIG_TABLE => 'REDEF_TARGET' , INT_TABLE => 'REDEFINER');
  8  END;
  9  /

ORA-01741: illegal zero-length identifier
ORA-06512: at "SYS.DBMS_REDEFINITION", line 1646
ORA-06512: at "SYS.DBMS_REDEFINITION", line 2502
ORA-06512: at "SYS.DBMS_REDEFINITION", line 3803
ORA-06512: at line 7

SQL> DROP TABLE REDEF_TARGET;

Table dropped

SQL> DROP TABLE REDEFINER;

DROP TABLE REDEFINER

ORA-12083: must use DROP MATERIALIZED VIEW to drop "HR"."REDEFINER"

SQL> DROP MATERIALIZED VIEW REDEFINER;

Materialized view dropped

SQL> DROP TABLE REDEFINER;

Table dropped

SQL> CREATE TABLE REDEF_TARGET (
  2    THE_KEY  INTEGER PRIMARY KEY ,
  3    THE_DATE DATE INVISIBLE NOT NULL
  4  );

Table created

SQL> CREATE TABLE REDEFINER(
  2    THE_KEY  INTEGER,
  3    THE_DATE DATE INVISIBLE
  4  );

Table created

SQL> DECLARE
  2    V_NUM INTEGER;
  3  BEGIN
  4    DBMS_REDEFINITION.CAN_REDEF_TABLE(UNAME => USER , TNAME => 'REDEF_TARGET');
  5    DBMS_REDEFINITION.START_REDEF_TABLE(UNAME => USER , ORIG_TABLE => 'REDEF_TARGET' , INT_TABLE => 'REDEFINER');
  6    DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS(UNAME => USER , ORIG_TABLE => 'REDEF_TARGET' , INT_TABLE => 'REDEFINER' , NUM_ERRORS => V_NUM);
  7    DBMS_REDEFINITION.FINISH_REDEF_TABLE(UNAME => USER , ORIG_TABLE => 'REDEF_TARGET' , INT_TABLE => 'REDEFINER');
  8  END;
  9  /

ORA-01741: illegal zero-length identifier
ORA-06512: at "SYS.DBMS_REDEFINITION", line 1646
ORA-06512: at "SYS.DBMS_REDEFINITION", line 2502
ORA-06512: at "SYS.DBMS_REDEFINITION", line 3803
ORA-06512: at line 7

数据库版本 12cR2:

Connected to Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 
Connected as hr

SQL> CREATE TABLE REDEF_TARGET (
  2    THE_KEY  INTEGER PRIMARY KEY ,
  3    THE_DATE DATE INVISIBLE NOT NULL
  4  );

Table created

SQL> CREATE TABLE REDEFINER(
  2    THE_KEY  INTEGER,
  3    THE_DATE DATE
  4  );

Table created

SQL> DECLARE
  2    V_NUM INTEGER;
  3  BEGIN
  4    DBMS_REDEFINITION.CAN_REDEF_TABLE(UNAME => USER , TNAME => 'REDEF_TARGET');
  5    DBMS_REDEFINITION.START_REDEF_TABLE(UNAME => USER , ORIG_TABLE => 'REDEF_TARGET' , INT_TABLE => 'REDEFINER');
  6    DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS(UNAME => USER , ORIG_TABLE => 'REDEF_TARGET' , INT_TABLE => 'REDEFINER' , NUM_ERRORS => V_NUM);
  7    DBMS_REDEFINITION.FINISH_REDEF_TABLE(UNAME => USER , ORIG_TABLE => 'REDEF_TARGET' , INT_TABLE => 'REDEFINER');
  8  END;
  9  /

ORA-042067: invalid column mapping with invisible columns on original or interim table
ORA-06512: at "SYS.DBMS_REDEFINITION", line 109
ORA-06512: at "SYS.DBMS_REDEFINITION", line 3887
ORA-06512: at "SYS.DBMS_REDEFINITION", line 5208
ORA-06512: at line 5

SQL> DROP TABLE REDEF_TARGET;

Table dropped

SQL> DROP TABLE REDEFINER;

Table dropped

SQL> CREATE TABLE REDEF_TARGET (
  2    THE_KEY  INTEGER PRIMARY KEY ,
  3    THE_DATE DATE INVISIBLE NOT NULL
  4  );

Table created

SQL> CREATE TABLE REDEFINER(
  2    THE_KEY  INTEGER,
  3    THE_DATE DATE INVISIBLE
  4  );

Table created

SQL> DECLARE
  2    V_NUM INTEGER;
  3  BEGIN
  4    DBMS_REDEFINITION.CAN_REDEF_TABLE(UNAME => USER , TNAME => 'REDEF_TARGET');
  5    DBMS_REDEFINITION.START_REDEF_TABLE(UNAME => USER , ORIG_TABLE => 'REDEF_TARGET' , INT_TABLE => 'REDEFINER');
  6    DBMS_REDEFINITION.COPY_TABLE_DEPENDENTS(UNAME => USER , ORIG_TABLE => 'REDEF_TARGET' , INT_TABLE => 'REDEFINER' , NUM_ERRORS => V_NUM);
  7    DBMS_REDEFINITION.FINISH_REDEF_TABLE(UNAME => USER , ORIG_TABLE => 'REDEF_TARGET' , INT_TABLE => 'REDEFINER');
  8  END;
  9  /

PL/SQL procedure successfully completed.

结果如下:

  • Version 12c Release 1 解决了以下主要问题 ORA-042067 而不是 ORA-01741。因此,需要为 REDEFINER 表的 THE_DATE (DATE) 列添加 INVISIBLE 选项,以便在 original 之间实现真正的列映射> 和 临时 表。
  • 即使为上述列添加了 INVISIBLE 选项,您也会 对于版本 R1 仍然得到相同的错误代码 (ORA-01741),而 R2 版本你会成功的。所以,升级似乎是 必要的。
  • 顺便说一句,每次我们尝试删除 REDEFINER 表时,都会具体化 R1 需要删除 View ,R2 则不需要。有趣,可能是一个错误......

关于oracle - ORA-01741 用于带有不可见字段和隐式约束的 DBMS_REDEFINITION,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51391212/

相关文章:

sql - 如何覆盖 ORDER 方法 PL/SQL?

sql - Oracle SQL session 的生命周期是什么?

sql - 为什么我在 PL SQL 包中遇到 Declare Identifier 和许多其他错误?

java - Spring JMS 和 Oracle AQ

oracle - 使用 Oracle 进行单元测试

sql - 如何在 PL/SQL 中访问字符串的索引?

java - Hibernate Oracle12c方言可以使用hibernate 4.3吗

Oracle - 如何使用动态绑定(bind)参数定义动态 SQL?

sql - PL/SQL 性能优化 - 计算记录更改的总和与差值

甲骨文 (PL/SQL) : Is UPDATE RETURNING concurrent?