导读:本期聚焦于南京GEO公司创作的《Oracle Chr函数怎么用?基础语法、常见疑问与避坑要点一次说清》,敬请观看详情。Oracle数据库里需要往字符串中插入换行、回车、制表符或单引号时,直接拼接往往不直观也容易出错。Chr函数可以把数值编码转换成对应字符,尤其适合处理控制字符和不可见字符,但很多人对它的参数边界和字符集影响并不清楚。本文先说明CHR(n)的基础语法、返回规则以及它和ASCII函数的互逆关系,再用SQL示例演示CHR(10)生成换行、CHR(39)拼接单引号、CHR(9)输出制表符。接着集中解答常见疑问,包括CHR(0)为何容易引发截断、多字节字符集下同一编码为何返回不同字符、NCHR与CHR有什么区别、如何用DUMP定位不可见字符。掌握这些内容后,在动态SQL、报表格式化和数据清洗时可以避开大部分隐藏字符带来的排查成本。

Oracle 的 CHR 函数经常被简化成“把数字转成字符”的工具,但真正用到动态 SQL、报表排版或数据清洗时,很多人会发现它牵涉到字符集、控制字符和不可见字符的细节。本文先把基础用法和参数规则讲清楚,再结合几个容易踩坑的场景说明如何避开常见问题。

Oracle Chr函数怎么用?基础语法、常见疑问与避坑要点一次说清

一、基础语法与返回规则

函数名不区分大小写,通常写作 CHR(n),其中 n 是数值类型参数。它返回数据库字符集里与这个数值对应的字符。最典型的例子是 CHR(65) 返回字母 A,CHR(10) 返回换行符,CHR(13) 返回回车符。可以使用下面的语句一次查看三个结果:

SELECT CHR(65) AS letter,
       CHR(10) AS line_feed,
       CHR(13) AS carriage_return
FROM dual;

虽然查询界面里换行符和回车符看起来就像空白,但它们真实存在于返回值中。可以用 LENGTH 函数观察字符串长度变化,也可以把结果导出到文本文件后查看排版效果。

参数 n 理论上接受 NUMBER 类型,也可以由其他类型隐式转换。实际使用中建议始终传入整数,避免小数或非数值造成隐式转换结果不确定。对于单字节数据库字符集,CHR 的常用范围是 0 到 255,其中 0 到 127 基本与 ASCII 表一致。超出这个范围时,Oracle 的处理方式会依赖具体字符集,结果不如常用区间稳定,因此不要依赖那些边界行为。

CHR 与 ASCII 函数互为逆运算。下面语句可以验证这个关系:

SELECT ASCII('A') AS code_value,
       CHR(ASCII('A')) AS char_value
FROM dual;

这一步在排查不可见字符时非常有用,因为可以先通过 ASCII 取出某个位置的字符编码,再用 CHR 反向生成该字符进行比对或清理。

二、操作要点:生成控制字符与特殊符号

处理报表和导出文本时,最常用的组合是制表符、回车和换行。CHR(9) 表示制表符,CHR(13) 表示回车,CHR(10) 表示换行。Windows 下的换行通常建议写成 CHR(13) || CHR(10),也就是 CRLF,而 Unix/Linux 场景可以只使用 CHR(10)。下面的语句演示如何把字段拼成一份带制表符分隔的文本行:

SELECT '姓名' || CHR(9) || '部门' || CHR(13) || CHR(10) ||
       '张三' || CHR(9) || '技术部' AS report_line
FROM dual;

这种输出在报表导出、接口报文拼接和日志格式化时很实用,可以让文本在 Excel 或文本编辑器中直接呈现正确的分列和换行结构。

另一个常见需求是在动态 SQL 中生成单引号。字符串里出现单引号时,直接用 CHR(39) 会让拼接逻辑更清晰。比如要查询 ename 等于 SMITH 的记录,可以这样写:

DECLARE
  v_sql VARCHAR2(200);
  v_cnt NUMBER;
BEGIN
  v_sql := 'SELECT COUNT(*) FROM emp WHERE ename = ' || CHR(39) || 'SMITH' || CHR(39);
  EXECUTE IMMEDIATE v_sql INTO v_cnt;
  DBMS_OUTPUT.PUT_LINE(v_cnt);
END;
/

虽然也可以使用两个连续单引号来表示字符串内的单引号,但 CHR(39) 的方式在拼接变量较多时更好阅读,也便于统一维护特殊字符。

数据清洗场景中也经常需要移除换行、回车和制表符。下面语句通过嵌套 REPLACE 把三类常见控制字符替换为空字符串:

SELECT REPLACE(
         REPLACE(
           REPLACE(column_name, CHR(10), ''),
           CHR(13), ''),
         CHR(9), '') AS cleaned_text
