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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值