ALTER DATABASE CHARACTER SET 在 Oracle 12c 中基本不可用,因其仅适用于非 CDB 模式,不支持多租户架构下的 PDB 字符集变更,且要求所有字符列字节长度能无损映射至目标字符集,真实环境中几乎无法满足。
不能直接用 alter database character set 修改已存在数据的字符集,除非满足极严格前提——否则会损坏数据或触发 ora-12712 错误。
为什么 ALTER DATABASE CHARACTER SET 在 12c 中基本不可用
Oracle 12c 默认启用多租户(CDB/PDB),而 ALTER DATABASE CHARACTER SET 是针对非 CDB 模式的旧语法。即使你连的是 CDB$ROOT,该命令也仅作用于 CDB 层,不自动同步到 PDB;更关键的是,它要求数据库中所有字符类型列(VARCHAR2、CHAR、CLOB 等)的当前字节长度必须能无损映射到目标字符集——这在真实业务库中几乎不可能满足。
常见错误现象:
- 执行
ALTER DATABASE CHARACTER SET AL32UTF8后报错:ORA-12712: new character set must be a superset of the old character set - 强行加
INTERNAL_USE后看似成功,但后续插入中文时报ORA-01401: inserted value too large for column,或查询乱码 - PDB 中用户对象无法访问,
SELECT * FROM NLS_DATABASE_PARAMETERS显示字符集已改,但V$NLS_PARAMETERS仍为旧值
真正可行的字符集变更路径:从 INTERNAL_USE 到 DMU 工具
Oracle 官方明确将 ALTER DATABASE CHARACTER SET ... INTERNAL_USE 标记为“仅用于紧急修复且不支持”的内部机制,12c 起唯一受支持的迁移方式是使用 Database Migration Assistant for Unicode (DMU) 工具。
实操建议:
- 确认当前字符集:
SELECT PROPERTY_VALUE FROM DATABASE_PROPERTIES WHERE PROPERTY_NAME = 'NLS_CHARACTERSET'; - 若当前是
WE8MSWIN1252或ZHS16GBK,目标是AL32UTF8,必须先用 DMU 扫描全部表、列、约束、索引,识别潜在截断/转换风险 - DMU 不修改原库,而是生成可执行的转换脚本 + 数据重载方案;它会自动处理
CLOB编码转换、NCHAR列对齐、约束重建等细节 - 不要跳过“预检查”步骤——例如某
VARCHAR2(10)列存了 10 个 GBK 中文,在 AL32UTF8 下需至少 30 字节空间,DMU 会提示你先ALTER TABLE ... MODIFY col VARCHAR2(30)
INTERNAL_USE 的唯一适用场景与高危操作要点
仅当满足以下全部条件时,才考虑用 INTERNAL_USE(如迁移测试库、空库、或已确认无任何用户数据的 PDB):
- 数据库处于
RESTRICTED SESSION模式,且无任何活跃连接 - 已关闭所有后台进程:
ALTER SYSTEM SET JOB_QUEUE_PROCESSES=0、AQ_TM_PROCESSES=0 - 目标字符集是源字符集的严格超集(如
ZHS16GBK → AL32UTF8可行,AL32UTF8 → ZHS16GBK绝对禁止) - 执行顺序必须是:
SHUTDOWN IMMEDIATE→STARTUP MOUNT→ALTER SYSTEM ENABLE RESTRICTED SESSION→ALTER DATABASE OPEN→ALTER DATABASE CHARACTER SET INTERNAL_USE AL32UTF8
注意:INTERNAL_USE 不校验数据,也不调整列宽。如果已有数据,后续必须人工逐表检查 VARCHAR2 长度是否足够,否则插入失败。
PDB 级别字符集变更必须单独处理
CDB 的字符集和 PDB 的字符集可以不同(12c+ 支持 PDB-level charset),但 ALTER DATABASE CHARACTER SET 命令对 PDB 无效。正确做法是:
- 先
ALTER SESSION SET CONTAINER=pdb_name - 再运行 DMU 并指定该 PDB 为扫描目标
- 或使用
CREATE PLUGGABLE DATABASE ... USING+ 字符集参数克隆新 PDB(推荐)
试图在 PDB 中执行 ALTER DATABASE 会静默失败或报 ORA-65040: operation not allowed from within a pluggable database —— 这个错误容易被忽略,导致你以为改成功了,其实什么都没变。