FROM table_name;

这类清洗在导入外部文件或拼接多行文本时非常必要。否则这些不可见字符会干扰 WHERE 条件、GROUP BY 分组和前端展示,经常出现“看着一样却关联不上”的情况。

三、常见疑问与避坑指南

第一个容易踩坑的是 CHR(0)。它返回空字符,也称 NUL 字符。虽然逻辑上它可能只是字符串中的一个字符,但在很多 Oracle 客户端、日志工具和接口程序里,空字符会被当作字符串结束标记,导致后面的内容被截断或显示异常。不要在正常业务字段里插入 CHR(0),尤其是手机号、地址、备注等文本字段。如果怀疑数据里混入了空字符,可以用 INSTR(column_name, CHR(0)) 判断,也可以结合 DUMP 查看完整字节内容。

第二个问题是字符集影响。同一个 CHR(128) 在不同数据库字符集下可能返回完全不同的字符。数据库字符集可以通过 v$nls_parameters 查看:

SELECT value
FROM v$nls_parameters
WHERE parameter = 'NLS_CHARACTERSET';

如果数据库字符集是 AL32UTF8,CHR(20013) 通常可以返回汉字“中”;但在单字节字符集下传入 20013 这样的数值可能无法得到预期结果,甚至报错。换句话说,CHR 的行为绑定数据库字符集,不是固定不变的。

和 CHR 类似的是 NCHR。区别在于 NCHR 使用国家字符集,返回 NVARCHAR2 类型,更适合需要统一 Unicode 输出的场景。下面语句可以对比两者:

SELECT CHR(20013) AS db_char,
       NCHR(20013) AS national_char
FROM dual;

如果应用需要跨环境稳定生成某个 Unicode 字符,优先考虑 NCHR,避免数据库字符集切换后 CHR 结果变化。

第三个常见疑问是如何定位不可见字符。数据看起来没问题,但 TRIM 去不掉、长度总是不对,多半是因为字段里含有非打印字符。此时不要凭肉眼判断,要用 DUMP 和 ASCII 看编码:

SELECT DUMP(column_name) AS dump_info,
       ASCII(SUBSTR(column_name, 3, 1)) AS third_char_code
FROM table_name
WHERE id = 1;

如果第三个字符的编码是 10、13 或 9,就分别对应换行、回车和制表符。DUMP 会进一步显示每个字节的十六进制值,适合排查等号比较失败、关联不上的问题。

四、工程实践:少走弯路的几个建议

动态 SQL 中如果只是为了处理字符串里的单引号,完全可以使用绑定变量。绑定变量不仅避免大量 CHR(39) 拼接,还能降低 SQL 注入风险、提高执行计划复用率。写法如下:

DECLARE
  v_cnt NUMBER;
BEGIN
  EXECUTE IMMEDIATE 'SELECT COUNT(*) FROM emp WHERE ename = :ename'
    INTO v_cnt
    USING 'SMITH';
  DBMS_OUTPUT.PUT_LINE(v_cnt);
END;
/

只有在确实需要生成控制字符、输出定长报文、拼接特殊分隔符时,才显式使用 CHR,这样代码意图更清楚。

当系统里多处使用换行符、制表符时,建议把这些值封装为包常量,而不是在 SQL 里到处写裸的 CHR(10)。例如:

CREATE OR REPLACE PACKAGE char_const AS
  c_lf CONSTANT VARCHAR2(1) := CHR(10);
  c_cr CONSTANT VARCHAR2(1) := CHR(13);
  c_tab CONSTANT VARCHAR2(1) := CHR(9);
  c_quote CONSTANT VARCHAR2(1) := CHR(39);
END;
/

调用时使用 char_const.c_lf 这样的命名常量,既方便统一修改,也能让同事一眼看懂当前插入的是哪种控制字符。

最后建议在关键业务表上建立不可见字符检查脚本。可以定期用 INSTR 检查 CHR(10)、CHR(13)、CHR(9) 和 CHR(0) 是否出现在文本字段中。发现异常后,再结合 REPLACE 清洗或追溯到上游导入任务。与其等到报表显示混乱、关联失败甚至接口传输截断后再查,不如把检查放到数据入库或定时任务里,处理成本会低很多。

Oracle Chr函数ASCII码转换SQL特殊字符处理修改时间:2026-10-04 11:37:32

免责声明:已尽一切努力确保本网站所含信息的准确性。网站作品多为原创整理与精心创作,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们进行处理Email:chomcom@qq.com。
引用或转载本作品时,请注明当前出处:https://www.ipipp.com/html/1004/65538.html,基于非商业用途的前提下,欢迎转载或二创本作品。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。