欢迎光临
我们一直在努力

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

Oracle与Hive中文乱码问题总结


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


Oracle处理:

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

  • Hive处理:

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

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


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


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


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


    一、Oracle 字符集查看

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


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

    — 方法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. 查看客户端/当前会话字符集

    — 查看当前会话的字符集设置(即客户端NLS_LANG)
    SELECT userenv('language') FROM dual;


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

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


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

    DESC FORMATTED your_table_name;

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

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

    登录 MySQL 元数据库:

    — 查看 Metastore 数据库的字符集设置
    SHOW VARIABLES LIKE 'character_set%';
    — 查看具体表的字符集
    SHOW CREATE DATABASE metastore;

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

    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. 查询/修改当前会话的字符集

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

    — 设置当前会话字符集为 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 环境:

      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:数据迁移过程中出现的乱码

    排查思路:

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

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

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

    — 将 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 习惯”不是改历史,而是规范未来。


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

    赞(0)
    未经允许不得转载:171主机测评 » Oracle(字符集分为服务端和客户端) 和 Hive(依赖 MySQL(或 PostgreSQL)存储元数据)字符集编码格式查询,中文乱码处理
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址