Oracle(字符集分为服务端和客户端) 和 Hive(依赖 MySQL(或 PostgreSQL)存储元数据)字符集编码格式查询,中文乱码处理

Oracle与Hive中文乱码问题总结


核心问题:字符集不一致导致中文乱码。


Oracle处理

  1. 检查服务端字符集:SELECT * FROM nls_database_parameters WHERE parameter IN ('NLS_CHARACTERSET','NLS_NCHAR_CHARACTERSET');
  2. 统一客户端NLS_LANG设置,与服务端保持一致(如ZHS16GBK或AL32UTF8)

Hive处理

  1. 修改元数据库(Metastore)字符集为UTF-8:ALTER TABLE COLUMNS_V2 MODIFY COLUMN COMMENT VARCHAR(256) CHARACTER SET utf8;
  2. 检查数据文件编码:file -i 数据文件名
  3. 设置会话字符集:SET NAMES 'utf8';

最佳实践:新建表统一使用UTF-8编码,历史表通过ETL转码处理,避免直接修改生产表编码。银行数据迁移需特别注意源文件与目标系统编码一致性。


Oracle和Hive都是怎么查sql的字符集编码格式的,中文乱码怎么处理


在银行的数据迁移和日常查询中,中文乱码是绕不开的坎,根源通常是数据库字符集客户端/文件字符集不一致。


下面分别讲 Oracle 和 Hive 怎么查字符集、怎么处理乱码。


一、Oracle 字符集查看

Oracle 的字符集分为服务端客户端两个概念,乱码往往就是它俩不一致导致的。


1. 查询服务端数据库字符集

sql 复制代码
-- 方法1:查看NLS_CHARACTERSET参数(最常用)
SELECT * FROM nls_database_parameters 
WHERE parameter IN ('NLS_CHARACTERSET', 'NLS_NCHAR_CHARACTERSET');

-- 方法2:获取完整的语言环境信息(包含客户端设置)
SELECT userenv('language') FROM dual;

结果示例

复制代码
NLS_CHARACTERSET = ZHS16GBK  或  AL32UTF8

ZHS16GBK 是简体中文字符集,AL32UTF8 是 Unicode 编码。

2. 查看客户端/当前会话字符集

sql 复制代码
-- 查看当前会话的字符集设置(即客户端NLS_LANG)
SELECT userenv('language') FROM dual;

二、Hive 字符集查看与元数据乱码解决

Hive 依赖 MySQL(或 PostgreSQL)存储元数据,中文乱码通常是 Hive 元数据库(Metastore)的字符集不是 UTF-8 造成的。


1. 查看 Hive 表注释/字段注释是否正常

sql 复制代码
DESC FORMATTED your_table_name;

如果 COMMENT 字段显示为 ??? 或乱码,基本就是元数据字符集问题。

2. 检查并修改 Hive 元数据库(MySQL)字符集

登录 MySQL 元数据库

sql 复制代码
-- 查看 Metastore 数据库的字符集设置
SHOW VARIABLES LIKE 'character_set%';
-- 查看具体表的字符集
SHOW CREATE DATABASE metastore;

修改元数据库中相关表的字段字符集为 UTF-8

sql 复制代码
use metastore;

-- 修改表注释(TABLE_PARAMS)的字符集
ALTER TABLE TABLE_PARAMS MODIFY COLUMN PARAM_VALUE VARCHAR(4000) CHARACTER SET utf8;

-- 修改字段注释(COLUMNS_V2)的字符集
ALTER TABLE COLUMNS_V2 MODIFY COLUMN COMMENT VARCHAR(256) CHARACTER SET utf8;

-- 修改分区参数(PARTITION_PARAMS)的字符集(如有)
ALTER TABLE PARTITION_PARAMS MODIFY COLUMN PARAM_VALUE VARCHAR(4000) CHARACTER SET utf8;

3. 检查数据文件本身的字符集

可以通过 Linux 命令 file -i 数据文件名 查看文件编码是否为 utf-8

如果源文件是 GBK,需要使用 iconv 等工具进行转码后再加载。

4. 查询/修改当前会话的字符集

在执行查询前,可以设置当前会话的字符集:

sql 复制代码
-- 设置当前会话字符集为 UTF-8
SET character_set_client = utf8;
SET character_set_results = utf8;
SET character_set_connection = utf8;

