惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

H
Help Net Security
L
LINUX DO - 最新话题
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
罗磊的独立博客
宝玉的分享
宝玉的分享
博客园 - 聂微东
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Cyberwarzone
Cyberwarzone
S
Securelist
博客园_首页
Know Your Adversary
Know Your Adversary
S
Schneier on Security
雷峰网
雷峰网
L
LINUX DO - 热门话题
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Simon Willison's Weblog
Simon Willison's Weblog
Last Week in AI
Last Week in AI
P
Privacy & Cybersecurity Law Blog
Scott Helme
Scott Helme
Schneier on Security
Schneier on Security
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
P
Proofpoint News Feed
AI
AI
K
Kaspersky official blog
爱范儿
爱范儿
H
Heimdal Security Blog
S
Secure Thoughts
T
Threatpost
B
Blog RSS Feed
NISL@THU
NISL@THU
C
CERT Recently Published Vulnerability Notes
云风的 BLOG
云风的 BLOG
Spread Privacy
Spread Privacy
Microsoft Azure Blog
Microsoft Azure Blog
IT之家
IT之家
Security Latest
Security Latest
V
Vulnerabilities – Threatpost
V2EX - 技术
V2EX - 技术
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Google DeepMind News
Google DeepMind News
Vercel News
Vercel News
人人都是产品经理
人人都是产品经理
Recent Announcements
Recent Announcements
The Cloudflare Blog
T
Troy Hunt's Blog
Stack Overflow Blog
Stack Overflow Blog
MyScale Blog
MyScale Blog
D
Docker
C
Cyber Attacks, Cyber Crime and Cyber Security

博客园 - AlfredZhao

impdp 遇到 TSTZ Version 报错:ORA-39405 处理实践 数据乱成一锅粥,还能先做本体吗? Podman 报错:普通用户无法运行 rootless Podman 怎么办 语义层构建:企业级AI落地绕不开的关键 AI时代最扎心的真相:人类在打杂,AI在做决策 Win7老系统登录报错怎么解?PuTTY这次真能救急 Linux 主机防火墙如何同时开启 80 和 443? AI 编程变更记录:知识加工模块与博客工厂模块的状态重新定义 一篇搞定:用 curl 测试私有部署模型联通性 DBA除了修库,还能把经验变成更大的价值 原本3GB+ 的 Docker 镜像直接缩成500M RAG技术从1.0到4.0,系统为何越来越“会想” 生产环境里,为什么不建议把普通端口直接暴露到公网? ORACLE默默地搞了个免费的智能体工厂 GPT 省钱,不是别用最新模型,而是别浪费缓存 Docker 容器时区不对,`timedatectl` 不存在怎么办? AI 编程工作总结:从体验问题到模块能力建设 OCI 明明分配了 200G 系统盘,为什么 df 只看到 30G? vi 删除指定范围的行,不用再反复按 dd AI编程系列02:合并知识功能,给 AI 问数和 RAG 场景打基础 AI编程系列01:裸 API 账单场景下,如何自建 LLM 用量可视化看板 氛围编程实战系列:先规划清楚学习路径 入门:我的第一个Vibe Coding实践程序 Linux时区修改为CST 如何在Oracle Agent Factory中配置国内厂商的LLM? Oracle Deep Data Security (Deep Sec) 初体验 APEX实战第13篇:全套开发环境的本地配置与恢复实践 Codex 和 OpenClaw,到底差在哪? 微信对接OpenClaw的常见问题和解决方案 在群晖NAS上配置OpenClaw:一次踩坑后的保姆级教程(完整修订版) 用Docker安全驯服OpenClaw,并打通社交软件 RAG 时代的“破壁人”:为什么你的大模型应用急需 Docling? 为什么 AI 服务器首选 Ubuntu?难道 OEL 和 RHEL 不香吗? APEX实战第12篇:Oracle APEX 工作区密码忘记了怎么办? AI开发者如何无痛部署Oracle AI Database 26ai环境 Oracle 26ai 本地通用版这次是真的来了 Docker 快速入门:手把手教你打包 Python 应用 APEX实战第11篇:图形界面轻松解锁工作区账户 APEX实战第10篇:手把手教你给APEX打补丁 APEX实战第9篇:手把手教你集成RAS轻松实现真正的数据安全 小白学AI开发01:创建第一个示例Agent LangChain、LangFlow、LangGraph:一文讲清三大 LLM 框架的定位与差异 使用 Oracle 官方 HR Demo 快速验证 RAS 功能(小白实战指南) Oracle RAS:AI时代企业数据安全核心 新版MOS(My Oracle Support)主要变化 APEX实战第8篇:ORDS连库报错574?一招根治用户过期问题 为什么 Iceberg 在数据湖领域这么火
SQL*Plus 执行中文 SQL 文件,如何避开乱码坑
AlfredZhao · 2026-07-15 · via 博客园 - AlfredZhao

