字符 146 在 Oracle SQLDeveloper 数据库副本上转换为 14844057

Character 146 converted to 14844057 on Oracle SQLDeveloper Database copy

我正在使用 Oracle SQL 开发人员进行数据库复制,工具>数据库复制...

来自:Oracle Database 11g 版本 11.1.0.6.0 - 64 位生产 至:Oracle Database 12c Standard Edition Release 12.2.0.1.0 - 64 位生产

用 Oracle ASCII() 函数解释的旧数据库中的单引号 return 146。 来自 Oracle ASCII() 函数的新副本 return 14844057 中的单引号 如果我尝试将单引号放入 Varchar2(1) 变量中,单引号也会崩溃 PL/SQL。

导致此字符转换的原因是什么?

我不知道字符翻译是SQL开发人员问题、Oracle 版本问题还是我不​​知道的 Oracle 中的某些设置。

让我们澄清一下“单引号”的含义。首先,是基本的“直”单引号字符 '(用作开始和结束引号),标准 ASCII 集的一部分,位于位置 39。然后,有“书法" 左右单引号字符 - 以 Unicode 和其他字符集表示(但不是基本 ASCII 字符集的一部分)。

ASCII() 函数,与其名称相反,与 ASCII 几乎没有关系,除了在字符实际包含在 ASCII 集中的情况下,函数 returns 它们的 ASCII 码.一般来说,函数returns表示字符在数据库中的十进制编码。请注意,Oracle 文档本身是错误的:它说“字符 set 中的表示”,但实际上它是 encoded 值,而不是字符的代码点。这在 Unicode 中产生了巨大的差异。 (事实上​​ ASCII() returns ASCII 字符的 ASCII 码只是因为在大多数(如果不是全部)字符编码中,ASCII 字符的编码等于它们的 ASCII 码。这是兼容性非常方便,但这不是理论上的要求 - 这只是一个实际问题。)

右单引号字符编码在字符集146位置CP1252,在Oracle中叫做WE8MSWIN1252。这很可能是您旧数据库中的数据库字符集。

同一个字符在Unicode的UTF-8编码中的编码是14844057。您的数据库“字符集”(实际上,编码)很可能是AL32UTF8.

你将可以在两个数据库中找到数据库“字符集”,并确认我所说的,

select value from v$nls_parameters where parameter = 'NLS_CHARACTERSET';

您可以与您的 DBA 联系以确认新数据库使用与旧数据库不同的字符集。

至于单引号(真的:右单引号,我们说的那个),在Unicode中是多字节字符。如果它被 varchar2(1) 拒绝,这意味着您的字符长度语义是 BYTE 而不是 CHAR。请尝试使用 varchar2(1 char)(明确表示 1 的含义)。你可以在这个答案的末尾看到一个插图。

相同的赋值在旧数据库中可能工作正常,不管它的长度语义如何,因为在 CP1252 中正确的单-引号字符被编码为单字节。

因此,这是示例。我分配的字符是右单引号字符,我的数据库字符编码是AL32UTF8,我的NLS_LENGTH_SEMANTICSBYTE.

失败:

declare
  x varchar2(1);
begin
  x := '’';
end;
/


Error starting at line : 1 in command -
declare
  x varchar2(1);
begin
  x := '’';
end;
Error report -
ORA-06502: PL/SQL: numeric or value error: character string buffer too small
ORA-06512: at line 4
06502. 00000 -  "PL/SQL: numeric or value error%s"
*Cause:    An arithmetic, numeric, string, conversion, or constraint error
           occurred. For example, this error occurs if an attempt is made to
           assign the value NULL to a variable declared NOT NULL, or if an
           attempt is made to assign an integer larger than 99 to a variable
           declared NUMBER(2).
*Action:   Change the data, how it is manipulated, or how it is declared so
           that values do not violate constraints.
           

作品:

declare
  x varchar2(1 char);
begin
  x := '’';
end;
/

PL/SQL procedure successfully completed.