【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不一致, …...
安全知识之网络扫描器概念与相关技术
网络安全扫描器简介 迅速发展的Internet给人们的生活、工作带来了巨大的方便,但同时,也带来了一些不容忽视的问题,网络信息的安全保密问题就是其中之一。 网络的开放性以及黑客的攻击是造成网络不安全的主要原因。科学家在设计Internet之初就…...
Vim跳转文件及文件行结束符EOL
跳转文件 gf 从当前窗口打开那个文件的内容,操作方式:让光标停在文件名上,输入gf。 Ctrlo 从打开的文件返回之前的窗口 Ctrlwf 可以在分割的窗口打开跳转的文件,不过在我的实验不是次次都成功。 统一行尾格式 文本文件里存放的…...
Termux安装ssh实现电脑ssh
Termux下载 点击下载 在 Termux 中安装并使用 SSH,按照以下步骤操作: 1. 更新软件包列表 pkg update && pkg upgrade2. 安装 OpenSSH pkg install openssh3. 设置 SSH 密码(必须,否则无法使用 SSH 服务器)…...
DeepSeek大模型介绍、本地化部署与使用!【AI大模型】
一、DeepSeek 是什么? 1.技术定位 专注大模型与AGI研究,开发高性能基座模型(如 DeepSeek LLM 系列),支持长文本、多模态、代码生成等复杂任务。 提供开源模型(如 DeepSeek-MoE、DeepSeek-V2)…...
Axios 的原理
🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…...
Gitlab中如何进行仓库迁移
需求:之前有一个自己维护的新仓库A,现在需要将这个仓库提交并覆盖另一个旧的仓库B,需要保留A中所有的commit信息。 1.方法一:将原有仓库A导出后再导入到新的仓库B中 适用场景:新的仓库B是一个待建仓库,相当…...
Android的MQTT客户端实现
在 Android 平台上实现 MQTT 客户端的完整技术方案,涵盖基础实现、安全连接、性能优化和最佳实践: 一、技术选型与依赖配置 推荐库 Eclipse Paho Android Service(官方维护,支持后台运行) gradle 复制 // build.gradl…...
Centos挂载镜像制作本地yum源,并补装图形界面
内网环境centos7.9安装图形页面内网环境制作本地yum源 上传镜像到服务器目录 创建目录并挂载镜像 #创建目录 cd /mnt/ mkdir iso#挂载 mount -o loop ./CentOS-7-x86_64-DVD-2009.iso ./iso #前面镜像所在目录,后面所挂载得目录#检查 [rootlocalhost mnt]# df -h…...
Thread类以及常见方法
Thread类是JVM用来管理线程的一个类,每个线程都有一个唯一的Thread对象与之关联。 多一个线程,就多一条执行流,每个执行流也要一个对象来描述,而Thread类的对象就是用来描述一个线程的执行流,JVM 会将这些 Thread 对象…...
【蓝桥杯—单片机】第十一届省赛真题代码题解题笔记 | 省赛 | 真题 | 代码题 | 刷题 | 笔记
第十一届省赛真题代码部分 前言赛题代码思路笔记竞赛板配置内部振荡器频率设定键盘工作模式跳线扩展方式跳线 建立模板明确设计要求和初始状态显示功能部分数据界面第一部分第二部分第三部分调试时发现的问题 参数设置界面第一部分第二部分和第四部分第三部分和第五部分 按键功…...
【原创】Android Studio Ladybug 中Gradle配置
使用Android Studio创建项目后,由于需要下载的一下文件在国外,加上网速的问题,以及防火墙的问题,不少文件难以下载。常常导致项目创建后,要等很长时间,各种折腾,结果一个demo都跑不起来。 经过…...
CLion2024.3.2版中引入vector头文件报错
报错如下: 在MacBook端的CLion中引入#include <vector>报 vector file not found(引入map、set等也看参考此方案),首先可以在Settings -> Build,Execution,Deployment -> Toolchains中修改C compiler和C compiler的路…...
自动化测试工具:selenium
🍅 点击文末小卡片 ,免费获取软件测试全套资料,资料在手,涨薪更快 Selenium是一个用于Web应用程序测试的工具。是一个开源的Web的自动化测试工具,最初是为网站自动化测试而开发的,类型像我们玩游戏用的按键…...
MR30分布式IO模块:驱动智能制造工厂的工业互联与高效控制新范式
在工业4.0与智能制造浪潮的推动下,传统制造业正经历着从“机械驱动”向“数据驱动”的深刻转型。作为工业数据连接领域的领军者,明达技术凭借其自主研发的MR30分布式IO模块,以创新的技术架构与卓越的性能表现,为全球制造企业构建了…...
计算机领域QPM、TPM分别是什么并发指标,还有其他类似指标吗?
在计算机领域,QPM和TPM是两种不同的并发指标,它们分别用于衡量系统处理请求的能力和吞吐量。 QPM(每分钟请求数) QPM(Query Per Minute)表示每分钟系统能够处理的请求数量。它通常用于衡量系统在单位时间…...
Python截图轻量化工具
这是用Python做到截图工具,不过由于使用了ctypes调用了Windows的API, 同时访问了Windows中"C:/Windows/Cursors/"中的.cur光标样式文件, 这个工具只适用于Windows环境; 如果要提升其跨平台性的话,需要考虑替换ctypes的一些专属于W…...
Python----Python高级(并发编程:协程Coroutines,事件循环,Task对象,协程间通信,协程同步,将协程分布到线程池/进程池中)
一、协程 1.1、协程 协程,Coroutines,也叫作纤程(Fiber) 协程,全称是“协同程序”,用来实现任务协作。是一种在线程中,比线程更加轻量级的存在,由程序员自己写程序来管理。 当出现IO阻塞时,…...
DeepSeek使用技巧大全(含本地部署教程)
在人工智能技术日新月异的今天,DeepSeek 作为一款极具创新性和实用性的 AI,在众多同类产品中崭露头角,凭借其卓越的性能和丰富的功能,吸引了大量用户的关注。 DeepSeek 是一款由国内顶尖团队研发的人工智能,它基于先进…...
.NET Core 8 Blazor 和 Vue 3 技术构建网
以下是一个可行的解决方案,能够满足使用 .NET Core 8 Blazor 和 Vue 3 技术构建网站,并且将前后端代码放在一个站点中,实现一次发布部署的目标。 解决方案概述 技术栈选择: 后端:.NET Core 8 Blazor Server 或 Blazor …...
ElasticSearch集群因索引关闭重打开导致飘红问题排查
背景 某组件向 ElasticSearch 写入数据,从最近某一天开始写入速度变慢,数据一直有积压。推测是 ElasticSearch 集群压力导致的,查看 ElasticSearch 集群状态,发现集群确实处于 red 状态。 本文记录 ElasticSearch 集群因索引关闭…...
计算机毕业设计Tensorflow+LSTM空气质量监测及预测系统 天气预测系统 Spark Hadoop 深度学习 机器学习 人工智能
温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:文末有 CSDN 平台官方提供的学长联系方式的名片! 作者简介:Java领…...
手搓基于CNN的Chest X-ray图像分类
数据集Chest X-ray PD Dataset 数据集介绍 - 知乎https://zhuanlan.zhihu.com/p/661311561 CPU版本 import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import Dataset, DataLoader from torchvision import transforms, models import …...
使用java代码操作rabbitMQ收发消息
SpringAMQP 将来我们开发业务功能的时候,肯定不会在控制台收发消息,而是应该基于编程的方式。由于RabbitMQ采用了AMQP协议,因此它具备跨语言的特性。任何语言只要遵循AMQP协议收发消息,都可以与RabbitMQ交互。并且RabbitMQ官方也…...
【数据结构】(7) 栈和队列
一、栈 Stack 1、什么是栈 栈是一种特殊的线性表,它只能在固定的一端(栈顶)进行出栈、压栈操作,具有后进先出的特点。 2、栈概念的例题 答案为 C,以C为例进行讲解: 第一个出栈的是3,那么 1、…...
【Pytorch实战教程】让数据飞轮转起来:PyTorch Dataset与Dataloader深度指南
文章目录 让数据飞轮转起来:PyTorch Dataset与Dataloader深度指南一、为什么需要数据管理组件?二、Dataset:数据集的编程接口2.1 自定义Dataset三要素2.2 实战案例:图像分类数据集三、Dataloader:高效数据流水线3.1 核心参数解析3.2 数据流可视化3.3 多卡训练支持四、综合…...
Python的秘密基地--[章节13] Python 数据分析与可视化
第13章:Python 数据分析与可视化 在大数据时代,数据分析与可视化是至关重要的技能。Python 提供了多个强大的库,如 NumPy、Pandas、Matplotlib 和 Seaborn,用于数据处理、分析和可视化。本章将介绍如何使用 Python 进行数据分析&…...
Python 入门:文件操作、读写、管理
目录 1. 引言 2. 文件基础操作 2.1 打开文件(open()) 2.2 读取文件内容 2.3 写入文件 3. 处理 CSV 文件 3.1 读取 CSV 文件 3.2 写入 CSV 文件 4. 处理 JSON 文件 4.1 读取 JSON 文件 4.2 写入 JSON 文件 5. 文件管理操作 5.1 删除文件 5.…...
Composo:企业级AI应用的质量守门员
在当今快速发展的科技世界中,人工智能(AI)的应用已渗透到各行各业。然而,随着AI技术的普及,如何确保其可靠性和一致性成为了企业面临的一大挑战。Composo作为一家致力于为企业提供精准AI评估服务的初创公司,通过无代码和API双模式,帮助企业监测大型语言模型(LLM)驱动的…...
crictl和ctr命令详解
一,crictl crictl 是 CRI 兼容的容器运行时命令行接口。 你可以使用它来检查和调试 Kubernetes 节点上的容器运行时和应用程序。 crictl 和它的源代码在 cri-tools 代码库。 1,安装 需要下载与kubernetes相对应的版本,我的k8s版本是1.30的…...
