#算术运算符

YashanDB提供如下算术运算符:

运算符 操作数 含义 NULL参与运算
+ 一元/二元 一元表示正数,二元表示加法 结果为NULL
- 一元/二元 一元表示负数,二元表示减法 结果为NULL
* 二元 乘法 结果为NULL
/ 二元 普通除法 结果为NULL
% 二元 整数除法,返回余数 结果为NULL

# 除法

YashanDB中,可实现除法运算的方式有:

  • 算术运算符:/、%
  • 内置函数:MODDIV

%

取模运算,与MOD函数同义。

格式为:n2 % n1

含义为:将n2 整除n1后剩余的数值作为取模的结果,即余数,余数的正负符号与n2一致。

若n1为0,不报错,而是直接将n2的值作为余数结果返回。

/

普通除法运算。

/与DIV的关系:

  • 对于小数(FLOAT/DOUBLE/NUMBER),/与DIV算法一致。
  • 对于整数,/作普通除法运算,DIV作整除运算并返回商数。

一般情况下,在/或DIV运算里0不能作为除数,否则报错,但是在被除数是浮点数的情况下,不报错而是做如下特殊处理:

  • 如果被除数是Nan,计算结果为Nan
  • 如果被除数是正浮点数或Inf,计算结果为Inf
  • 如果被除数是负浮点数或-Inf,计算结果为-Inf

# 运算优先级

从高到低的运算优先级为:+(取正)、-(取负)>*、/、%>+、-。同一优先级运算符从左向右执行。

可以使用双括号()来调整想达到的运算优先级。

# 数据类型

如下数据类型可能会参与到算术运算中:

  • 数值型(除BIT外)

  • 字符型

  • 日期时间型

# 类型转换

在进行二元算术运算时,YashanDB将通过隐式数据转换,将参与运算的数据类型统一到某个数据类型,统一原则为:

  • 数值型加、减、乘法最小提升规则:按TINYINT->SMALLINT->INT->BIGINT->NUMBER->FLOAT->DOUBLE顺序向后统一。
  • 数值型除法最小提升规则:按TINYINT/SMALLINT/INT/BIGINT->NUMBER->FLOAT->DOUBLE顺序向后统一。
  • 字符型数据与数值型数据进行运算时,将会向数值型统一。
  • 数值型、字符型数据与日期时间型数据进行运算时,将会向日期时间型统一。

# (1)整型数值之间统一规则

行列标题格为参与算术运算的数据类型;内容单元格为统一后的数据类型;–表示不支持两种数据类型参与算术运算。

数据类型 运算符or函数 TINYINT SMALLINT INT BIGINT*
TINYINT +、-、* SMALLINT INT BIGINT BIGINT/NUMBER
/ NUMBER NUMBER NUMBER NUMBER
%、MOD、DIV SMALLINT INT BIGINT BIGINT/NUMBER
SMALLINT +、-、* INT INT BIGINT BIGINT/NUMBER
/ NUMBER NUMBER NUMBER NUMBER
%、MOD、DIV INT INT BIGINT BIGINT/NUMBER
INT +、-、* BIGINT BIGINT BIGINT BIGINT/NUMBER
/ NUMBER NUMBER NUMBER NUMBER
%、MOD、DIV BIGINT BIGINT BIGINT BIGINT/NUMBER
BIGINT* +、-、* BIGINT/NUMBER BIGINT/NUMBER BIGINT/NUMBER BIGINT/NUMBER
/ NUMBER NUMBER NUMBER NUMBER
%、MOD、DIV BIGINT/NUMBER BIGINT/NUMBER BIGINT/NUMBER BIGINT/NUMBER

Note

BIGINT类型与所有整数类型参与+、-、*、%、MOD、DIV算术运算,或者对BIGINT类型作取负(-)运算时:

运算结果转换为BIGINT或NUMBER由系统内部决定,YashanDB默认统一转换为BIGINT,如因业务需要转换为NUMBER,请联系我们的技术支持处理。

# (2)整型数值与其他数值之间统一规则

行列标题格为参与算术运算的数据类型;内容单元格为统一后的数据类型,其中(1)表示采用上面(1)整型数值之间统一规则;–表示不支持两种数据类型参与算术运算。