-- 或者直接使用 SET NAMES 命令(效果等同于上面三条)
SET NAMES 'utf8';

三、中文乱码处理实战

场景1:Oracle 查询出来的中文是问号/乱码

原因:客户端字符集(NLS_LANG)与服务端不一致。


解决方案:统一客户端 NLS_LANG 设置。

  • Linux/Unix 环境

    bash 复制代码
    export NLS_LANG="SIMPLIFIED CHINESE_CHINA.ZHS16GBK"
    # 或者
    export NLS_LANG="AMERICAN_AMERICA.AL32UTF8"
  • Windows 环境

    • 打开注册表编辑器(regedit)

    • 找到路径 HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\KEY_OracleHome

    • 修改或新建字符串值 NLS_LANG,设置为服务端一致的字符集(如 SIMPLIFIED CHINESE_CHINA.ZHS16GBK

设置 NLS_LANG 后必须重启客户端才能生效。

场景2:Hive 建表时 COMMENT 显示乱码

原因 :Hive 的元数据存储在 MySQL 中,默认字符集可能是 latin1,不支持中文。


解决方案 :参照"第二部分:Hive 元数据乱码解决",修改 Metastore 相关表的字段字符集为 utf8

场景3:数据迁移过程中出现的乱码

排查思路

  1. 检查源文件编码 :是否为 UTF-8Hive 对 UTF-8 支持最好)。

  2. 检查导入方式 :使用 LOAD DATA 命令时,可尝试加上 CHARSET 'UTF-8' 参数(取决于具体版本)。

  3. 使用转换函数:如果数据已经乱码,在 Hive 查询时可尝试通过内置函数进行修正:

    sql 复制代码
    -- 将 latin1 编码的列转换为 utf8 显示(慎用,取决于数据实际编码)
    SELECT conv(column_name, 'latin1', 'utf8') FROM table_name;

总结:最佳实践

环境 操作 核心命令/方法
Oracle 查看服务端字符集 SELECT * FROM nls_database_parameters;
Oracle 查看客户端字符集 SELECT userenv('language') FROM dual;
Oracle 修复乱码 修改环境变量 NLS_LANG 与服务端一致
Hive 查看元数据乱码 DESC FORMATTED table_name;
Hive 解决元数据乱码 修改 Metastore 数据库中相关表的字段字符集为 utf8
通用 设置会话字符集 SET NAMES 'utf8'; (MySQL)

一句话总结

Oracle 乱码先看 NLS_LANG,Hive 乱码先修 MySQL Metastore


在银行数据开发中,养成统一使用 UTF-8 编码的习惯,能避免 90% 的中文乱码问题。


在银行数据开发中,养成统一使用 UTF-8 编码的习惯,是什么意思?不是说有的表的格式不能随便修改,而且改编码是需要更高权限才行?


你这个追问非常到位,说明你已经在用生产环境的思维考虑问题了,而不仅仅是学语法。


核心结论

"养成统一使用 UTF-8 编码的习惯"不是让你去改生产表 ,而是让你在新建表、写 ETL、导文件时主动选 UTF-8,并理解乱码产生的根源。


下面分三个层次帮你彻底搞清楚。


一、"养成使用 UTF-8 习惯"到底是什么意思?

这句话针对的是你可以控制的范围,不是让你去动老旧系统。

范围 你能做的 不能做的
新建表 建表时指定 CHARSET=utf8 ---
ETL 中间文件 CSV/Parquet 统一用 UTF-8 ---
数据交换 接口文件、Kafka 消息用 UTF-8 ---
历史表 / 老旧系统 不要乱改 不要自己改 Oracle / MySQL 元数据

一句话

从你手里出去的东西,尽量用 UTF-8。存量系统,按它原来的编码处理,不乱动。


二、为什么不能随便改?你说得很对

你说的是事实:

1️⃣ 改表编码确实需要更高权限

  • 修改 Hive Metastore 字符集

    → 需要 MySQL 的 ALTER 权限,普通开发没有

  • 修改 Oracle 数据库字符集

    → 需要 DBA 权限 + 停业务 + 重建库,几乎不可能让你干

2️⃣ 改编码可能造成更严重的乱码

text

复制代码
GBK → 强制转 UTF-8(不按规则转)
=> 变成 UTF-8 环境下的“乱码永久化”
=> 比原来还难修

