3

我有 2 个数据库,我想将包含 CHAR 列的现有表从数据库 A 传输到数据库 B。

数据库 A 是 Oracle 9i,编码为 WE8ISO8859P1,并包含一个表“foo”,其中至少有 1 列类型为 CHAR(1 char)。我无法更改数据库 A 上的表,因为它是第三方设置的一部分。

数据库B是我自己的Oracle 10g数据库,由于各种原因使用编码AL32UTF8,我想将foo复制到这个数据库中。

我设置了从数据库 B 到数据库 A 的数据库链接。然后发出以下命令:

*从#link#.foo中选择*创建表格栏;*

数据被很好地复制了,但是当我检查列的类型时,我注意到 CHAR(1 char) 已转换为 CHAR(3 char),并且在查询数据库 B 中的数据时,它都用空格填充.

我认为在水下某处,Oracle 混淆了它自己的字节和字符。CHAR(1 byte) 与 CHAR(1 char) 等不同。我已经阅读了所有这些内容。

为什么数据类型变为填充的 CHAR(3 char) 以及如何阻止 Oracle 这样做?

编辑:这似乎与在 Oracle 9 和 10 的两个特定补丁级别之间传输 CHAR 有关。看起来这确实是一个错误。一旦我发现我会发布更新。同时:不要尝试像我描述的那样在数据库之间移动 CHAR。VARCHAR2 工作正常(经过测试)。

编辑 2:我找到了答案并将其发布在这里: Why does Char(1) change to Char(3) when copying over an Oracle DBLINK? 太糟糕了,我不能接受自己的答案,因为我的问题已经解决了。

4

3 回答 3

3

此问题是由 Oracle(错误)处理基于原始列长度定义的不同字符集之间的字符转换的方式引起的。当您以字节为单位定义字符类型列的大小时,Oracle 不知道如何进行转换并拒绝它。解决方案是始终以 characters 定义字符类型的长度

要更深入地解释这个问题以及我是如何解决这个问题的,请查看 http://www.rolfje.com/2008/11/04/transporting-oracle-chars-over-a-dblink/

于 2008-11-04T21:17:57.197 回答
2

您需要了解 WE8ISO8859P1 NLS(将字符存储在一个字节中)和 AL32UTF8 之间的区别,后者将字符存储在最多四个字节中。您将需要花一些时间阅读 Oracle 国家语言支持 (NLS)文档。Oracle 通过数据库链接自动进行转换,以提供帮助。

在 SQL 提示符下尝试以下操作:

ALTER SESSION NLS_NCHAR WE8ISO8859P1 
create table bar as select * from #link#.foo;
于 2008-10-31T16:20:01.370 回答
1

我要尝试的第一件事是将表创建为不是 CTAS,而是使用列定义列表,并尝试执行前几千行的插入。如果那没有成功,那么原因就很清楚了……而且您很快就会确认 Thomas Low 已经死定了。

于 2008-10-31T16:55:15.497 回答