数据类型 运算符or函数 整型数值 NUMBER FLOAT DOUBLE
整型数值 +、-、* (1) NUMEBR FLOAT DOUBLE
/ (1) NUMEBR FLOAT DOUBLE
%、MOD、DIV (1) NUMEBR FLOAT DOUBLE
NUMBER +、-、* NUMEBR NUMBER FLOAT DOUBLE
/ NUMEBR NUMEBR FLOAT DOUBLE
%、MOD、DIV NUMEBR NUMEBR FLOAT DOUBLE
FLOAT +、-、* FLOAT FLOAT FLOAT DOUBLE
/ FLOAT FLOAT FLOAT DOUBLE
%、MOD、DIV FLOAT FLOAT FLOAT DOUBLE
DOUBLE +、-、* DOUBLE DOUBLE DOUBLE DOUBLE
/ DOUBLE DOUBLE DOUBLE DOUBLE
%、MOD、DIV DOUBLE DOUBLE DOUBLE DOUBLE

# (3)数值型与字符型统一规则

行列标题格为参与算术运算的数据类型;内容单元格为统一后的数据类型,其中(2)表示采用上面(2)整型数值与其他数值之间统一规则;–表示不支持两种数据类型参与算术运算。

数据类型 运算符or函数 整型数值 NUMBER FLOAT DOUBLE 字符型
整型数值 +、-、*、/、%、MOD、DIV (2) (2) (2) (2) NUMEBR
NUMBER +、-、*、/、%、MOD、DIV (2) (2) (2) (2) NUMBER
FLOAT +、-、*、/、%、MOD、DIV (2) (2) (2) (2) FLOAT
DOUBLE +、-、*、/、%、MOD、DIV (2) (2) (2) (2) DOUBLE
字符型 +、-、*、/、%、MOD、DIV NUMBER NUMEBR FLOAT DOUBLE NUMEBR

# (4)数值型、字符型与日期时间型统一规则

行列标题格为参与算术运算的数据类型;内容单元格为统一后的数据类型,其中(3)表示采用上面(3)数值型与字符型统一规则;–表示不支持两种数据类型参与算术运算;YM表示INTERVAL YEAR TO MONTH,DS表示INTERVAL DAY TO SECOND,TS表示TIMESTAMP。

数据类型 运算符 数值型 字符型 TIME DATE TS YM DS
数值型 + (3) (3) -- DATE DATE -- --
- (3) (3) -- -- -- -- --
* (3) (3) -- -- -- YM DS
/ (3) (3) -- -- -- -- --
字符型 +、- (3) (3) -- DATE DATE -- --
*、/ (3) (3) -- -- -- YM DS
TIME + -- -- -- TS TS -- TIME
- -- -- DS -- -- -- TIME
DATE + DATE DATE TS -- -- DATE DATE
- DATE DATE TS NUMBER DS DATE DATE
TS + DATE DATE TS -- -- TS TS
- DATE DATE TS DS DS TS TS
YM + -- -- -- DATE TS YM --
- -- -- -- -- -- YM --
* YM YM -- -- -- --
/ YM YM -- -- -- --
DS + -- -- TIME DATE TS -- DS
- -- -- -- -- -- -- DS
* DS DS -- -- -- -- --
/ DS DS -- -- -- -- --

示例

--字符型与数值型运算时,将字符型转换为NUMBER类型后参与计算
SELECT '44'/2 char_cal,
TYPEOF('44'/2) type_trans
FROM dual;
   CHAR_CAL TYPE_TRANS
----------- ----------
         22 number
   
--INT类型与FLOAT类型计算时,将INT类型转换为FLOAT类型参与计算
SELECT 2*CAST(2 AS FLOAT) int_cal,
TYPEOF(2*CAST(2 AS FLOAT)) type_trans
FROM dual;
    INT_CAL TYPE_TRANS                                                     
----------- ----------------------------------------------------------------
   4.0E+000 float

# 日期时间型算术运算

日期时间型数据可参与如下算术运算:

运算符 操作数 返回类型 运算规则
+ 二元 * 时间 * 将两个间隔类型相加,返回更长的间隔类型。
* 将DATE、TIMESTAMP与TIME类型相加,返回在时间轴上更靠后的TIMESTAMP。
* 将TIME、DATE、TIMESTAMP与间隔类型相加,返回在时间轴上更靠后的TIME、DATE、TIMESTAMP。
* 将DATE、TIMESTAMP与数值相加,数值被解释为天数(小数部分表示不满一天的时间),返回在时间轴上更靠后的DATE。
- 二元 * 时间间隔
* 时间
* 将两个间隔类型相减,返回更短的间隔类型。
* 将DATE、TIMESTAMP与TIME相减,返回在时间轴上更靠前的TIMESTAMP。
* 将两个DATE相减,返回数值,表示相差的天数。
* 将DATE与TIMESTAMP相减,或TIMESTAMP与TIMESTAMP相减,返回DS_INTERVAL。
* 将DATE或TIMESTAMP与数值相减,数值被解释为天数(小数部分表示不满一天的时间),返回在时间轴上更靠前的DATE。
* 二元 * 时间间隔
* 时间
* 将间隔类型与数值相乘,返回被扩大倍数的间隔。
/ 二元 * 时间间隔
* 时间
* 将间隔类型除以数值,返回被缩小倍数的间隔。

如下是时间类型和时间间隔类型支持运算的详细情况,其中YM表示INTERVAL YEAR TO MONTH,DS表示INTERVAL DAY TO SECOND,TS表示TIMESTAMP:

数据类型 NUMBER TIME DS YM DATE TS
TIME N/A 支持运算:-
返回类型:DS
支持运算:+-
返回类型:TIME
N/A 支持运算:+
返回类型:TS
支持运算:+
返回类型:TS
DS 支持运算:*/ 
返回类型:DS
支持运算:+ 
返回类型:TIME
支持运算:+-
返回类型:DS
N/A 支持运算:+
返回类型:DATE
支持运算:+
返回类型:TS
YM 支持运算:*/ 
返回类型:YM
N/A N/A 支持运算:+-
返回类型:YM
支持运算:+
返回类型:DATE
支持运算:+
返回类型:TS
DATE 支持运算:+-
返回类型:DATE
支持运算:+-
返回类型:TS
支持运算:+-
返回类型:DATE
支持运算:+-
返回类型:DATE
支持运算:-
返回类型:NUMBER
支持运算:-
返回类型:DS
TS 支持运算:+-
返回类型:DATE
支持运算:+-
返回类型:TS
支持运算:+-
返回类型:TS
支持运算:+-
返回类型:TS
支持运算:-
返回类型:DS
支持运算:-
返回类型:DS

示例

CREATE TABLE date_dd(a DATE, b DATE);
INSERT INTO date_dd VALUES('2008-12-31','2018-12-31');
COMMIT;
     
--运算符 '-'  返回时间间隔
SELECT b-a FROM date_dd;
        B-A
-----------
       3652
     
--运算符 '-'  返回时间
SELECT b-1 FROM date_dd;
B-1                          
--------------------------------
2018-12-30 00:00:00                 
     
SELECT SYSDATE+2 FROM DUAL;
SYSDATE+2                    
--------------------------------
2021-06-10 11:07:47                  
    
-- DATE和TIEMSTAMP与数值类型做加减运算,数值表示天
CREATE TABLE date_dt(c1 DATE, c2 TIMESTAMP);
INSERT INTO date_dt VALUES ('2020-03-31', '2020-03-31 12:30:59.999999');
COMMIT;
     
SELECT c1-2.5, c2-2.5 FROM date_dt;
C1-2.5                           C2-2.5
-------------------------------- --------------------------------
2020-03-28 12:00:00              2020-03-29 00:30:59
     
SELECT c1+'2.5', c2+'2.5' FROM date_dt;
C1+'2.5'                         C2+'2.5'
-------------------------------- --------------------------------
2020-04-02 12:00:00              2020-04-03 00:30:59    
     
SELECT c1 FROM date_dt;
C1
--------------------------------
2020-03-31 00:00:00             
   
 
-- 输出结果为TIME类型的运算
CREATE TABLE date_t(c1 TIME);
INSERT INTO date_t VALUES ('23:59:59.999999');
COMMIT;
     
SELECT c1+INTERVAL '5' HOUR FROM date_t;
C1+INTERVAL'5'HOUR
--------------------
04:59:59.999999

输出的日期如果不合法,结果会报错。

示例

--对上例data_dt中的字段执行下面的运算,结果为4月31日,该日期不合法
SELECT C1+INTERVAL '01-01' YEAR TO MONTH FROM date_dt;
--行存表输出
YAS-00008 type convert error : not a valid month
--列存表输出
YAS-05012 date not valid for month specified