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
的列,长度在 byte
s 中提供:
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,bd
即 U+FFFD: Replacement Character
你不插入ффф
,它被转换为���
。
我想实际上您的客户端使用 UTF-8 但您没有告诉数据库,因此数据库很可能假定客户端使用默认值 US7ASCII
(或其他)。客户端发送 6 个字节 (d1,84,d1,84,d1,84
),但 Oracle 数据库将其解释为 6 个单字节字符。
通常您使用 NLS_LANG
环境变量来定义它。但是,dbeaver 是基于 Java 的,Java/JDBC 不使用 NLS_LANG
设置——至少默认情况下没有。
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
的列,长度在 byte
s 中提供:
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,bd
即 U+FFFD: Replacement Character
你不插入ффф
,它被转换为���
。
我想实际上您的客户端使用 UTF-8 但您没有告诉数据库,因此数据库很可能假定客户端使用默认值 US7ASCII
(或其他)。客户端发送 6 个字节 (d1,84,d1,84,d1,84
),但 Oracle 数据库将其解释为 6 个单字节字符。
通常您使用 NLS_LANG
环境变量来定义它。但是,dbeaver 是基于 Java 的,Java/JDBC 不使用 NLS_LANG
设置——至少默认情况下没有。