3️⃣ 表格式不能随便改

  • 历史表下游依赖很多

  • 你改了编码 → 下游 ETL / 应用 全部可能报错

所以

存量表不是你的事,是 DBA + 数据治理 + 业务方一起决定的事。


三、银行实际工作中怎么处理编码问题?

场景 1:你新建一张表(你有控制权)

正确做法:主动用 UTF-8

Hive

sql

复制代码
CREATE TABLE my_table (
  id INT,
  name STRING
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY '\t'
STORED AS TEXTFILE
TBLPROPERTIES ('serialization.encoding'='UTF-8');

如果底层存储是 ORC / Parquet,已经是二进制,不存在编码问题

MySQL(极少作为数仓,但可能用)

sql

复制代码
CREATE TABLE my_table (
  id INT,
  name VARCHAR(100)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

场景 2:你发现历史表乱码(你不能改表)

错误做法

  • 提工单要求 DBA 改表编码

  • 自己写 ALTER 命令

正确做法(数据层解决)

Hive 查询时转换

sql

复制代码
SELECT 
  col,
  CONVERT(col USING UTF8) AS col_utf8
FROM old_table;
Sqoop 导出 / 导入时指定编码

bash

复制代码
-- 强制使用 UTF-8
--map-column-java "name=String" \
--map-column-hive "name=STRING" \
--fields-terminated-by '\001' \
--null-string '\\N' \
--null-non-string '\\N' \
--connect "jdbc:mysql://host/db?useUnicode=true&characterEncoding=UTF-8"

场景 3:两个异构系统对接(最真实)

  • Oracle(GBK) → Hive(UTF-8)

  • 你不能改 Oracle

正确做法在 ETL 中转码

bash

复制代码
# 导出阶段指定编码
sqlplus user/pwd@orcl
set NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK
spool data.csv

# 导入 Hive 时明确使用 UTF-8
LOAD DATA INPATH '/path/data.csv'
INTO TABLE hive_table
-- 明确文件编码
-- 部分版本支持
WITH SERDEPROPERTIES ('serialization.encoding'='UTF-8');

四、一个你一定能听懂的比喻

改表编码 ≈ 把一仓库老账本的文字全用修正液改一遍

  • 你可以从今天开始用新本子(新表)

  • 但不能动老账本(历史表)

  • 老账本看不懂时,你可以配翻译(ETL 转码)

✅ 你问的"不能随便改"、"要更高权限"

完全正确,不是你能动的事情


五、面试 / 工作中可以这样说(非常加分)

*"我理解,编码问题不是随便改表。我的原则是:新表主动用 UTF-8;存量表不动;乱码在 ETL 层用转码函数或调整连接参数解决。如果全局改编码,会申请 DBA 配合,并经过充分测试。"*


总结(请你记住这三条)

情况 你能不能改 怎么办
新建表 ✅ 可以 主动指定 CHARSET=utf8
老表乱码 ❌ 不能 ETL 中转码 / 查询时转换
两个系统不一致 ❌ 不能 导出 / 导入时统一编码(不碰表)

"养成 UTF-8 习惯"不是改历史,而是规范未来。


不越权、不瞎改、不假设,这是银行数据开发的底线。

相关推荐
网管NO.11 小时前
SQL 企业实战全流程|全覆盖前置基础 + 核心语法(MySQL8.0 可直接运行)
数据库·oracle
大尚来也1 小时前
主键、外键、索引,一篇讲透
java·数据库·oracle
韶博雅2 小时前
oracle优化用到的sql
sql·oracle·ffmpeg
鸽芷咕2 小时前
金仓数据库标量子查询消除:一条SQL从32秒优化到24毫秒
数据库·sql
兔子宇航员03012 小时前
HiveSQL 中 NULL 与空字符串的区别与注意事项
数据库·数据仓库·sql
杨云龙UP2 小时前
Oracle CDB巡检脚本使用SOP:从HTML原始报告到Word正式交付_2026-05-29
运维·服务器·数据库·oracle·架构·html·巡检
保定公民2 小时前
Oracle 层次查询(CONNECT BY)完全指南:从入门到精通
数据库·sql·oracle·达梦数据库·层次查询
闪电悠米2 小时前
黑马点评-优惠券秒杀-03_basic_seckill_and_oversell
java·数据库·spring boot·spring·缓存·oracle·面试
逍遥德2 小时前
PostgreSQL --- 数组函数详解
数据库·sql·postgresql