§ SQL兼容性 - DATETIME加减运算
§ 1. 语法
set sql_mode=oracle;
select sysdate + 1 from dual;
select sysdate - 1 from dual;
select sysdate - sysdate from dual;
1
2
3
4
5
2
3
4
5
§ 2. 定义和用法
- 只支持加减运算,不支持其他运算类型。
- 对TIME类型运算前,会先被转换成
DATETIME
类型。 - 会先将时间戳的值转换为日期值,并将
NUMBER
算术日期时间和间隔表达式中的常量解释为天数。 - 年份范围为:0 ~ 9999年,不支持公元前的年份,溢出时将返回NULL,并产生warning。
- 当计算结果包含无限循环小数时,默认只保留10位,即:
div_precincrement
选项默认值(4) + 6 = 10。 - 对YEAR类型加减运算时,默认转换将失败而无法运算时,会返回NULL , 并产生warning。
- 例1:多个查询结果集合并,或者数值作为查询条件时
greatsql> select to_date('00:00:00','HH24:MI:SS') - to_date('00:00:01','HH24:MI:SS') from dual
union all
select to_date('00:00:00','HH24:MI:SS') - to_date('00:00:01','HH24:MI:SS') from dual;
+----------------------------------------------------------------------+
| to_date('00:00:00','HH24:MI:SS') - to_date('00:00:01','HH24:MI:SS') |
+----------------------------------------------------------------------+
| -0.0000115741 |
| -0.0000115741 |
+----------------------------------------------------------------------+
- 例2:在单一查询计算结果作为字符串展示的时候,保留小数位长度不再限制保留10位
greatsql> select to_date('00:00:00','HH24:MI:SS') - to_date('00:00:01','HH24:MI:SS');
+----------------------------------------------------------------------+
| to_date('00:00:00','HH24:MI:SS') - to_date('00:00:01','HH24:MI:SS') |
+----------------------------------------------------------------------+
| -0.000011574074074074 |
+----------------------------------------------------------------------+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
DATETIME类型运算兼容矩阵
Operand & Operator | DATETIME | TIMESTAMP | TIME | NUMBER |
---|---|---|---|---|
DATETIME | - | - | - | - |
+ | - | - | - | DATETIME |
— | DECIMAL | DECIMAL | DECIMAL | DATETIME |
* | - | - | - | - |
/ | - | - | - | - |
TIMESTAMP | - | - | - | - |
+ | - | - | - | TIMESTAMP |
- | DECIMAL | DECIMAL | DECIMAL | TIMESTAMP |
* | - | - | - | - |
/ | - | - | - | - |
DATE | ||||
+ | - | - | - | DATETIME |
- | DECIMAL | DECIMAL | DECIMAL | DATETIME |
* | - | - | - | - |
/ | - | - | - | - |
TIME | - | - | - | |
+ | - | - | - | DATETIME |
- | DECIMAL | DECIMAL | DECIMAL | DATETIME |
* | - | - | - | - |
/ | - | - | - | - |
NUMBER | - | - | - | - |
+ | DATETIME | TIMESTAMP | DATETIME | NA |
- | DATETIME | TIMESTAMP | DATETIME | NA |
* | - | - | - | NA |
/ | - | - | - | NA |
上表是 DATETIME
类型算术运算的兼容矩阵,破折号代表不支持的操作。
§ 3. 与Oracle差异说明
- 默认日期差异日期保留精度不一致,在GreatSQL中默认保留10位小数精度,而Oracle中根据不同的精度数据不一样。
- 时间范围最大与最小范围不一致。在GreatSQL中年份范围是
0 ~ 9999
,而Oracle中的范围是-4713 ~ 9999
。 - 加减字符串运算行为不同,例如字符串'a',在Oracle中转换失败将会报错,而在GreatSQL中将转换为 '0' 并产生警告,之后再进行运算。
- 在GreatSQL中,
TIMESTAMP - TIMESTAMP
返回的结果是DECIMAL
类型, Oracle 中返回INTERVAL
类型。
§ 4. 示例
set sql_mode='oracle';
greatsql> set timestamp=1;
-- +1/2 等同于 +12小时
greatsql> select sysdate +1/2 ;
+----------------------------+
| sysdate +1/2 |
+----------------------------+
| 1970-01-01 12:00:01.000000 |
+----------------------------+
-- 等同于 +1天
greatsql> select sysdate +1 ;
+----------------------------+
| sysdate +1 |
+----------------------------+
| 1970-01-02 00:00:01.000000 |
+----------------------------+
-- 等同于 -1 天
greatsql> select sysdate -1 ;
+----------------------------+
| sysdate -1 |
+----------------------------+
| 1969-12-31 00:00:01.000000 |
+----------------------------+
greatsql> select sysdate - sysdate;
+-------------------+
| sysdate - sysdate |
+-------------------+
| 0 |
+-------------------+
-- 将'a'转换成'0'后再运算,并产生warning
greatsql> select sysdate + 'a';
+----------------------------+
| sysdate + 'a' |
+----------------------------+
| 1970-01-01 00:00:01.000000 |
+----------------------------+
1 row in set, 1 warning (0.00 sec)
greatsql> show warnings;
+---------+------+---------------------------------------+
| Level | Code | Message |
+---------+------+---------------------------------------+
| Warning | 1292 | Truncated incorrect DOUBLE value: 'a' |
+---------+------+---------------------------------------+
-- 不支持 乘/除 运算,
greatsql> select sysdate * 10;
ERROR 7038 (42000): in oracle_mode: date * LONGLONG not allowed
greatsql> select sysdate / 10;
ERROR 7038 (42000): in oracle_mode: date / LONGLONG not allowed
greatsql> select sysdate + sysdate;
ERROR 7038 (42000): in oracle_mode: date + DATETIME not allowed
greatsql> select sysdate + 1000000000000;
+-------------------------+
| sysdate + 1000000000000 |
+-------------------------+
| NULL |
+-------------------------+
1 row in set, 1 warning (0.00 sec)
greatsql> show warnings;
+---------+------+--------------------------------------------+
| Level | Code | Message |
+---------+------+--------------------------------------------+
| Warning | 1441 | Datetime function: datetime field overflow |
+---------+------+--------------------------------------------+
-- 无法对YEAR做运算
greatsql> select cast(2023 as year) + 1;
+------------------------+
| cast(2023 as year) + 1 |
+------------------------+
| NULL |
+------------------------+
1 row in set, 1 warning (0.00 sec)
greatsql>show warnings;
+---------+------+----------------------------------+
| Level | Code | Message |
+---------+------+----------------------------------+
| Warning | 1292 | Incorrect datetime value: '2023' |
+---------+------+----------------------------------+
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
§ 问题反馈
§ 联系我们
扫码关注微信公众号