当前位置: 首页 > news >正文

oracle和达梦数据库的区别杂谈

这几天正在做数据库国产化的相关工作,之前的一个项目数据库用的是oracle的,现在要换成达梦的。所以我就把遇到的,需要修改的列出来,本篇文章持续更新中。

目录

1 达梦数据库中会出现多余的0占位

2 order by 排序的时候会把null空值排前面

3 is null,is not null与空字符不兼容

4 达梦数据库查询语句严格区分字符串尾部空格问题

5 oracle有自动收集统计信息的定时任务,而达梦需要自己去弄个定时任务

6 oracle和达梦date数据类型区别


1 达梦数据库中会出现多余的0占位

无论是oracle还是达梦数据库,都有number类型,格式都为number(m,n)。两个数据库中有相同的表,由于业务需求,我不能将原表的相关表的表结构晒出,现将测试表的结构展示如下:

CREATE TABLE CESHI (

ID VARCHAR2(50) DEFAULT SYS_GUID() NOT NULL,

NAME VARCHAR2(50) NULL,

ADDRESS VARCHAR2(50) NULL,

COLUMN1 VARCHAR2(70) NULL,

TOTAL NUMBER(15,3) NULL,

CONSTRAINT CESHI_PK PRIMARY KEY (ID)

);

达梦数据库的数据如下:

oracle数据库如下:

java端用的是springboot加mybatis,代码如下:

package boke.hbc.dingshiqi.ceshi; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; @RequestMapping("/ceshi") @RestController public class CeshiController { @Autowired private CeshiService service; @RequestMapping(value = "/dmandorcl") public JSONObject dmandorcl() { List<Map> list1=service.dmandorcl(); for(Map map1:list1) { System.out.println(map1.toString()); } JSONObject resultjson=new JSONObject(); resultjson.put("code", 0); return resultjson; } }

service:

package boke.hbc.dingshiqi.ceshi; import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.alibaba.fastjson.JSONObject; @Service public class CeshiService { @Autowired CeshiMapper mapper; public List<Map> dmandorcl() { // TODO Auto-generated method stub return mapper.dmandorcl(); } }

mapper

package boke.hbc.dingshiqi.ceshi; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Update; @Mapper public interface CeshiMapper { @Select("select * from ceshi") List<Map> dmandorcl(); }

在oracle数据库的情况下,控制台显示如下:

{TOTAL=777, ADDRESS=null, ID=22222, COLUMN1=null, NAME=null}
{TOTAL=444.745, ADDRESS=z, ID=2F172A78A876449F8B267927741774FB, COLUMN1=null, NAME=ssss}
{TOTAL=111, ADDRESS=ddd, ID=AB26EE87BFFF4ED7B4A666FBCAF357CC, COLUMN1=null, NAME=ssssf}

在dameng数据库环境下,控制台显示如下:

{TOTAL=22.000, ADDRESS=null, ID=22222, COLUMN1=null, NAME=null}
{TOTAL=344.000, ADDRESS=z, ID=2F172A78A876449F8B267927741774FB, COLUMN1=null, NAME=ssss}
{TOTAL=22.870, ADDRESS=ddd, ID=AB26EE87BFFF4ED7B4A666FBCAF357CC, COLUMN1=null, NAME=ssssf}

这种小数点后三个0的情况输入到前端页面显然是不合适的,所以我做了个拦截器,代码如下:

package com.bocomsoft.util; import java.math.BigDecimal; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.MappedJdbcTypes; import org.apache.ibatis.type.MappedTypes; @MappedJdbcTypes({JdbcType.NUMERIC,JdbcType.DECIMAL}) @MappedTypes(BigDecimal.class) public class BigDecimalTypeHandler extends BaseTypeHandler<String> { @Override public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { // TODO Auto-generated method stub System.out.println("i="+i+"@parameter="+parameter+"@jdbcType="+jdbcType.toString()); ps.setString(i, parameter); } @Override public String getNullableResult(ResultSet rs, String columnName) throws SQLException { // TODO Auto-generated method stub //System.out.println("哈哈1="+columnName); BigDecimal val = rs.getBigDecimal(columnName); if(val!=null) { String val2=val.toPlainString(); if (val2.indexOf(".") > 0) { // 去掉多余的0 val2 = val2.replaceAll("0+?$", ""); // 如果最后一位是. 则去掉 val2 = val2.replaceAll("[.]$", ""); } return val2; }else { return ""; } } @Override public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException { // TODO Auto-generated method stub //System.out.println("哈哈2"); BigDecimal val = rs.getBigDecimal(columnIndex); if(val!=null) { String val2=val.toPlainString(); if (val2.indexOf(".") > 0) { // 去掉多余的0 val2 = val2.replaceAll("0+?$", ""); // 如果最后一位是. 则去掉 val2 = val2.replaceAll("[.]$", ""); } return val2; }else { return ""; } } @Override public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException { // TODO Auto-generated method stub //System.out.println("哈哈3"); BigDecimal val = cs.getBigDecimal(columnIndex); if(val!=null) { String val2=val.toPlainString(); if (val2.indexOf(".") > 0) { // 去掉多余的0 val2 = val2.replaceAll("0+?$", ""); // 如果最后一位是. 则去掉 val2 = val2.replaceAll("[.]$", ""); } return val2; }else { return ""; } } }

这样输出的结果就不带有多余的0了

2 order by 排序的时候会把null空值排前面

在oracle中,select语句如果涉及到排序,默认的情况是把排序字段中为null的值排后,而达梦数据库正好相反,还是看那个ceshi表,两个数据库执行同样的sql语句:SELECT * FROM ceshi t ORDER BY t.ADDRESS,oracle的执行结果如下所示:

而达梦数据库则变成这个样子了:

如果要做数据库适配的话一定要注意。

3 is null,is not null与空字符不兼容

在oracle中,如果一个字段的值是空字符得话,他与null是等价的,我们可以用is null或is not null进行判断,但是达梦有可能是不一样,空字符和null不是等价的。主要与数据库设置有关,这个参数叫COMPATIBLE_MODE,具体参考链接如下所示:达梦数据库非空约束错误解决,明明插入空字符串,但还是触发非空约束_达梦数据库违反列非空约束-CSDN博客

4 达梦数据库查询语句严格区分字符串尾部空格问题

在oracle数据库中,是严格区分'a'和'a '的,但是在达梦数据库中是有可能不区分的,可数据库的BLANK_PAD_MODE参数,当BLANK_PAD_MODE=0时,除去group by 这种分组操作时严格区分外,其他比较、count等操作不严格区分'a'和'a ',认为这两个字符串是相等的。而且比较坑的是数据库实例已经建立的情况下,他是不能改的,除非重装数据库((╯‵□′)╯︵┴─┴ 掀桌),补救的措施是修改SPACE_COMPARE_MODE参数,然后重启服务器,右空格可以这么解决,左空格自求多福吧,我当时找的参考链接如下:

达梦数据库查询语句严格区分字符串尾部空格问题_达梦数据库空格填充模式-CSDN博客

5 oracle有自动收集统计信息的定时任务,而达梦需要自己去弄个定时任务

这个问题我当时是这么发现的,当时我们达梦上的测试库和正式库的数据量差不多,然后我就发现正式库查询特别慢,我就问达梦数据库的售后咋回事,他调了半天,说oracle默认的情况下有自动收集统计信息的定时任务,当高于一个阈值的时候,他会自动进行收集统计信息。达梦需要自己弄(后来我在网上看到说达梦也可以进行设定,但是我没时间,以后去验证一下吧),他就用sysdba用户加了个定时任务,里面执行的sql脚本为:CALL DBMS_STATS.GATHER_SCHEMA_STATS('大写的用户名',100,TRUE,'FOR ALL COLUMNS SIZE AUTO'),每两天执行一次,参考链接如下:

达梦数据库如何收集统计信息?_达梦收集统计信息-CSDN博客

6 oracle和达梦date数据类型区别

oracle和达梦都有date数据类型,但oracle是精确到秒,达梦只能精确到天,默认值都可以用sysdate,所以,如果达梦想要精确到秒,数据类型应该使用TIMESTAMP,在日期计算上,也是有区别的,总结如下:

在达梦数据库中,SYSDATE + 1表示‌当前系统时间往后推 1 天‌(即 24 小时)。

  • 运算单位‌:达梦日期运算以“天”为基本单位,整数1代表 1 天 。
  • 语法示例‌:SELECT SYSDATE + 1 FROM DUAL;返回明天的日期时间。
  • 其他精度‌:若需计算小时或分钟,需转换为天数,如加 5 小时写作SYSDATE + 5.0/24。‌‌
http://www.jsqmd.com/news/1120759/

相关文章:

  • DNS 劫持(DNS Spoofing)攻击手法 python脚本编写手法
  • Drogon框架API文档自动化测试实践:从OpenAPI契约到DrogonTest用例
  • PAT 乙级题目讲解:1013《数素数》
  • JetBrain系列应用配置
  • Instatic多环境部署:配置管理与环境变量使用
  • RESTMock实战案例:从0到1构建Android应用的Mock测试框架
  • 5步精通UI.Vision RPA:零基础掌握免费自动化工具
  • Python依赖注入高级技巧:上下文管理器与异步支持的完美结合
  • 3步构建高效离线OCR工作流:Umi-OCR实战指南
  • Python+Selenium自动化测试报告生成实战:从pytest-html到邮件发送
  • 【一个信号输入通过逻辑门能输出俩个信号一个沿上升沿一个下降沿】2024-12-31
  • JUC并发编程知识二(待完善)
  • 计算机毕业设计之基于大数据的传统文化数据采集与可视化分析
  • GTU的局放本底在现场测出来不太一样
  • Linux/WSL终端美化指南:gh_mirrors/do/dotfiles-archive的zsh与Hyper配置技巧
  • DevExpress WinForms中文教程:Grid View - 行高和布局基础知识
  • HsMod终极指南:解锁《炉石传说》55个隐藏功能的完整教程
  • Auto_PPT魔法背后:Markdown多步链式生成技术解析
  • 剑指offer hot100 第三周
  • 解决Windows版Redis无法远程连接的问题
  • 计算机毕业设计之基于安卓的高效机房管理系统设计与实现
  • 量子增强侧信道与迭代攻击:后量子密码(如McEliece)的混合威胁与防御实践
  • 模拟人工智能(Simulated Artificial Intelligence, SAI):一种工程化认知架构的理论范式
  • DevExpress WinForms中文教程:Grid View - 如何实现单元格合并?
  • 4-20mA电流环原理与工业自动化应用解析
  • Kali Linux实战:基于DVWA靶场深入解析一句话木马攻防原理
  • Selenium自动化测试:浏览器驱动路径管理的四种策略与最佳实践
  • AI时代开发者如何构建护城河:从工具崇拜到问题定义与流程重塑
  • 如何高效使用Mole AI清理工具:终极Mac系统优化指南
  • Elm-platform安装教程:Windows、macOS、Linux三大平台详细步骤