达梦 报错 数据类型不匹配

简介: 讲述DM数据库报错数据类型不匹配问题处理

问题产生

最近接触到达梦(DM)数据库,之前没有用过,因此对于DM数据库还处在摸索阶段。过去一直用的是Mysql数据库,今天在开发过程中用到了一个查询,查询语句很简单,查询语句如下

select*from sys_dict_data where is_valid =1and status =1and"sys_dict_data"."dict_type"='courseCategory'and to_char(dict_value)='1001';

在DM数据库管理工具执行sql可以正常执行,如图

image.png

但是sql放在Java代码中执行时却报错:第1 行附近出现错误: 数据类型不匹配;

### The error occurred while executing a query
### SQL: select * from sys_dict_data where is_valid = 1 and status = 1 and dict_type=? and dict_value= ?
### Cause: dm.jdbc.driver.DMException: 第1 行附近出现错误:
数据类型不匹配
; 第1 行附近出现错误:
数据类型不匹配; nested exception is dm.jdbc.driver.DMException: 第1 行附近出现错误:
数据类型不匹配
  at org.springframework.jdbc.support.SQLStateSQLExceptionTranslator.doTranslate(SQLStateSQLExceptionTranslator.java:104)
  at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
  at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
  at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:81)
  at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:73)
  at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:446)
  at com.sun.proxy.$Proxy102.selectOne(Unknown Source)
  at org.mybatis.spring.SqlSessionTemplate.selectOne(SqlSessionTemplate.java:166)

那么这是为什么呢?

问题分析

首先这个sql本身很简单,就是传入两个参数进行数据查询,在DM管理工具执行也没有问题,可以正常查询,只是在Java代码中查询时报错。为了快速的定位问题,去网上百度了一下同样遭遇的小伙伴,看到可能是DM数据库的text类型字段不支持比较导致的,于是查看了一下表结构

image.png

看到查询条件中涉及到的字段确实是text类型,那么为什么DM管理工具执行却没有报错呢?是因为DM管理工具将text类型字段转换成了varchar类型所以没有报错

image.png

而Java代码中编译sql的时候就已经报错了

image.png

image.png

如果将Java中打印的有占位符的sql放在DM管理工具执行的话也是会复现错误的

image.png

问题处理

到这里也就知道问题所在了,那么如何处理呢?

方案1:

首先可以考虑根据实际情况设计字段,对于字典表设计text类型的字段,完全可以改为varchar(1024)就够用了,设计text类型浪费存储空间还影响数据库性能,那么既然已经如此设计了,不能改表结构只能通过其他方案折中。

方案2:

like

尝试like关键字查询,改写sql

select*from sys_dict_data where is_valid =1and status =1and"sys_dict_data"."dict_type"='courseCategory'and dict_value like'1001';

可以正常查询,但是

达梦数据库对大字段文本的like比较是有限制的,受参数CLOB_LIKE_MAX_LEN的影响,默认值10240KB,最大上限是102400KB。
如果遇到超过10MB的文本内容,请及时调整参数值,并且它需要重启数据库生效。
正因为只支持100MB的文本内容,超过100MB,就应该换用其他方法解决,即不再适合。

DM数据库CLOB_LIKE_MAX_LEN参数的查询可以通过以下sql语句查询

select*from v$parameter where NAME='CLOB_LIKE_MAX_LEN';

查询结果如图

image.png

或者通过sql查询

select*from v$dm_ini where PARA_NAME='CLOB_LIKE_MAX_LEN';

image.png

执行方案1的sql查看执行计划,发现也经历了类型转换

image.png

TO_CHAR(str)

可以使用TO_CHAR(str)函数将 VARCHAR、CLOB、TEXT 类型的数据转化为 VARCHAR 类型输出。VARCHAR 类型的长度不能超过 32767 个字节,CLOB、TEXT 类型的长度不能超过 32766 个字节。查询语句如下

select*from sys_dict_data where is_valid =1and status =1and"sys_dict_data"."dict_type"='courseCategory'and to_char(dict_value)=?;

to_char转化之后传入?占位符,不会直接报错,而是提示输入参数

