Oracle varchar2 和 unicode 文本

Oracle varchar2 and unicode texts

According to spec VARCHAR2(max_size CHAR) 应该存储 max_size 个字符。我观察到 Unicode 文本的 other/strange 行为。

让我们考虑一下这个例子:

create table test (id varchar2(3 char) not null, primary key (id));

insert into test(id) values('abc');
insert into test(id) values('ффф');

Query 1 ERROR: ORA-12899: value too large for column "TEST"."TEST"."ID" (actual: 6, maximum: 3)

所以varchar2 3 chars其实和byte是一样的意思? 没有:)

create table test (id varchar2(3 byte) not null, primary key (id))

insert into test(id) values('abc')
insert into test(id) values('ффф')

Query 1 ERROR: ORA-12899: value too large for column "TEST"."TEST"."ID" (actual: 18, maximum: 3)

我的问题仍然是如何告诉 Oracle varchar2 长度用于 Unicode 文本(更准确地说是 UTF8)?

更新: 是否可以写下一个 SQL 查询来显示所有 tables/columns 长度以字节为单位?

实际上,我的问题分为两部分:TablePlus 的不正确查询编码,随机列的字节长度(w/o 字符后缀):)

更新 2: 感谢@Wernfried Domscheit!

查询显示 table 和具有 varchar2 的列,长度在 bytes 中提供:

SELECT TABLE_NAME, COLUMN_NAME, DATA_LENGTH, CHAR_USED
FROM USER_TAB_COLUMNS WHERE DATA_TYPE = 'VARCHAR2' AND CHAR_USED = 'B'

你的例子对我有用:

SELECT * 
FROM V$NLS_PARAMETERS 
WHERE PARAMETER = 'NLS_CHARACTERSET';

PARAMETER          VALUE      
------------------------------
NLS_CHARACTERSET   AL32UTF8   

1 row selected.



CREATE TABLE TEST (ID VARCHAR2(3 CHAR));
Table created.

INSERT INTO TEST(ID) VALUES('abc');
1 row created.

INSERT INTO TEST(ID) VALUES('ффф');
1 row created.

也许你这边打错了?

更新:

看起来您的客户端使用了错误的字符设置。

ф (U+0444: Cyrillic Small Letter Ef) 具有这些字节值:

+-------------------------------------------------------------------------------+
|Encoding|hex        |dec (bytes)|dec       |binary                             |
+-------------------------------------------------------------------------------+
|UTF-8   |D1 84      |209 132    |53636     |11010001 10000100                  |
|UTF-16BE|04 44      |4 68       |1092      |00000100 01000100                  |
|UTF-16LE|44 04      |68 4       |17412     |01000100 00000100                  |
|UTF-32BE|00 00 04 44|0 0 4 68   |1092      |00000000 00000000 00000100 01000100|
|UTF-32LE|44 04 00 00|68 4 0 0   |1141112832|01000100 00000100 00000000 00000000|
+-------------------------------------------------------------------------------+

DUMP 应该 return Typ=1 Len=6 CharacterSet=AL32UTF8: d1,84,d1,84,d1,84 但你得到 ef,bf,bdU+FFFD: Replacement Character

你不插入ффф,它被转换为���

我想实际上您的客户端使用 UTF-8 但您没有告诉数据库,因此数据库很可能假定客户端使用默认值 US7ASCII(或其他)。客户端发送 6 个字节 (d1,84,d1,84,d1,84),但 Oracle 数据库将其解释为 6 个单字节字符。

通常您使用 NLS_LANG 环境变量来定义它。但是,dbeaver 是基于 Java 的,Java/JDBC 不使用 NLS_LANG 设置——至少默认情况下没有。