ORA-01741,用于DBMS_REDEFINITION,具有不可见字段和隐式约束

时间:2018-07-17 22:51:01

标签: oracle plsql oracle12c redefinition ora-01741

最近我在使用DBMS_REDEFINITION时在一个数据库(12cR1)中发现了一个奇怪的故障模式。 CAN_REDEF_TABLE可以很好地完成,START_REDEF_TABLE也可以,但是COPY_TABLE_DEPENDENTS失败时会产生困惑:

  

ORA-01741:非法的零长度标识符

经过一些调试后,异常似乎与{strong> {strong> ORIG_TABLE列中包含隐式系统名称的INVISIBLE有关约束。我将在下面提供一个示例来演示该问题,但我希望对该行为有所了解,并且在docs中未发现关于INVISIBLE的任何值得注意的内容。

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

我还希望看看是否还有其他解决方法可以建议,而不仅仅是重命名隐式约束或在重新定义之前取消隐藏列。

谢谢

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

版本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
);

针对以下内容运行第一个选项将起作用,而在复制后将第三个选项运行失败。

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;
/

2 个答案:

答案 0 :(得分:1)

似乎是由于oracle的错误。该错误已在oracle 12.2上修复。 以下是一些关键信息:

错误17871192:ILM策略在列不可见的桌子上出现ORA-01741失败

问题:

添加了不可见的非null默认列的表上的ADO策略失败 并显示以下消息:

ORA-12012:自动执行作业“ SYS”时出错。“ ILMJOB2628” ORA-1741:非法的零长度标识符 ORA-6512:位于“ SYS.DBMS_REDEFINITION”的第2525行

诊断分析:

要重现,您需要一个表,该表的列包含以下命令 添加:

在表“ ILMT3”中添加“ C4” varchar2(10)不可见默认值''不为null;

必须复制所有三个属性。

WORKAROUND:

不要使用其中一个属性

发行说明:

]]缺少看不见的列元数据。

重新发现信息:

在“看不见的列”中缺少列名,则您遇到了这个问题。

答案 1 :(得分:1)

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

让我们在您的情况下,在 DB版本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

DB版本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.

因此,结果紧随其后

  • 版本12c发行版1消除了主要问题 ORA-042067,而不是ORA-01741。因此,需要为INVISIBLE表的THE_DATE (DATE)列添加REDEFINER选项,以实现originalinterim表之间的真实列映射。
  • 即使为上述列添加了INVISIBLE选项,您也会 对于版本 R1 ,仍然获得相同的错误代码(ORA-01741),而 您将成功获得版本 R2 。因此,升级似乎是
  • 顺便说一句,每次我们尝试删除已实现的REDEFINER表时 需要删除 R1 的视图,但不删除 R2 的视图。有趣,可能是一个错误...