0

我们有一个 Oracle 12.1 数据库,其中MAX_STRING_SIZE已设置为EXTENDED,从而可以使用VARCHAR2(32767)列。我们通过物化视图和数据库链接将数据复制到 Oracle 11.2 数据库。一切都顺利运行了三年,直到我们删除并重新创建 mview(在开发中)并得到一个错误

ORA-00910: specified length too long for its datatype

一个最小的测试用例在源数据库(12.1)上有一个表。请注意,实际值非常短,并且不使用声明的长度。所以这只是关于声明而不是关于数据:

CREATE TABLE sematest (
  vc_char VARCHAR2(4000 CHAR),
  vc_byte VARCHAR2(4000 BYTE)
);
INSERT INTO sematest VALUES ('char','byte');

列定义为:

SELECT column_name,data_type,data_length,char_length,char_used 
  FROM user_tab_columns 
 WHERE table_name = 'SEMATEST';

COLUMN_NAME DATA_TYPE DATA_LENGHT CHAR_LENGTH CHAR_USED
VC_CHAR     VARCHAR2        16000        4000         C
VC_BYTE     VARCHAR2         4000        4000         B

目标数据库(11.2,但如果未启用扩展数据类型,则在 12.1 上相同)可以轻松复制 data_length=4000 列,但不能复制 data_lenght=16000 列:

CREATE MATERIALIZED VIEW test_char BUILD DEFERRED REFRESH COMPLETE ON DEMAND AS
SELECT vc_char FROM sematest@dblink;
ORA-00910: specified length too long for its datatype

CREATE MATERIALIZED VIEW test_byte BUILD DEFERRED REFRESH COMPLETE ON DEMAND AS
SELECT vc_byte FROM sematest@dblink;
Materialized view TEST_BYTE created.

更令人困惑的是,这种行为取决于BUILD DEFERRED. 有了BUILD IMMEDIATE,一切都很好:

CREATE MATERIALIZED VIEW test_char BUILD IMMEDIATE REFRESH COMPLETE ON DEMAND AS
SELECT vc_char FROM sematest@dblink;
Materialized view TEST_BYTE created

真正令人沮丧的是,我们三年前已经解决了这个问题,但忘记了如何解决。请帮忙!

4

1 回答 1

2

您可以使用SUBSTRB( Docs ) 获取限制为 4000 字节的远程 16000 字节列的子字符串。请注意,如果您确实有任何行的值具有字符长度 <= 4000 但字节长度 > 4000(由于多字节字符),那么您将丢失额外的数据(您无处可将其放入 varchar2)。

在较新的版本中,您可能可以将该列转换为 a CLOB,但我认为这不适用于您的 11.2 DB。您需要升级到 12.2,以便更轻松地通过数据库链接传输 clob。如果您计划很快升级,您可以考虑使用 MVIEW DB 的扩展字符串大小。

于 2020-11-21T00:38:32.597 回答