【问题标题】:Importing dump using impdp throws ORA-39083 and ORA-04079 (invalid trigger specification)使用 impdp 导入转储会引发 ORA-39083 和 ORA-04079(无效的触发器规范)
【发布时间】:2021-12-12 21:21:34
【问题描述】:

导入包含触发器的 dp 转储文件会出现错误 ORA-39083 和 ORA-04079。 我在 Windows 10 上使用 Oracle XE 11g 64 位。 我导出了一个包含状态为“VALID”的触发器的架构。 当我在同一个数据库(但不同的架构)中再次导入转储文件时,它会引发上述异常。

导入日志显示失败的 SQL。 但是,它只显示了 CREATE TRIGGER-sql 的一部分。 接下来是导出和导入日志,以及相关的触发器。

导出日志

;;; 
Export: Release 11.2.0.2.0 - Production on Wed Oct 27 16:42:13 2021

Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.
;;; 
Connected to: Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
Starting "VBSDB"."SYS_EXPORT_SCHEMA_01":  VBSDB/********@XE DIRECTORY=VBS DUMPFILE=20211027_164212_$VBSDB.dpdmp LOGFILE=20211027_164212_$VBSDB.dplog VERSION=11 EXCLUDE=STATISTICS 
Estimate in progress using BLOCKS method...
Processing object type SCHEMA_EXPORT/TABLE/TABLE_DATA
Total estimation using BLOCKS method: 3.812 MB
Processing object type SCHEMA_EXPORT/PRE_SCHEMA/PROCACT_SCHEMA
Processing object type SCHEMA_EXPORT/TYPE/TYPE_SPEC
Processing object type SCHEMA_EXPORT/SEQUENCE/SEQUENCE
Processing object type SCHEMA_EXPORT/TABLE/TABLE
Processing object type SCHEMA_EXPORT/TABLE/INDEX/INDEX
Processing object type SCHEMA_EXPORT/TABLE/CONSTRAINT/CONSTRAINT
Processing object type SCHEMA_EXPORT/TABLE/COMMENT
Processing object type SCHEMA_EXPORT/FUNCTION/FUNCTION
Processing object type SCHEMA_EXPORT/FUNCTION/ALTER_FUNCTION
Processing object type SCHEMA_EXPORT/VIEW/VIEW
Processing object type SCHEMA_EXPORT/TABLE/CONSTRAINT/REF_CONSTRAINT
Processing object type SCHEMA_EXPORT/TABLE/TRIGGER
Processing object type SCHEMA_EXPORT/TABLE/INDEX/FUNCTIONAL_AND_BITMAP/INDEX
...
. . exported "VBSDB"."FIN_BETALING"                          0 KB       0 rows
...
Master table "VBSDB"."SYS_EXPORT_SCHEMA_01" successfully loaded/unloaded
******************************************************************************
Dump file set for VBSDB.SYS_EXPORT_SCHEMA_01 is:
  D:\DATABASES\20211027_164212_$VBSDB.DPDMP
Job "VBSDB"."SYS_EXPORT_SCHEMA_01" successfully completed at 16:42:27

导入日志

;;; 
;;; 
Import: Release 11.2.0.2.0 - Production on Wed Oct 27 16:42:35 2021

Copyright (c) 1982, 2009, Oracle and/or its affiliates.  All rights reserved.
;;; 
Connected to: Oracle Database 11g Express Edition Release 11.2.0.2.0 - 64bit Production
Master table "VBSDB2"."SYS_IMPORT_SCHEMA_01" successfully loaded/unloaded
Starting "VBSDB2"."SYS_IMPORT_SCHEMA_01":  USERID=VBSDB2/********@XE directory=VBS dumpFILE=20211027_164212_$VBSDB.DPDMP logfile=271021164234.oracleimplog.txt schemas=VBSDB remap_schema=VBSDB:VBSDB2 transform=oid:n 
Processing object type SCHEMA_EXPORT/PRE_SCHEMA/PROCACT_SCHEMA
Processing object type SCHEMA_EXPORT/TYPE/TYPE_SPEC
Processing object type SCHEMA_EXPORT/SEQUENCE/SEQUENCE
Processing object type SCHEMA_EXPORT/TABLE/TABLE
Processing object type SCHEMA_EXPORT/TABLE/TABLE_DATA
...
. . imported "VBSDB2"."FIN_BETALING"                         0 KB       0 rows
...
Processing object type SCHEMA_EXPORT/TABLE/INDEX/INDEX
Processing object type SCHEMA_EXPORT/TABLE/CONSTRAINT/CONSTRAINT
Processing object type SCHEMA_EXPORT/FUNCTION/FUNCTION
Processing object type SCHEMA_EXPORT/FUNCTION/ALTER_FUNCTION
Processing object type SCHEMA_EXPORT/VIEW/VIEW
Processing object type SCHEMA_EXPORT/TABLE/CONSTRAINT/REF_CONSTRAINT
Processing object type SCHEMA_EXPORT/TABLE/TRIGGER
ORA-39083: Object type TRIGGER failed to create with error:
ORA-04079: invalid trigger specification
Failing sql is:
CREATE TRIGGER "VBSDB2"."T_FIN_BETALING_DELETE" 
BEFORE DELETE
ON FIN_BETALING
FOR EACH ROW
 WHEN (OLD.VERREKENINGFACTUURREGELID IS NOT NULL)     V_MSG := 'De betaling-id ' || TO_CHAR(:OLD.FIN_BETALINGID) || ' is reeds doorgestort en kan derhalve niet verwijderd worden';    IF V_AFREKENINGID IS NOT NULL THEN        V_MSG := V_MSG || ' (afrekening-id ' || TO_CHAR(V_AFREKENINGID) || ', beheer
Processing object type SCHEMA_EXPORT/TABLE/INDEX/FUNCTIONAL_AND_BITMAP/INDEX
Job "VBSDB2"."SYS_IMPORT_SCHEMA_01" completed with 1 error(s) at 16:42:44

触发器

CREATE TRIGGER VBSDB.T_FIN_BETALING_DELETE
  BEFORE DELETE
  ON VBSDB.FIN_BETALING
  FOR EACH ROW
  WHEN (OLD.VERREKENINGFACTUURREGELID IS NOT NULL)
DECLARE
  V_AFREKENINGID NUMBER;
  V_BOVK         VARCHAR2(50 CHAR);
  V_MSG          VARCHAR2(255 CHAR);
BEGIN

  SELECT A.PRG_AFREKENINGID,
         C.CONTRACTNRSTR
    INTO V_AFREKENINGID,
         V_BOVK
    FROM FIN_FACTUURREGEL FR
      JOIN FIN_FACTUUR F
        ON FR.FIN_FACTUURID = F.FIN_FACTUURID
      JOIN PRG_CONTRACT C
        ON C.PRG_CONTRACTID = F.PRG_CONTRACTID
      JOIN PRG_AFREKENING A
        ON F.BEHFACTAFREKENINGID = A.PRG_AFREKENINGID
    WHERE FR.FIN_FACTUURREGELID = :OLD.VERREKENINGFACTUURREGELID;

  V_MSG := 'De betaling-id ' || TO_CHAR(:OLD.FIN_BETALINGID) || ' is reeds doorgestort en kan derhalve niet verwijderd worden';

  IF V_AFREKENINGID IS NOT NULL
  THEN
    V_MSG := V_MSG || ' (afrekening-id ' || TO_CHAR(V_AFREKENINGID) || ', beheerovereenkomst ' || V_BOVK || ')';
  END IF;

  RAISE_APPLICATION_ERROR(-20500, V_MSG);
END;
/

事实证明,仅当 CREATE TRIGGER-sql 通过 .NET 和 ODT for Visual Studio 2019 (ODP.net 4.122.19.1) 执行时才会出现问题。 但是,通过 System.Data.OracleClient 命名空间执行 SQL 时也会出现问题。 当通过 DBForge 执行相同的 CREATE TRIGGER-sql 时,则导出和导入成功。虽然,在第一种情况下,Oracle 无法成功完成抽水工作是很奇怪的,因为触发器具有 VALID 状态。

我使用的代码:

private const string SQL = @"CREATE OR REPLACE TRIGGER T_FIN_BETALING_DELETE 
BEFORE DELETE 
ON FIN_BETALING 
FOR EACH ROW 
WHEN (OLD.VERREKENINGFACTUURREGELID IS NOT NULL)
DECLARE
    V_AFREKENINGID NUMBER;
    V_BOVK VARCHAR2(50 CHAR);
    V_MSG VARCHAR2(255 CHAR);
BEGIN

    SELECT
    A.PRG_AFREKENINGID,
    C.CONTRACTNRSTR INTO V_AFREKENINGID, V_BOVK
    FROM
    FIN_FACTUURREGEL FR
    JOIN FIN_FACTUUR F on FR.FIN_FACTUURID = F.FIN_FACTUURID
    JOIN PRG_CONTRACT C ON C.PRG_CONTRACTID = F.PRG_CONTRACTID
    JOIN PRG_AFREKENING A on F.BEHFACTAFREKENINGID = A.PRG_AFREKENINGID
    WHERE FR.FIN_FACTUURREGELID = :OLD.VERREKENINGFACTUURREGELID;

    V_MSG := 'De betaling-id ' || TO_CHAR(:OLD.FIN_BETALINGID) || ' is reeds doorgestort en kan derhalve niet verwijderd worden';

    IF V_AFREKENINGID IS NOT NULL THEN
        V_MSG := V_MSG || ' (afrekening-id ' || TO_CHAR(V_AFREKENINGID) || ', beheerovereenkomst ' || V_BOVK || ')';
    END IF;

    RAISE_APPLICATION_ERROR(-20500, V_MSG);
END;";

    private static void CreateTrigger(OracleConnection connection)
    {
      using (var cmd = new OracleCommand(SQL, connection))
      {
        cmd.ExecuteNonQuery();
      }
    }

我已尝试更改 CREATE TRIGGER 语句的结尾部分:

  • 通过添加/删除';'
  • 通过添加/删除 CRLF
  • 通过添加/删除“\”

任何偏离上述 SQL 语句的变体都会导致触发器进入 INVALID 状态。

剩下的问题是:是什么导致 ODP.net 创建了一个状态为 VALID 的 Oracle 触发器,该触发器无法使用数据泵再次导出和导入?

任何帮助将不胜感激!

【问题讨论】:

  • 导入完成后触发器在目标模式中是否处于无效状态?如果是这样,如果你尝试编译触发器,你会得到什么错误?
  • @RobertoHernandez 触发器在目标模式 (VBSDB2) 中不存在。
  • 你能运行这个吗? impdp USERID=xxxx directory=xxx dumpfile=xxxxx logfile=xxxx.txt remap_schema=VBSDB:VBSDB2 include=trigger content=metadata_only
  • @RobertoHernandez 它给出了 ORA-04079: invalid trigger specification。
  • 我尝试在 Oracle EE 中复制您的问题,使用带或不带引号的数据泵触发器导入/导出我没有任何问题。我怀疑您的问题可能与 Oracle XE 以及您使用的那个非常旧的版本有关

标签: database oracle datapump impdp


【解决方案1】:

关键可能是你的 DDL 中的这个子句:

ON VBSDB.FIN_BETALING

impdp 中的 remap_schema 更改了触发器名称中的架构名称(CREATE TRIGGER VBSDB.T_FIN_BETALING_DELETE 变为 CREATE TRIGGER VBSDB2.T_FIN_BETALING_DELETE),但在以下代码中没有。然后在导入期间触发器创建失败,因为它正在引用另一个模式中的表。

尝试像这样重新定义您的原始触发器并删除任何其他架构名称引用:

CREATE TRIGGER VBSDB.T_FIN_BETALING_DELETE
  BEFORE DELETE
  ON FIN_BETALING
  FOR EACH ROW
  WHEN (OLD.VERREKENINGFACTUURREGELID IS NOT NULL)
DECLARE
  V_AFREKENINGID NUMBER;
  V_BOVK         VARCHAR2(50 CHAR);
  V_MSG          VARCHAR2(255 CHAR);
BEGIN

  SELECT A.PRG_AFREKENINGID,
         C.CONTRACTNRSTR
    INTO V_AFREKENINGID,
         V_BOVK
    FROM FIN_FACTUURREGEL FR
      JOIN FIN_FACTUUR F
        ON FR.FIN_FACTUURID = F.FIN_FACTUURID
      JOIN PRG_CONTRACT C
        ON C.PRG_CONTRACTID = F.PRG_CONTRACTID
      JOIN PRG_AFREKENING A
        ON F.BEHFACTAFREKENINGID = A.PRG_AFREKENINGID
    WHERE FR.FIN_FACTUURREGELID = :OLD.VERREKENINGFACTUURREGELID;

  V_MSG := 'De betaling-id ' || TO_CHAR(:OLD.FIN_BETALINGID) || ' is reeds doorgestort en kan derhalve niet verwijderd worden';

  IF V_AFREKENINGID IS NOT NULL
  THEN
    V_MSG := V_MSG || ' (afrekening-id ' || TO_CHAR(V_AFREKENINGID) || ', beheerovereenkomst ' || V_BOVK || ')';
  END IF;

  RAISE_APPLICATION_ERROR(-20500, V_MSG);
END;
/

那么你应该可以毫无问题地导出/导入它。

【讨论】:

  • @prmdba,我认为这不是问题所在。数据泵重映射模式正在转换该子句。来自数据泵的日志显示 CREATE TRIGGER "VBSDB2"."T_FIN_BETALING_DELETE" BEFORE DELETE ON FIN_BETALING FOR EACH ROW
  • @pmdba 根据您的回答,我将没有 remap_schema 的转储导入回 VBSDB(我先清空了架构)。不幸的是,同样的问题也出现了。
猜你喜欢
  • 2016-08-02
  • 1970-01-01
  • 1970-01-01
  • 2013-07-08
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多