三大数据库 sequence 之华山论剑 (下篇)
MySQL 5.7 MYISAM ENGINE
以下是 MySQL 5.7 MYISAM ENGINE 中的运行结果
mysql> CREATE TABLE tb_test5 (
-> test_id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
-> test_order INTEGER
-> ) ENGINE = MYISAM;
Query OK, 0 rows affected (0.00 sec)
mysql> SHOW CREATE TABLE tb_test5;
+----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table |
+----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| tb_test5 | CREATE TABLE `tb_test5` (
`test_id` int(11) NOT NULL AUTO_INCREMENT,
`test_order` int(11) DEFAULT NULL,
PRIMARY KEY (`test_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 |
+----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> INSERT INTO tb_test5 (test_order) VALUES (1);
Query OK, 1 row affected (0.00 sec)
mysql> SELECT last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 1 |
+------------------+
1 row in set (0.00 sec)
mysql> INSERT INTO tb_test5 (test_id,test_order) VALUES (100,2);
Query OK, 1 row affected (0.00 sec)
mysql> SELECT last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 1 |
+------------------+
1 row in set (0.00 sec)
mysql> INSERT INTO tb_test5 (test_order) VALUES (3);
Query OK, 1 row affected (0.00 sec)
mysql> SELECT last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 101 |
+------------------+
1 row in set (0.00 sec)
mysql>
mysql> SELECT * FROM tb_test5 ORDER BY 2 DESC;
+---------+------------+
| test_id | test_order |
+---------+------------+
| 101 | 3 |
| 100 | 2 |
| 1 | 1 |
+---------+------------+
3 rows in set (0.00 sec)
mysql> UPDATE tb_test5 SET test_id = 200 WHERE test_order = 3;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> SELECT last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 101 |
+------------------+
1 row in set (0.00 sec)
mysql> SELECT * FROM tb_test5 ORDER BY 2 DESC;
+---------+------------+
| test_id | test_order |
+---------+------------+
| 200 | 3 |
| 100 | 2 |
| 1 | 1 |
+---------+------------+
3 rows in set (0.00 sec)
mysql> INSERT INTO tb_test5 (test_order) VALUES (5);
Query OK, 1 row affected (0.00 sec)
mysql> SELECT last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 201 |
+------------------+
1 row in set (0.00 sec)
mysql> SELECT * FROM tb_test5 ORDER BY 2 DESC;
+---------+------------+
| test_id | test_order |
+---------+------------+
| 201 | 5 |
| 200 | 3 |
| 100 | 2 |
| 1 | 1 |
+---------+------------+
4 rows in set (0.00 sec)
mysql> INSERT INTO tb_test5 (test_order) VALUES (5);
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO tb_test5 (test_order) VALUES (6);
Query OK, 1 row affected (0.00 sec)
mysql> SELECT last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 203 |
+------------------+
1 row in set (0.00 sec)
mysql> SELECT * FROM tb_test5 ORDER BY 2 DESC;
+---------+------------+
| test_id | test_order |
+---------+------------+
| 203 | 6 |
| 201 | 5 |
| 202 | 5 |
| 200 | 3 |
| 100 | 2 |
| 1 | 1 |
+---------+------------+
6 rows in set (0.00 sec)
mysql> DELETE FROM tb_test5 WHERE test_order = 5;
Query OK, 2 rows affected (0.00 sec)
mysql> DELETE FROM tb_test5 WHERE test_order = 6;
Query OK, 1 row affected (0.01 sec)
mysql> SELECT last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 203 |
+------------------+
1 row in set (0.00 sec)
mysql> SELECT * FROM tb_test5 ORDER BY 2 DESC;
+---------+------------+
| test_id | test_order |
+---------+------------+
| 200 | 3 |
| 100 | 2 |
| 1 | 1 |
+---------+------------+
3 rows in set (0.00 sec)
mysql> INSERT INTO tb_test5 (test_order) VALUES (7);
Query OK, 1 row affected (0.00 sec)
mysql> SELECT last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 204 |
+------------------+
1 row in set (0.00 sec)
mysql> SELECT * FROM tb_test5 ORDER BY 2 DESC;
+---------+------------+
| test_id | test_order |
+---------+------------+
| 204 | 7 |
| 200 | 3 |
| 100 | 2 |
| 1 | 1 |
+---------+------------+
4 rows in set (0.00 sec)
mysql> TRUNCATE TABLE tb_test5;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 204 |
+------------------+
1 row in set (0.00 sec)
mysql> INSERT INTO tb_test5 (test_order) VALUES (8);
Query OK, 1 row affected (0.00 sec)
mysql> SELECT last_insert_id();
+------------------+
| last_insert_id() |
+------------------+
| 1 |
+------------------+
1 row in set (0.00 sec)
mysql> SELECT * FROM tb_test5 ORDER BY 2 DESC;
+---------+------------+
| test_id | test_order |
+---------+------------+
| 1 | 8 |
+---------+------------+
1 row in set (0.00 sec)
mysql>
Oracle 12c
以下是 Oracle 12c(Release 12.2.0.1.0) 中的运行结果
SQL> INSERT INTO tb_test4 (test_order) VALUES (1);
1 row created.
SQL> INSERT INTO tb_test4 (test_id,test_order) VALUES (100,2);
1 row created.
SQL> INSERT INTO tb_test4 (test_order) VALUES (3);
1 row created.
SQL> COMMIT;
Commit complete.
SQL> SELECT * FROM tb_test4 ORDER BY 2 DESC;
TEST_ID TEST_ORDER
---------- ----------
2 3
100 2
1 1
SQL> COL table_name FOR a30
COL column_name FOR a30
COL generation FOR a30
COL sequence_name FOR a30
SELECT table_name,column_name,sequence_name FROM user_tab_identity_cols;SQL> SQL> SQL> SQL>
SQL> SELECT table_name,column_name,sequence_name FROM user_tab_identity_cols;
TABLE_NAME COLUMN_NAME SEQUENCE_NAME
------------------------------ ------------------------------ ------------------------------
TB_TEST4 TEST_ID ISEQ$$_254864
SQL>
SQL> SELECT ISEQ$$_254864.currval FROM dual;
CURRVAL
----------
2
SQL> UPDATE tb_test4 SET test_id = 200 WHERE test_order = 3;
1 row updated.
SQL> SELECT ISEQ$$_254864.currval FROM dual;
CURRVAL
----------
2
SQL> INSERT INTO tb_test4 (test_order) VALUES (5);
1 row created.
SQL> SELECT ISEQ$$_254864.currval FROM dual;
CURRVAL
----------
3
SQL> SELECT * FROM tb_test4 ORDER BY 2 DESC;
TEST_ID TEST_ORDER
---------- ----------
3 5
200 3
100 2
1 1
SQL>
SQL> INSERT INTO tb_test4 (test_order) VALUES (6);
1 row created.
SQL> COMMIT;
Commit complete.
SQL> SELECT ISEQ$$_254864.currval FROM dual;
CURRVAL
----------
4
SQL> SELECT * FROM tb_test4 ORDER BY 2 DESC;
TEST_ID TEST_ORDER
---------- ----------
4 6
3 5
200 3
100 2
1 1
SQL>
SQL> DELETE FROM tb_test4 WHERE test_order = 5;
1 row deleted.
SQL> DELETE FROM tb_test4 WHERE test_order = 6;
1 row deleted.
SQL> COMMIT;
Commit complete.
SQL> INSERT INTO tb_test4 (test_order) VALUES (7);
1 row created.
SQL> COMMIT;
Commit complete.
SQL> SELECT ISEQ$$_254864.currval FROM dual;
CURRVAL
----------
5
SQL> SELECT * FROM tb_test4 ORDER BY 2 DESC;
TEST_ID TEST_ORDER
---------- ----------
5 7
200 3
100 2
1 1
SQL> TRUNCATE TABLE tb_test4;
Table truncated.
SQL> INSERT INTO tb_test4 (test_order) VALUES (8);
1 row created.
SQL> SELECT ISEQ$$_254864.currval FROM dual;
CURRVAL
----------
6
SQL> SELECT * FROM tb_test4 ORDER BY 2 DESC;
TEST_ID TEST_ORDER
---------- ----------
6 8
PostgreSQL 11
以下是 PostgreSQL 11 中的运行结果
alvindb=> INSERT INTO tb_test4 (test_order) VALUES (1);
INSERT 0 1
alvindb=> INSERT INTO tb_test4 (test_id,test_order) VALUES (100,2);
INSERT 0 1
alvindb=> INSERT INTO tb_test4 (test_order) VALUES (3);
INSERT 0 1
alvindb=> SELECT * FROM tb_test4 ORDER BY 2 DESC;
test_id | test_order
---------+------------
2 | 3
100 | 2
1 | 1
(3 rows)
alvindb=>
alvindb=> \d+ tb_test4
Table "public.tb_test4"
Column | Type | Collation | Nullable | Default | Storage | Stats target | Description
------------+---------+-----------+----------+-------------------------------------------+---------+--------------+-------------
test_id | integer | | not null | nextval('tb_test4_test_id_seq'::regclass) | plain | |
test_order | integer | | | | plain | |
Indexes:
"tb_test4_pkey" PRIMARY KEY, btree (test_id)
alvindb=> SELECT currval('tb_test4_test_id_seq');
currval
---------
2
(1 row)
alvindb=> UPDATE tb_test4 SET test_id = 200 WHERE test_order = 3;
UPDATE 1
alvindb=> SELECT * FROM tb_test4 ORDER BY 2 DESC;
test_id | test_order
---------+------------
200 | 3
100 | 2
1 | 1
(3 rows)
alvindb=> SELECT currval('tb_test4_test_id_seq');
currval
---------
2
(1 row)
alvindb=> INSERT INTO tb_test4 (test_order) VALUES (5);
INSERT 0 1
alvindb=> SELECT currval('tb_test4_test_id_seq');
currval
---------
3
(1 row)
alvindb=> SELECT * FROM tb_test4 ORDER BY 2 DESC;
test_id | test_order
---------+------------
3 | 5
200 | 3
100 | 2
1 | 1
(4 rows)
alvindb=> INSERT INTO tb_test4 (test_order) VALUES (6);
INSERT 0 1
alvindb=> SELECT currval('tb_test4_test_id_seq');
currval
---------
4
(1 row)
alvindb=> SELECT * FROM tb_test4 ORDER BY 2 DESC;
test_id | test_order
---------+------------
4 | 6
3 | 5
200 | 3
100 | 2
1 | 1
(5 rows)
alvindb=> DELETE FROM tb_test4 WHERE test_order = 5;
DELETE 1
alvindb=> DELETE FROM tb_test4 WHERE test_order = 6;
DELETE 1
alvindb=> INSERT INTO tb_test4 (test_order) VALUES (7);
INSERT 0 1
alvindb=> SELECT currval('tb_test4_test_id_seq');
currval
---------
5
(1 row)
alvindb=> SELECT * FROM tb_test4 ORDER BY 2 DESC;
test_id | test_order
---------+------------
5 | 7
200 | 3
100 | 2
1 | 1
(4 rows)
alvindb=>
alvindb=> TRUNCATE TABLE tb_test4;
TRUNCATE TABLE
alvindb=> INSERT INTO tb_test4 (test_order) VALUES (8);
INSERT 0 1
alvindb=> SELECT currval('tb_test4_test_id_seq');
currval
---------
6
(1 row)
alvindb=> SELECT * FROM tb_test4 ORDER BY 2 DESC;
test_id | test_order
---------+------------
6 | 8
(1 row)
总结
sequence 调用方式支持统计
从下表可以看出,Oracle 与 PostgreSQL 对以下sequence 的调用方式都支持。MySQL 仅支持 AUTO INCREMENT 方式。
Oracle | PostgreSQL | MySQL | |
---|---|---|---|
显示调用 sequence | YES | YES | NO |
触发器中调用 sequence | YES | YES | NO |
DEFAULT 中调用 sequence | YES | YES | NO |
AUTO INCREMENT | YES | YES | YES |
AUTO INCREMENT 方式统计
AUTO INCREMENT 主键创建方式统计如下:
Database | AUTO INCREMENT 主键创建方式 |
---|---|
Oracle | test_id NUMBER GENERATED BY DEFAULT ON NULL AS IDENTITY |
PostgreSQL | test_id SERIAL PRIMARY KEY |
MySQL | test_id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY |
AUTO INCREMENT 方式中,INSERT 大于 sequence 的值/UPDATE/DELETE/TRUNCATE 是否会重置 sequence 统计如下:
Oracle | PostgreSQL | MySQL 5.7 InnoDB | MySQL 5.7 MYISAM | |
---|---|---|---|---|
INSERT 大于 sequence 的值 | NO | NO | YES | YES |
UPDATE | NO | NO | NO | YES |
DELETE | NO | NO | NO | NO |
TRUNCATE | NO | NO | YES | YES |
可以看出,AUTO INCREMENT 方式下,
Oracle 和 PostgreSQL 中,sequence 与 UPDATE/DELETE/TRUNCATE 相对独立的,仅会在 INSERT 时自增,且在INSERT 大于 当前sequence 的值时,并不会重置 sequence。
在 MySQL 中,sequence 的重置与否,不但与 MySQL DML/DDL 有关,还与表使用的 ENGINE有关,使用时需要特别注意。
INSERT 方式统计
INSERT WITH SEQUENCE
以下方式在 SQL 中指明了 sequence。
这种使用方式灵活多变,基本适用各种场景,尤其是大型复杂数据库应用中。
如果使用的数据库是 Oracle 或 PostgreSQL,推荐这种方式。
--Oracle
INSERT INTO tb_test (test_id) VALUES (seq_test.nextval);
--PostgreSQL
INSERT INTO tb_test (test_id) VALUES (nextval('seq_test'));
INSERT WITHOUT COLUMN NAME
SQL 如下
INSERT INTO tb_test (test_order) VALUES (1);
下表统计 INSERT WITHOUT COLUMN NAME 时,数据库是否能如期插入 sequence 的下一个值。
可以看出,这种 INSERT 方式对以下三种数据库支持良好,且好记好理解。
从 SQL 对各数据库的兼容性考虑,推荐这种省略列名的方式。
Oracle | PostgreSQL | MySQL | |
---|---|---|---|
触发器中调用 sequence | YES | YES | |
DEFAULT 中调用 sequence | YES | YES | - |
AUTO INCREMENT | YES | YES | YES |
INSERT NULL
SQL 如下
INSERT INTO tb_test (test_id,test_order) VALUES (NULL,1);
下表统计 INSERT NULL 时,数据库是否能如期插入 sequence 的下一个值。
从以下统计表格可以看出,支持不统一。
从 SQL 对各数据库的兼容性考虑,除非特意使用,一般不作推荐。
Oracle | PostgreSQL | MySQL | |
---|---|---|---|
触发器中调用 sequence | YES | YES | - |
DEFAULT 中调用 sequence | NO | NO | - |
AUTO INCREMENT | YES/NO | NO | YES |
INSERT DEFAULT
SQL 如下
INSERT INTO tb_test (test_id,test_order) VALUES (DEFAULT,1);
从下表可以看出,INSERT DEFAULT 都能插入 sequence 的下一个值。
但在触发器调用 sequence 的方式中,DEFAULT 并不是专门用来插入 sequence 的下一个值的,此时用 DEFAULT 较奇怪。
DEFAULT 一般仅在定义了列的 DEFAULT 值时使用。
Oracle | PostgreSQL | MySQL | |
---|---|---|---|
触发器中调用 sequence | YES | YES | - |
DEFAULT 中调用 sequence | YES | YES | - |
AUTO INCREMENT | YES | YES | YES |
公众号
关注 DBA Daily 公众号,第一时间收到文章的更新。
通过一线 DBA 的日常工作,学习实用数据库技术干货!
公众号优质文章推荐
[PG Upgrade Series] Extract Epoch Trap
[PG Upgrade Series] Toast Dump Error
GitLab supports only PostgreSQL now
三大数据库 sequence 之华山论剑 (下篇)的更多相关文章
- 三大数据库 sequence 之华山论剑 (上篇)
前言 本文将基于以下三种关系型数据库,对 sequence (序列) 展开讨论. Oracle - 应用最广泛的商用关系型数据库 PostgreSQL - 功能最强大的开源关系型数据库 MySQL - ...
- 三大数据库 sequence 之华山论剑 (中篇)
sequence 用法四 AUTO INCREMENT 通过 DEFAULT 还是需要手动创建 sequence.有没有更简单的用法呢? 当然,就是通过 AUTO INCREMENT 方式,自动创建 ...
- redis mongodb mysql 三大数据库的更简单的批量操作。批量任务自动聚合器。
1.redis mongodb mysql的python包都提供了批量插入操作,但需要自己在外部对一个例如1000 001个任务进行分解成每1000个为1个小批次,还要处理整除批次数量后的余数,如果做 ...
- 数据库sequence的作用和用法
转: 数据库sequence的作用和用法 2016年10月14日 19:51:03 很菜很菜的鸟 阅读数 14456 标签: oracle数据库db2sequence seqence的作用: se ...
- JDBC读取新插入Oracle数据库Sequence值的5种方法
Oracle的sequence实现非常灵活,所以也带来一些易用性问题,如何取到新插入记录生成的sequence值与其它数据库有较大差别,本文详国介绍了5种实现读取新插入记录sequence值的方法. ...
- 数据库Sequence创建与使用
最近几天使用Oracle的sequence序列号,发现对如何创建.修改.使用存在很多迷茫点,在上网寻找答案后,根据各路大神的总结,汇总下对自己的学习成果: 在Oracle中sequence就是序号,每 ...
- Oracle,Mysql ,SQL Server 三大数据库带参数的模糊查询, 拼接查询条件问题
最近项目开发一直在不断切换数据库,有时候一条sql 要同时考虑多种数据库中的兼容问题 , 先总结一条模糊查询拼接查询条件的问题,后续追加总结. 目前使用 mybatis: 1. Oracle 中使 ...
- Mysql、SqlServer、Oracle三大数据库的区别
一.MySQL 优点: 体积小.速度快.总体拥有成本低,开源: 支持多种操作系统: 是开源数据库,提供的接口支持多种语言连接操作 : MySQL的核心程序采用完全的多线程编程.线程是轻量级的进程,它可 ...
- oracle、mysql、db2三大数据库分页方法的整理
最近项目中经常会涉及到代码中支持三种数据库的分页的功能,自己整理了关于三种数据库的分页的写法,分享给大家,以供大家使用.希望能帮到更多的码友! 先来看一个代码片段: String page = ala ...
随机推荐
- C++虚函数和静态函数调用方式
简单情况: #include<iostream> using namespace std; class A { public: virtual void foo() { cout < ...
- Android开发----EditText&ImageView&第三方库的加载
EditText组件 一个实例描述该组件的全部属性(虚假的登录界面) 在activity.xml中 <?xml version="1.0" encoding="ut ...
- MongoDB常用运维命令
# 查看Mongodb版本信息 mongos> db.version() # 关闭mongodb服务 mongos> use admin mongos> shutdownServer ...
- find直接copy大于某一个时间小于某一个时间的文件
find ./ -type f -newermt '2000-01-04 10:30:00' ! -newermt '2019-10-28 10:57:00' -exec cp -a {} /var/ ...
- 蓝桥杯试题 基础练习 2n皇后问题以及n皇后问题
在学习2n皇后之前,我们应该认识一下n皇后问题: 在N*N的方格棋盘放置了N个皇后,使得它们不相互攻击(即任意2个皇后不允许处在同一排,同一列,也不允许处在与棋盘边框成45角的斜线上.你的任务是,对于 ...
- 最大公因数与最小公倍数-gcd&lcm
一.一些性质 \(gcd(a,b)=gcd(b,a)\) \(gcd(-a,b)=gcd(a,b)\) \(gcd(a,a)=|a|, gcd(a,0)=|a|\) \(gcd(a,1)=1\) \( ...
- STL priority_queue 优先队列 小记
今天做题发现一个很有趣的地方,竟然还是头一次发现,唉,还是太菜了. 做图论用STL里的priority_queue去优化prim,由于特殊需求,我需要记录生成树中是用的哪些边. 于是,我定义的优先队列 ...
- String存放位置
简介 字符串在不同的JDK版本中,存放的位置不同,创建方式不同,存放的位置也不同. 存放位置 JDK1.7以下,无论何种方法创建String对象,位置都位于方法区. JDK1.8及1.8以上,new ...
- JAVA之容器(转)
一.概览 容器主要包括 Collection 和 Map 两种,Collection 存储着对象的集合,而 Map 存储着键值对(两个对象)的映射表. Collection 1. Set TreeSe ...
- svn中.a文件无法上传解决方法
项目导入后总是缺少.a文件,如shareSDK.a,libPushSDK.a,libbaidumapapi.a等 解决方法 方法一.修改SVN配置文件 通过终端直接打开配置文件: open ~/.s ...