image.png

CAST(value AS type)

或者也可以使用CAST(value AS type)将参数 value 转换为 type 类型返回。类型之间转换的相容性如下表所示:表中,“允许”表示这种语法有效且不受限制,“-”表示语法无效,“受限”表示转换还受到具体参数值的影响。

数值类型为:精确数值类型和近似数值类型。

精确数值类型为:NUMERIC、DECIMAL、BYTE、INTEGER、SMALLINT。

近似数值类型为:FLOAT、REAL、DOUBLE PRECISION。

字符串为:变长字符串、固定字符串和 ROWID 类型。其中 ROWID 类型只能和字符串中的 VARCHAR(或 VARCHAR2)相互转换。

变长字符串为:VARCHAR、VARCHAR2。

固定字符串为:CHAR、CHARACTER。

ROWID 类型:ROWID。

字符串大对象为:CLOB、TEXT。

二进制为:BINARY、VARBINARY。

二进制大对象为:BLOB、IMAGE。

判断类型为:BIT、BOOLEAN。

日期为:DATE。时间为:TIME。时间戳为:TIMESTAMP。

时间时区为:TIME WITH TIME ZONE。

时间戳时区为:TIMESTAMP WITH TIME ZONE。

年月时间间隔为:INTERVAL YEAR TO MONTH、INTERVAL YEAR、INTERVAL MONTH。

日时时间间隔为:INTERVAL DAY、INTERVAL DAY TO HOUR、INTERVAL DAY TO MINUTE、INTERVAL DAY TO SECOND、INTERVAL HOUR、INTERVAL HOUR TO MINUTE、INTERVAL HOUR TO SECOND、INTERVAL MINUTE、INTERVAL MINUTE TO SECOND、INTERVAL SECOND。

如图

image.png

cast语句示例

select*from sys_dict_data where is_valid =1and status =1and"sys_dict_data"."dict_type"='courseCategory'and cast(dict_value asVARCHAR)=?;

执行效果如图,不会直接报错,而是提示输入参数

image.png

CONVERT(type,value)

使用CONVERT(type,value)函数,用于当 INI 参数 ENABLE_CS_CVT=0 时,将参数 value 转换为 type 类型返回。其类型转换相容矩阵与函数 CAST()的相同,查询语句sql

select*from sys_dict_data where is_valid =1and status =1and"sys_dict_data"."dict_type"='courseCategory'and convert(varchar,dict_value)=?;

执行结果如图,提示输入参数

image.png

DBMS_LOB 包

兼容 ORACLE 的 DBMS_LOB 包,用于对大对象(BLOB、CLOB)进行操作所提供的一系列方法的集合。

SUBSTR

获取指定偏移开始的指定长度的子串

语法如下

FUNCTION SUBSTR(  LOB_LOC   INBLOB,  AMOUNT    ININTEGER:=32767,  OFFSET    ININTEGER:=1) RETURN VARBINARY;FUNCTION SUBSTR(  LOB_LOC   IN  CLOB,  AMOUNT    ININTEGER:=32767,  OFFSET    ININTEGER:=1) RETURN VARCHAR2;FUNCTION SUBSTR(  FILE_LOC  IN  BFILE,  AMOUNT    ININTEGER:=32767,  OFFSET    INBIGINT:=1) RETURN VARBINARY;

参数详解

LOB_LOC :临时大对象。
FILE_LOC:BFILE 对象。
AMOUNT:读取的数据长度,BLOB 为字节,CLOB 为字符,上限为 32767,实际获取为大对象长度与 AMOUNT 的小值。
OFFSET:读取数据的起始偏移。
返回值:返回指定偏移开始的指定长度的子串。若输入的 AMOUNT 或 OFFSET 参数非法,返回 NULL。

sql语句如下

select*from sys_dict_data where is_valid =1and status =1and"sys_dict_data"."dict_type"='courseCategory'and dbms_lob.substr(dict_value)=?;

执行结果如图,没有直接报错,输入参数即可

image.png

TEXT_EQUAL(n1,n2)