2026-07-15 18:32  AlfredZhao  阅读(0)  评论()    收藏  举报

在 Linux 上用 sqlplus @xxx.sql 执行脚本时,只要 SQL 文件里有中文字符串或中文注释,就可能遇到乱码。这个问题通常不是数据库本身坏了,而是 SQL 文件编码、Linux Locale、SQL*Plus 客户端字符集没有对齐。

01 | 先看清三个关键角色

执行 SQL 文件时,至少涉及三处字符集:

  • Linux Locale:由 LANGLC_CTYPE 控制,影响 Shell 如何处理文本。
  • SQL*Plus 客户端字符集:由 NLS_LANG 控制。
  • SQL 文件实际编码:常见是 UTF-8 或 GBK。

核心原则很简单:

SQL 文件编码要和 NLS_LANG 对应的客户端字符集一致,再由 Oracle 负责客户端与数据库之间的字符集转换。

这里最容易误解的是:NLS_LANG 表示客户端字符集,不是数据库字符集。

02 | UTF-8 文件的推荐配置

大多数 Linux 环境和编辑器默认已经使用 UTF-8,因此更推荐统一使用 UTF-8。

export LANG=en_US.UTF-8
export NLS_LANG=AMERICAN_AMERICA.AL32UTF8

如果使用中文 Locale,也可以是:

export LANG=zh_CN.UTF-8
export NLS_LANG=SIMPLIFIED CHINESE_CHINA.AL32UTF8

SQL 文件建议保存为:

  • UTF-8
  • 无 BOM,也就是 UTF-8 without BOM

如果 SQL 文件本身是 GBK 编码,才使用:

export LANG=zh_CN.GBK
export NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK

03 | 不要盲目照抄数据库字符集

很多人看到数据库字符集是 ZHS16GBK,就直接设置:

export NLS_LANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK

这只有在客户端 SQL 文件本身也是 GBK 编码时才合适。

如果 SQL 文件是 UTF-8,而数据库字符集是 ZHS16GBK,客户端仍然应该按 UTF-8 设置:

export NLS_LANG=AMERICAN_AMERICA.AL32UTF8

此时 Oracle 会完成字符集转换:

UTF-8(客户端)
↓
Oracle Character Conversion
↓
ZHS16GBK(数据库)

所以排查时不要只盯数据库字符集,更要先确认 SQL 文件到底是什么编码。

04 | 如何确认文件和数据库字符集

查看 SQL 文件编码,优先用:

file test.sql
file -i test.sql

如果输出中看到 charset=utf-8,说明是 UTF-8。若显示 UTF-8 Unicode (with BOM),说明文件带 BOM。

也可以用 iconv 验证 UTF-8 是否合法:

iconv -f UTF-8 -t UTF-8 test.sql >/dev/null
echo $?

返回 0 表示合法 UTF-8;如果出现 illegal input sequence,说明不是合法 UTF-8。

检查是否带 BOM:

xxd -l 16 test.sql

如果文件开头出现:

ef bb bf

说明带 BOM。

数据库字符集可以用 SQL 查询:

SELECT value
FROM nls_database_parameters
WHERE parameter = 'NLS_CHARACTERSET';

常见结果可能是 AL32UTF8ZHS16GBK

05 | LC_ALL 不一定要设置

通常不需要刻意设置 LC_ALL。Locale 优先级大致是:

LC_ALL
↓
LC_*
↓
LANG

SQL*Plus 中文乱码更相关的是:

  • LANG
  • LC_CTYPE
  • NLS_LANG

很多环境只设置下面这一项就够了:

export LANG=en_US.UTF-8

LC_ALL 是强制覆盖所有 Locale 设置,并不是解决 SQL*Plus 中文乱码的关键。有些系统还可能没有安装对应 Locale,导致 cannot change locale。可以先确认系统支持项:

locale -a

06 | 一套稳妥排查顺序

遇到乱码时,建议依次执行:

locale
echo $LANG
echo $NLS_LANG
file -i test.sql

再查数据库字符集:

SELECT value
FROM nls_database_parameters
WHERE parameter='NLS_CHARACTERSET';

笔者更推荐的长期做法是:团队统一使用 UTF-8 无 BOM 的 .sql 文件,并配置:

export LANG=en_US.UTF-8
export NLS_LANG=AMERICAN_AMERICA.AL32UTF8

这样可以减少 UTF-8、GBK 混用带来的跨平台问题。

一句话总结:保持 SQL 文件编码、Linux Locale 和 NLS_LANG 一致,让 Oracle 负责客户端与数据库之间的字符集转换,是避免 SQL*Plus 中文乱码的稳妥方案。

关注我,和AI一起成长~