首批通过分布式安全可靠测评,为关键业务系统打造
数据类型转换规则
更新时间:2025-01-17 14:57:56
通常,表达式不能包含不同数据类型的值,为了使表达式之间可以进行计算,OceanBase 数据库支持从一个数据类型到另一个数据类型的值的隐式转换和显式转换。本文主要介绍数据类型的隐式和显式转换规则。
注意
OceanBase 数据库建议您指定显式转换,而不是依赖隐式或自动转换。
隐式数据类型转换
当数据类型转换有意义时,OceanBase 数据库会自动将一个值从一种数据类型转换为另一种数据类型。
隐式数据类型的转换规则如下:
执行
INSERT和UPDATE操作时,OceanBase 数据库把变量值转换成受影响列的类型。执行
SELECT FROM操作时,OceanBase 数据库把列的数据类型转换成目标变量的类型。当字符值和数值进行比较时,OceanBase 数据库把字符值转换成数值。
在处理数值时,OceanBase 数据库会调整精度和小数位数。由此产生的数值数据类型与基础表中找到的数值数据类型不同。
字符值或 NUMBER 值与浮点数值之间的转换可以是不精确的,因为字符类型和 NUMBER 值类型使用十进制精度来表示数值,而浮点数使用二进制精度。
当一个
CLOB值转换为一个字符类型(例如VARCHAR2),或着BLOB转换为RAW数据时。如果要转换的数据大于目标数据类型,那么数据库会返回错误信息。在从时间戳值转换为
DATE值的过程中,时间戳值的小数秒部分被截断,并且对时间戳值的小数秒部分进行四舍五入。从
BINARY_FLOAT转换为BINARY_DOUBLE是精确的。如果
BINARY_DOUBLE的精度位数超出了BINARY_FLOAT支持的精度位数,则将BINARY_DOUBLE转换为BINARY_FLOAT是不精确的。当将字符值与
DATE值进行比较时,OceanBase 数据库将字符数据转换为DATE类型。进行赋值操作时,OceanBase 数据库把等号右边的值转换成左边赋值目标的数据类型。
进行连接操作时,OceanBase 数据库把非字符类型转换成字符类型或国家字符类型。
数据类型隐式转换矩阵
下表为所有数据类型的隐式转换矩阵,不需要考虑转换的方向或转换的上下文。
说明
"-"表示不支持转换。
| 数据类型 | CHAR | VARCHAR2 | NCHAR | NVARCHAR2 | DATE | DATETIME / INTERVAL | NUMBER | BINARY_FLOAT | BINARY_DOUBLE | RAW | CLOB | BLOB |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| CHAR | - | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
| VARCHAR2 | Yes | - | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | - |
| NCHAR | Yes | Yes | - | Yes | Yes | Yes | Yes | Yes | Yes | Yes | Yes | - |
| NVARCHAR2 | Yes | Yes | Yes | - | Yes | Yes | Yes | Yes | Yes | Yes | Yes | - |
| DATE | Yes | Yes | Yes | Yes | - | - | - | - | - | - | - | - |
| DATETIME / INTERVAL | Yes | Yes | Yes | Yes | - | - | - | - | - | - | - | - |
| NUMBER | Yes | Yes | Yes | Yes | - | - | - | Yes | Yes | - | - | - |
| BINARY_FLOAT | Yes | Yes | Yes | Yes | - | - | Yes | - | Yes | - | - | - |
| BINARY_DOUBLE | Yes | Yes | Yes | Yes | - | - | Yes | Yes | - | - | - | - |
| RAW | Yes | Yes | Yes | Yes | - | Yes 1 | - | - | - | - | Yes | - |
| CLOB | Yes | Yes | Yes | Yes | - | - | - | - | - | - | - | Yes |
| BLOB | - | - | - | - | - | - | - | - | - | Yes | - | - |
1 您不能直接将 RAW 转换为 INTERVAL,但是可以使用 UTL_RAW.CAST_TO_VARCHAR2([RAW]) 将 RAW 转换为 VARCHAR2,然后将所得的 VARCHAR2 值转换为 INTERVAL。
不同字符类型之间的隐式转换
下表为不同字符类型之间隐式转换的方式。
说明
"-"表示不支持转换。
| 数据类型 | to CHAR | to VARCHAR2 | to NCHAR | to NVARCHAR2 |
|---|---|---|---|---|
| from CHAR | - | VARCHAR2 | NCHAR | NVARCHAR2 |
| from VARCHAR2 | VARCHAR2 | - | NVARCHAR2 | NVARCHAR2 |
| from NCHAR | NCHAR | NCHAR | - | NCHAR2 |
| from NVARCHAR2 | NVARCHAR2 | NVARCHAR2 | NVARCHAR2 | - |
隐式数据类型转换示例
执行如下示例语句时,OceanBase 使用了隐式数据类型转换,将
'james'转换为数字类型,但是转换失败,并收到报错。obclient> SELECT 5 * 10 + 'james' FROM DUAL; OBE-01722: invalid number将字符串
'2'从CHAR数据类型隐式转换为了数值数据类型 2,计算结果为 52。obclient> SELECT 5 * 10 + '2' FROM DUAL; +----------+ | 5*10+'2' | +----------+ | 52 | +----------+ 1 row in set
显式数据类型转换
您可以使用 SQL 转换函数来转换数据类型,SQL 函数显式转换一个数据类型为另一个数据类型。
显式类型转换矩阵
| 数据类型 | to CHAR、VARCHAR2、NCHAR、NVARCHAR2 | to NUMBER | to DATETIME/INTERVAL | to RAW | to CLOB | to BLOB | to BINARY_FLOAT | to BINARY_DOUBLE |
|---|---|---|---|---|---|---|---|---|
| from CHAR、VARCHAR2、NCHAR、NVARCHAR2 | TO_CHAR(char . ) 、TO_NCHAR(char . ) | TO_NUMBER | TO_DATE、TO_TIMESTAMP、TO_TIMESTAMP_TZ、TO_YMINTERVAL、TO_DSINTERVAL | HEXTORAW | TO_CLOB | TO_CLOB | TO_BINARY_FLOAT | TO_BINARY_DOUBLE |
| from NUMBER | TO_CHAR(number) 、TO_NCHAR(number) | - | TO_DATE、NUMTOYM_INTERVAL、NUMTOOLS_INTERVAL | - | - | - | TO_BINARY_FLOAT | TO_BINARY_DOUBLE |
| from Datetime/Interval | TO_CHAR(date ) 、TO_NCHAR(date) | - | - | - | - | - | - | - |
| from RAW | RAWTOHEX、RAWTONHEX | - | - | - | TO_BLOB | TO_BLOB | - | - |
| from CLOB | TO_CHAR、TO_NCHAR | - | - | - | TO_CLOB | - | - | - |
| from BLOB | TO_CHAR、TO_NCHAR | - | - | - | - | TO_BLOB | - | - |
| from BINARY_FLOAT | TO_CHAR(char . ) 、TO_NCHAR(char . ) | TO_NUMBER | - | - | - | - | TO_BINARY_FLOAT | TO_BINARY_DOUBLE |
| from BINARY_DOUBLE | TO_CHAR(char . ) 、TO_NCHAR(char . ) | TO_NUMBER | - | - | - | - | TO_BINARY_FLOAT | TO_BINARY_DOUBLE |
显式数据类型转换示例
当前的时间通过 TO_CHAR 函数显式转换为指定的格式输出。
obclient> SELECT TO_CHAR(SYSDATE, 'YYYY_MM_DD') FROM DUAL;
+-------------------------------+
| TO_CHAR(SYSDATE,'YYYY_MM_DD') |
+-------------------------------+
| 2021_11_30 |
+-------------------------------+
1 row in set