返回 n1,n2 的比较结果,完全相等,返回 1;否则返回 0。n1,n2 的类型为 CLOB、TEXT 或 LONGVARCHAR。如果 n1 或 n2 均为空串或 NULL,结果返回为 1;否则只有一个为空串或为 NULL,结果返回 0。不忽略结果空格和英文字母大小写。sql示例代码

select*from sys_dict_data where is_valid =1and status =1and"sys_dict_data"."dict_type"='courseCategory'and TEXT_EQUAL(dict_value,?);

执行结果如图,指定参数即可查询成功

image.png

这个函数的字节数满足条件。

最后

到这里,关于DM数据库查询条件中涉及到text类型字段传参查询时报错的问题也就算处理完了,前面几种解决方案长度不能超过 32767 个字节,如果您的字段确实需要text类型的话可以尝试最后一种,TEXT_EQUAL函数支持text最大长度。

相关文章
|
6月前
|
SQL 存储 关系型数据库
MySQL 中将使用逗号分隔的字段转换为多行数据
在开发中,遇到逗号分隔字段的处理是常见问题。本文通过一个实际场景展示了如何改造数据存储:从单一字段存储多个页面(如`page1,page2,page3`)到使用新表`bus_pages`存储每个页面的详细配置。使用`SUBSTRING_INDEX`函数配合`help_topic`表(具有连续ID)拆分`bus_mark_info`表中的`pages`字段,按`help_topic_id`截取页面名称并插入新表。当`pages`字段超过701个页面时,需寻找其他辅助表。最终,数据成功迁移到新结构中,便于单独配置每个页面。
192 1
|
关系型数据库 PostgreSQL
PostgreSQL 判断字符串包含
PostgreSQL 判断字符串包含
180 0
|
存储 SQL Oracle
对比下不同RDBMS数据库中对字符数据类型处理的差异 - 为什么我们要尽量避免使用CHAR数据类型?
对比下不同RDBMS数据库中对字符数据类型处理的差异 - 为什么我们要尽量避免使用CHAR数据类型?
|
数据库
数据库——将多个逗号转成一个逗号
数据库——将多个逗号转成一个逗号
|
Oracle 关系型数据库 MySQL
数据库中判断是否包含字符串函数的使用
数据库中判断是否包含字符串函数的使用
440 0
数据库中判断是否包含字符串函数的使用
|
数据库
字符串转换成数据库in语句的形式(五)
字符串转换成数据库in语句的形式(五)
369 0
|
SQL 数据库
SQL语句大小写是否区分的问题,批量修改整个数据库所有表所有字段大小写
一、实例介绍 SQL语句大小写到底是否区分呢?我们先从下面的这个例子来看一下: 例: --> 创建表,插入数据: declare @maco table (number int,myvalue varchar(2)) insert into @maco select 1,'aa' ...
1433 0
|
存储 SQL 关系型数据库
PostgreSQL 10.1 手册_部分 II. SQL 语言_第 8 章 数据类型_8.3. 字符类型
8.3. 字符类型 表 8.4. 字符类型 名字 描述 character varying(n), varchar(n) 有限制的变长 character(n), char(n) 定长,空格填充 text 无限变长 表 8.4显示了在PostgreSQL里可用的一般用途的字符类型。
1287 0
|
SQL 存储 关系型数据库
PostgreSQL 10.1 手册_部分 II. SQL 语言_第 8 章 数据类型_8.1. 数字类型
8.1. 数字类型 8.1.1. 整数类型 8.1.2. 任意精度数字 8.1.3. 浮点类型 8.1.4. 序数类型 数字类型由2、4或8字节的整数以及4或8字节的浮点数和可选精度小数组成。
1360 0
|
SQL 关系型数据库 PostgreSQL
PostgreSQL 10.1 手册_部分 II. SQL 语言_第 8 章 数据类型_8.11. 文本搜索类型
8.11. 文本搜索类型 8.11.1. tsvector 8.11.2. tsquery PostgreSQL提供两种数据类型,它们被设计用来支持全文搜索,全文搜索是一种在自然语言的文档集合中搜索以定位那些最匹配一个查询的文档的活动。
1460 0