【ORACLE】这个‘‘和null不等价的场景,deepseek你怎么看?
【ORACLE】一处’'和null不等价的场景–to_char(number,varchar2)
背景
最近在做一个国产数据库替代项目,要求将ORACLE迁移到一个openGauss系数据库,迁移后,执行一个存储过程时,发现国产库的执行结果和ORACLE不一致,
declare
x varchar2(10);
y varchar2(10);
begin
y:='"'||to_char(20,x)||'kg"';
dbms_output.put_line(y);
end;
/
--ORACLE: "20kg"
--国产库: "kg"
并意外发现了一处在ORACLE中’'和null并不等价的情况
SQL> select to_char(20,null),to_char(20,'') from dual;TO_CHAR(20,NULL) TO_CHAR(20,'')
---------------- --------------#SQL>
分析
先看原始问题
y:='"'||to_char(20,x)||'kg"'; 这里的to_char,在第二个参数为空时,返回的是20,但是手动执行select to_char(20,null),to_char(20,'') from dual;,都不会返回20,自然会猜想,是不是SQL引擎和PLSQL引擎里对to_char函数的处理不一样?
于是构造以下用例:
declare
x varchar2(10);
y varchar2(10);
begin
y:='"'||to_char(20,x)||'kg"';
dbms_output.put_line('PLSQL:'||y);
select '"'||to_char(20,x)||'kg"' into y from dual;
dbms_output.put_line('SQL:'||y);
end;
/
输出:
PLSQL:"20kg"
SQL:"kg"
所以结论的确就是ORACLE的to_char函数在SQL及PLSQL引擎中的确会有差异表现,但是原因是什么,由于ORACLE官方文档并未提及,且ORACLE也未开源,因此无法得知这个原因。
我只能猜想,PLSQL引擎中,to_char的第二个参数为空时,认为是没有传第二个参数(或者参数使用了默认值),相当于执行了to_char(20);而在SQL引擎中,to_char的第二个参数为空时,则进入了参数为空则返回空的逻辑。
然后看SQL引擎里to_char第二个参数传''和null的差异。
众所周知,在ORACLE中,''等同于null,因此理论上to_char(20,null) 和to_char(20,'')的返回应该一样,但实际测试却不一样,
to_char(20,null)返回nullto_char(20,'')返回#
返回#意味着提供的格式是无效的,而返回null意味着提供的格式是有效但为空的。
而出现差异的原因,可能是SQL引擎里针对函数的参数会有不同处理,比如传null时就知道是null,不去做校验,而传''时,一开始还不知道里面没有东西,就进入了格式字符串的校验逻辑。
对比下执行计划:
select 1 from dual where '1'=to_char(1,'');Plan Hash Value : 4034615273 ------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost | Time |
------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 2 | 00:00:01 |
| * 1 | FILTER | | | | | |
| 2 | FAST DUAL | | 1 | | 2 | 00:00:01 |
------------------------------------------------------------------Predicate Information (identified by operation id):
------------------------------------------
* 1 - filter(TO_CHAR(1,'')='1')
select 1 from dual where '1'=to_char(1,null);Plan Hash Value : 4034615273 ------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost | Time |
------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 0 | |
| * 1 | FILTER | | | | | |
| 2 | FAST DUAL | | 1 | | 2 | 00:00:01 |
------------------------------------------------------------------Predicate Information (identified by operation id):
------------------------------------------
* 1 - filter(NULL IS NOT NULL)
这里可以清楚地看到,如果to_char的第二个参数传null时,则SQL引擎就把to_char函数优化掉了,直接改成了null。而传''时,SQL引擎并不能提前知道''的结果也是null,因此无法优化。
其实这也是ORACLE的sql引擎和PG系数据库的差异之一,在PG系数据库里,对于一些stable和immutable的函数和操作符,当参数为常量时,可以提前先进行计算,在优化器里就已经已经把这个函数或操作符表达式的结果计算出来了,到执行器里直接使用计算的结果,通常这个行为叫常量折叠。但是ORACLE并不会提前进行常量折叠,因此这个差异能解释得通。
由于无ORACLE源码和相关材料,只能猜到这里了。
deepseek怎么看
最近deepseek大火,正好问问看deepseek怎么分析这个问题。
由于deepseek官网提供的对话服务经常超时,我使用了“硅基流动 x 华为云联合推出基于昇腾云的 DeepSeek R1推理服务”,满血版671B参数,效果远好于一些蒸馏出来的7B、32B的其他三方服务。
点击以下链接注册可以有免费的2000万tokens使用
https://cloud.siliconflow.cn/i/K1q4jqh3
问:以下是ORACLE中执行的SQL及结果,分析出现这种结果的原因,并给出明确的证据
SQL> select to_char(20,null),to_char(20,'') from dual;TO_CHAR(20,NULL) TO_CHAR(20,'')
---------------- --------------#
- 深度思考
嗯,我现在遇到了一个Oracle SQL的问题,需要仔细分析一下。题目是执行了这样的SQL语句:select to_char(20,null),to_char(20,‘’) from dual; 结果得到的是空值和#号。我需要找出为什么会这样,并且给出明确的证据。
首先,我得回忆一下Oracle中to_char函数的用法。to_char通常用于将数字或日期转换成字符串,第二个参数是格式模型。如果格式参数有问题,可能会出现不同的结果。那这里的情况是,第二个参数一个是null,另一个是空字符串’',结果分别是空和#号。为什么会这样呢?
先来看第一个情况,to_char(20, null)。当格式参数是null的时候,根据Oracle的文档,当格式模型为null时,to_char函数应该返回null。因为格式模型是必须的,如果没提供或者为null,可能无法正确转换,所以返回null。所以第一个结果为空应该是对的。
那第二个情况,to_char(20, ‘’),也就是格式参数是空字符串。这时候Oracle如何处理呢?空字符串在Oracle中通常被当作null处理吗?或者是否有其他处理方式?比如,可能当格式模型是空字符串时,Oracle无法识别,所以返回某种错误符号,比如#号。或者可能因为格式无效,所以用#号表示转换错误。
我记得在Oracle中,如果数字转换的格式模型不匹配或者无效,通常会返回一串#号。例如,如果数字太大而格式模型指定的宽度不够,就会显示#。比如,to_char(12345, ‘9999’)会返回#####,因为五位数字无法放入四位宽度的格式中。那这里的情况,空字符串作为格式模型,可能被Oracle视为无效的格式,因此返回#号作为错误指示。
但需要验证这个结论是否正确。我需要查阅Oracle的官方文档,看看当to_char函数的格式参数为null或者空字符串时,具体的行为是怎样的。
查找Oracle文档,关于TO_CHAR函数的说明。在Oracle 12c的文档中,关于TO_CHAR (number)的部分,格式参数必须是有效的数字格式模型。如果格式参数被省略,那么Oracle会使用一个默认的模型。例如,对于数字,默认的格式可能足够大以显示所有有效数字。但如果在函数中显式传递null或空字符串,如何处理?
根据Oracle的文档,当格式参数为null时,函数返回null。例如,在SQL中,很多函数当参数为null时会返回null,特别是当参数是必须的情况下。例如,TO_CHAR(number, null)会导致结果为null,因为格式模型无效或者缺失。
而对于空字符串作为格式参数的情况,可能Oracle不认为这是一个有效的格式模型。例如,空字符串可能被当作无效的格式,导致转换错误。此时,Oracle可能返回由多个’#'组成的字符串,表示转换错误。例如,当格式模型无法正确转换数字时,就会用#填充。
另外,可能需要注意Oracle处理空字符串和null的区别。在Oracle中,空字符串’‘在VARCHAR2中被视为null,也就是说,’'和null是等同的。但在某些情况下,可能函数参数的处理会有不同。例如,在TO_CHAR函数中,如果第二个参数是空字符串,是否会被视为null,还是当作无效格式?
假设当格式参数是空字符串时,Oracle可能不会将其视为null,而是尝试解析为一个格式模型。但空字符串显然不是一个有效的格式模型,所以会导致错误,从而返回#号。而null作为参数时,函数直接返回null,而不是尝试处理格式。
例如,执行以下两个语句:
SELECT TO_CHAR(20, NULL) FROM DUAL;– 返回null,显示为空SELECT TO_CHAR(20, '') FROM DUAL;– 返回#,因为格式无效所以,两者的处理方式不同,尽管在Oracle中通常’'被视为null,但在这种情况下,可能函数内部对参数的处理不同。或者,可能是在参数传递时,空字符串被当作一个非null但无效的格式处理,导致不同的结果。
为了验证这一点,可以查阅Oracle的官方文档或者进行测试。
根据Oracle的文档,当使用无效的格式模型时,TO_CHAR函数会返回由填充字符(通常是#)组成的字符串,其长度等于格式模型中格式元素的长度。例如,如果格式模型是无效的,或者无法正确表示数字,则返回#号。
例如,如果格式模型是’ABC’,这样的无效格式,那么TO_CHAR(123, ‘ABC’)可能会返回###,因为无法解析格式模型。
同样,当格式模型是空字符串时,可能被视为无效,导致返回一个#号。而NULL作为格式参数时,函数直接返回NULL,因为没有格式模型。
另一个可能的测试是,当使用不同的格式参数时,比如NULL和空字符串,是否返回不同的结果。例如,执行以下查询:
SELECT TO_CHAR(NULL) FROM DUAL; – 错误,因为缺少参数
而正确的例子是,当第二个参数是NULL时,返回NULL;当第二个参数是空字符串时,返回#。
所以,结论是:
- TO_CHAR(20, NULL)返回NULL,因为格式参数是NULL,导致结果为NULL。
- TO_CHAR(20, ‘’)返回#,因为空字符串作为格式参数是无效的,无法正确转换,所以用#号表示错误。
这符合题目中的结果,第一个字段为空,第二个字段为#。
为了找到明确的证据,可以查阅Oracle的官方文档。例如,在Oracle Database SQL Language Reference中的TO_CHAR (number)部分,其中说明:
“The optional fmt and nlsparam arguments serve the same purpose as they do in the TO_CHAR function for datetime conversion.”
而关于格式模型的有效性,如果格式模型无效,则函数可能返回错误或特定符号。例如,在数字格式模型中,如果格式不足以显示数字,则返回#号。而当格式模型为NULL时,函数返回NULL。
另外,在Oracle的文档中,可能提到当格式参数为NULL时,结果返回NULL。例如,在Oracle的文档中,某些函数当参数为NULL时,返回NULL,而不管其他参数的值如何。例如,如果TO_CHAR的第二个参数是NULL,则整个表达式的结果为NULL。
而对于空字符串的情况,可能被当作无效格式处理,导致返回错误符号。例如,在Oracle的文档中,可能指出格式模型必须是有效的,否则结果不可预测或返回错误符号。
因此,结合文档和测试结果,可以得出这样的结论:当格式参数为NULL时,TO_CHAR返回NULL;当格式参数是空字符串时,视为无效格式,返回#号。
在Oracle中,
TO_CHAR函数的第二个参数(格式模型)为NULL或空字符串''时,结果会不同。以下是具体原因和证据:1.
TO_CHAR(20, NULL)返回空值
- 原因:当格式模型为
NULL时,TO_CHAR函数直接返回NULL。Oracle的函数在处理参数时,若关键参数为NULL,通常会返回NULL。- 证据:根据Oracle官方文档,格式模型是
TO_CHAR的必选参数。若显式传递NULL作为格式模型,函数会返回NULL,因为无法进行有效转换。2.
TO_CHAR(20, '')返回#
- 原因:空字符串
''被视为无效格式模型。当格式模型无效时,Oracle无法将数字转换为字符串,因此用#表示转换错误。- 证据:Oracle文档指出,若格式模型无法正确表示数字(如格式宽度不足或语法错误),结果会用
#填充。例如:SELECT TO_CHAR(12345, '999') FROM DUAL; -- 返回 '#####'(宽度不足)空字符串
''作为格式模型,同样被判定为无效,导致返回单个#。关键区别
NULLvs 空字符串:虽然Oracle中空字符串''通常与NULL等价,但在函数参数中,NULL表示“无值”,而''是一个实际传递的非NULL但无效的字符串。因此:
-TO_CHAR(20, NULL)触发参数为NULL的逻辑,返回NULL。
-TO_CHAR(20, '')触发格式无效的逻辑,返回错误符号#。验证测试
-- 测试NULL格式模型 SELECT TO_CHAR(20, NULL) FROM DUAL; -- 结果:NULL(显示为空)-- 测试空字符串格式模型 SELECT TO_CHAR(20, '') FROM DUAL; -- 结果:'#'-- 测试无效格式模型(如'XYZ') SELECT TO_CHAR(20, 'XYZ') FROM DUAL; -- 结果:'###'(长度与格式模型相关)结论
TO_CHAR(20, NULL):格式模型为NULL,函数返回NULL。TO_CHAR(20, ''):格式模型为空字符串,视为无效格式,返回错误符号#。这种行为符合Oracle对参数处理和格式模型有效性的设计逻辑。
「tokens: 1972, speed: 8.17 tokens/s」
以上deepseek的思考并不完全正确,但是其思考方式和人类已经极其相似了,最终得到的结论和我想的也一样。
总结
- 尽管在大多数情况下,ORACLE的
null和''是等价的,但有一些场景仍然会有区别,暂且只能认为select null和select ''的结果是一致的。 - 相同的函数,在ORACLE的SQL引擎和PLSQL引擎里,表现可能会有差异,比如
to_char(number,varchar2) - deepseek牛x
- 本文作者: DarkAthena
- 本文链接: https://www.darkathena.top/archives/oracle-null-0-len-string-diff-to_char-ask-deepseek
- 版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0 许可协议。转载请注明出处
相关文章:
【ORACLE】这个‘‘和null不等价的场景,deepseek你怎么看?
【ORACLE】一处’和null不等价的场景–to_char(number,varchar2) 背景 最近在做一个国产数据库替代项目,要求将ORACLE迁移到一个openGauss系数据库,迁移后,执行一个存储过程时,发现国产库的执行结果和ORACLE不一致, …...
使用Python实现PDF与SVG相互转换
目录 使用工具 使用Python将SVG转换为PDF 使用Python将SVG添加到现有PDF中 使用Python将PDF转换为SVG 使用Python将PDF的特定页面转换为SVG SVG(可缩放矢量图形)和PDF(便携式文档格式)是两种常见且广泛使用的文件格式。SVG是…...
ComfyUI 安装教程:macOS 和 Linux 统一步骤
本教程将详细介绍如何在 macOS 和 Linux 上安装 ComfyUI。我们将从 安装 Anaconda 开始,到安装 PyTorch 和 ComfyUI,最后提供一些常见问题的解决方法。 macOS和linux安装步骤很相似 可以按照1️⃣安装anaconda2️⃣安装python3️⃣torch4️⃣comfyui Co…...
360手机刷机 360手机解Bootloader 360手机ROOT
360手机刷机 360手机解Bootloader 360手机ROOT 问:360手机已停产,现在和以后,能刷机吗? 答:360手机,是肯定能刷机的 360手机资源下载网站 360手机-360手机刷机RootTwrp 360os.top 360rom.github.io 一、…...
t113-qt
修改QT配置: # # qmake configuration for building with arm-linux-gnueabi-g ## MAKEFILE_GENERATOR UNIX # CONFIG incremental # QMAKE_INCREMENTAL_STYLE sublib# include(../common/linux.conf) # include(../common/gcc-base-unix.conf) # inc…...
【真一键部署脚本】——一键部署deepseek
目录 deepseek一键部署脚本说明 0 必要前提 1 使用方法 1.1 使用默认安装配置 1.1 .1 使用其它ds模型 1.2 使用自定义安装 2 附录:deepseek模型手动下载 3 脚本下载地址 deepseek一键部署脚本说明 0 必要前提 linux环境 python>3.10 1 使用方法 1.1 …...
【AI 语音】实时语音交互优化全解析:从 RTC 技术到双讲处理
网罗开发 (小红书、快手、视频号同名) 大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等…...
pytest-xdist 进行多进程并发测试
在自动化测试中,运行时间过长往往是令人头疼的问题。你是否遇到过执行 Pytest 测试用例时,整个测试流程缓慢得让人抓狂?别担心,pytest-xdist 正是解决这一问题的利器!它支持多进程并发执行,能够显著加快测试…...
【Android】版本和API对应关系表
目录 版本和API对应关系表 不积跬步,无以至千里;不积小流,无以成江海。要沉下心来,诗和远方的路费真的很贵! 版本和API对应关系表 版本名版本号名称APIAndroid 1616.0W36Android 1515.0V35Android 1414.0U34Android 1…...
通过acme生成与续签ssl证书,并部署到nginx
通过acme生成与续签ssl证书,并部署到nginx 介绍 官方介绍: acme.sh 实现了 acme 协议,可以从 ZeroSSL,Lets Encrypt 等 CA 生成免费的证书。 安装 acme.sh 1. curl方式 curl https://get.acme.sh | sh -s emailmyexample.com…...
mysql系统库介绍,数据字典(介绍,存储方式,常见表,访问权限),系统表(介绍,不同功能的表)
目录 mysql系统库 介绍 数据字典 介绍 不同版本下的存储方式 常见的数据字典表 访问权限 系统表 介绍 权限授予系统表 对象信息系统表 服务器端帮助系统表 时区系统表 mysql系统库 介绍 MySQL 默认创建 的特殊数据库,主要用于存储服务器运行时所需的信…...
spring 学习(工厂方式 实例化对象(静态工厂,实例化工厂,实现factorybean 规范))
目录 前言 第一种:静态工厂方式实例化对象 静态工厂的特点 demo(案例) 第二种:实例工厂的方式 实例工厂和静态工厂的区别 demo(案例) 第三种:实现FactoryBean规范的方式 demo(案例) 前言 spring 实…...
MarkupLM:用于视觉丰富文档理解的文本和标记语言预训练
摘要 结合文本、布局和图像的多模态预训练在视觉丰富文档理解(VRDU)领域取得了显著进展,尤其是对于固定布局文档(如扫描文档图像)。然而,仍然有大量的数字文档,其布局信息不是固定的࿰…...
讯飞智作 AI 配音技术浅析(三):自然语言处理
自然语言处理(NLP)是讯飞智作 AI 配音技术的重要组成部分,负责将输入的文本转换为机器可理解的格式,并提取出文本的语义和情感信息,以便生成自然、富有表现力的语音。 一、基本原理 讯飞智作 AI 配音的 NLP 技术主要包…...
kafka服务端之日志存储
文章目录 日志布局日志索引日志清理日志删除基于时间基千日志大小基于日志起始偏移量 日志压缩总结 日志布局 Ka饮a 中的消息是以主题为基本单位进行归类的, 各个主题在逻辑 上相互独立。 每个主题又可以分为一个或多个分区, 分区的数量可以在主题创建的…...
软件工程的熵减:AI如何降低系统复杂度
软件开发的世界,如同一个不断膨胀的宇宙。随着功能的增加和时间的推移,代码库越来越庞大,系统复杂度也随之水涨船高。代码膨胀、维护困难、开发效率低下等问题困扰着无数开发者。这不禁让人联想到物理学中的“熵增”原理——一个孤立系统的熵…...
模拟开发小鹅通首页网站练习
HTML代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>小鹅通-首页</title><!-- 引入页…...
Ubuntu 下 nginx-1.24.0 源码分析 - ngx_strerror 函数
声明 ngx_strerror 函数声明在 ngx_errno.h 中: u_char *ngx_strerror(ngx_err_t err, u_char *errstr, size_t size); 实现 在 ngx_errno.c 中: u_char * ngx_strerror(ngx_err_t err, u_char *errstr, size_t size) {size_t len;const char *ms…...
第26场蓝桥入门赛
5.扑克较量【算法赛】 - 蓝桥云课 C: #include <iostream> #include <algorithm> using namespace std;int a[100005];int main() {int n,k;cin>>n>>k;for (int i1; i<n; i)cin>>a[i], a[i] % k;sort(a1, a1n);int mx a[1]k-a…...
【CAPL实战】实现弹窗提示及操作
文章目录 前言1、TestWaitForTesterConfirmation函数2、测试举例 前言 在使用CANoe进行车载通信测试的过程中,可能因为一些条件限制,我们需要在测试执行的过程中去观察一些硬件显示或者调整相关硬件状态。比如测试过程中,需要手动去调整小电…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
OpenLayers 分屏对比(地图联动)
注:当前使用的是 ol 5.3.0 版本,天地图使用的key请到天地图官网申请,并替换为自己的key 地图分屏对比在WebGIS开发中是很常见的功能,和卷帘图层不一样的是,分屏对比是在各个地图中添加相同或者不同的图层进行对比查看。…...
基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...
R 语言科研绘图第 55 期 --- 网络图-聚类
在发表科研论文的过程中,科研绘图是必不可少的,一张好看的图形会是文章很大的加分项。 为了便于使用,本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中,获取方式: R 语言科研绘图模板 --- sciRplothttps://mp.…...
面试高频问题
文章目录 🚀 消息队列核心技术揭秘:从入门到秒杀面试官1️⃣ Kafka为何能"吞云吐雾"?性能背后的秘密1.1 顺序写入与零拷贝:性能的双引擎1.2 分区并行:数据的"八车道高速公路"1.3 页缓存与批量处理…...
