必须在dbca“character sets”页显式选择use unicode (al32utf8),因默认继承操作系统locale(如we8mswin1252或zhs16gbk),后期无法安全修改;选后national character set自动设为al16utf16,建库脚本含characterset al32utf8;建库后alter database character set会触发ora-12712硬错误,internal_use命令风险极高;客户端nls_lang须同步设为al32utf8(如simplified chinese_china.al32utf8)并重启工具;启动后须验证nls_database_parameters等三处一致性。

建库时必须在DBCA的“Character Sets”页选AL32UTF8
新建数据库时,DBCA默认不启用AL32UTF8,而是继承操作系统 locale(如 Windows 上是 WE8MSWIN1252,Linux 上可能是 ZHS16GBK)。这个默认行为极易埋下乱码隐患,且后期无法安全修正。
关键操作点在 DBCA 流程中“Character Sets”页面(通常位于选择模板之后、存储配置之前),该页只有在 Advanced install 模式下才可见。这里有两个选项:
-
Use Unicode (AL32UTF8)—— 必须选它。这是 Oracle 官方推荐的 UTF-8 实现,支持完整 Unicode(含 emoji、越南语、代理对等) -
Use national character set (UTF8)—— 不要选。它是旧版兼容模式,不支持 surrogate pairs,已弃用
勾选前者后,NATIONAL CHARACTER SET会自动设为 AL16UTF16,这是标准搭配,不要手动改。此时生成的建库脚本里会包含 CHARACTERSET AL32UTF8,确保数据字典从初始化就按 UTF-8 解释。
建库后不能直接用ALTER DATABASE CHARACTER SET改字符集
一旦数据库非空,执行 ALTER DATABASE CHARACTER SET AL32UTF8 几乎必然报 ORA-12712: new character set must be a superset of old character set。这不是可绕过的警告,而是 Oracle 内核级硬校验。
网上流传的 ALTER DATABASE CHARACTER SET INTERNAL_USE AL32UTF8 属于未公开内部命令,风险极高:
- 不校验已有数据能否无损映射,中文可能变成乱码字节
- 破坏 Oracle Support 合同有效性,出问题官方不认
- 后续升级(如 19c → 21c)大概率失败
真正安全的做法只有一种:导出数据 → 重建数据库(DBCA 中显式选 AL32UTF8)→ 导入数据。若数据量大,可用 DMU(Database Migration Assistant for Unicode)工具辅助评估和迁移,但它仍依赖重建或导出导入流程。
客户端NLS_LANG必须匹配AL32UTF8
即使数据库已是 AL32UTF8,若客户端 NLS_LANG 设为 ZHS16GBK 或 AMERICAN_AMERICA.WE8MSWIN1252,PL/SQL Developer、SQL*Plus 等工具连接时就会触发乱码或警告“character set mismatch”。
正确设置方式(以 Windows 为例):
- 系统变量中新建或修改
NLS_LANG,值为SIMPLIFIED CHINESE_CHINA.AL32UTF8(中文环境)或AMERICAN_AMERICA.AL32UTF8(英文环境) - 修改后必须完全退出并重启所有数据库连接工具,否则不生效
- 注册表路径示例:
HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_OraDb19c_home1下的NLS_LANG字符串值
Linux 用户则应在 .bash_profile 中添加:export NLS_LANG='AMERICAN_AMERICA.AL32UTF8',然后运行 source .bash_profile。
验证AL32UTF8是否真正生效
别只信建库时的勾选,启动后必须立刻验证三处一致性:
- 数据库级:
SELECT VALUE FROM NLS_DATABASE_PARAMETERS WHERE PARAMETER = 'NLS_CHARACTERSET';—— 必须返回AL32UTF8 - 实例级:
SELECT * FROM NLS_INSTANCE_PARAMETERS;—— 关注NLS_LANGUAGE和NLS_TERRITORY是否与预期一致 - 会话级:
SELECT * FROM NLS_SESSION_PARAMETERS;—— 它受客户端NLS_LANG影响,应与数据库字符集匹配(尤其NLS_CHARACTERSET字段)
最容易被忽略的是:即使数据库和客户端都设对了,某些老旧应用(如部分 Java JDBC 驱动)仍可能通过连接字符串强制指定字符集,这时需检查 connection string 中是否含 charset=ZHS16GBK 类参数并清除。











