1

在数据库 A 上:我通过 oracle sql exp.exe 命令创建 test.dmp:

exp.exe %CONNECT% FILE=test.dmp LOG=%LOGFILE% DIRECT=Y STATISTICS=NONE

在 .log 文件中它写道:

. . export table TBL_TEST 7000 rows exported (no error!). 

版本:Oracle 数据库 11g 企业版版本 11.2.0.4.0 - 64 位生产

在数据库 B 上:我通过 imp.exe 命令导入 test.dmp:

imp.exe %CONNECT% file=test.dmp LOG=%LOGFILE% FULL=Y

在 .log 文件中,我看到错误:

. . importing table TBL_TEST
IMP-00019: row rejected due to ORACLE error 1400
IMP-00003: ORACLE error 1400 encountered
ORA-01400: cannot insert NULL into (TBL_TEST.COLUMN_A)

版本:Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

TBL_TEST.COLUMN_A 类型为 NUMBER(1,0),Nullable=No,DATA_DEFAULT=0。

这怎么可能?在数据库 A 上,“COLUMN_A”列已填充,并且也定义为非空值。所有表都是在数据库 B 上从头开始重新创建的。

你知道为什么会发生这种情况吗?

先感谢您,

路易莎·布拉杜斯卡

4

1 回答 1

0

这看起来像有问题的列被添加到已经有数据的现有表中。在以前的版本中,这可能非常缓慢。如果没有指定默认值,则将添加该列,通过更新为所有现有行设置其值,然后才能添加非空约束。使用默认值,更新将自动发生,但仍需要时间。

在 11g 中,当您指定默认值时,Oracle 消除了这种痛苦。这使得列添加几乎是即时的,并且对查询是透明的。这在文档中进行了解释:

如果为 NOT NULL 列指定 DEFAULT 子句,则默认值将存储为元数据,但列本身不会填充数据。但是,指定新列的后续查询将被重写,以便在结果集中返回默认值。

exp工具不理解这一点。它导出列中的值,对于旧行,这将为空。

您需要使用datapump 导出工具,expdp代替 - 这将在转储数据中包含默认值,因此它将正确插入到数据库 B 表中。然后您当然需要impdp用于导入。

于 2014-08-21T10:16:04.093 回答