三、MySQL 替代 Oracle 序列以及自增长处理

一、MySQL 替代 Oracle 序列以及自增长处理

什么是自增长?

  • 自增长只能用于表中的其中一个字段。
  • 自增长只能被分配给固定表的固定的某一字段,不能被多个表共用。
  • 自增长会把一个未指定或NULL值的字段自动填上。
一、在 Oracle 中如何实现 MySQL 的自增长?

请看下面的实例:

  • 1-1、在 MYSQL 里有这样一张表:
CREATE TABLE Movie(  
  id           INT NOT NULL AUTO_INCREMENT,  
  name     VARCHAR(60) NOT NULL,  
  released YEAR NOT NULL,  
  PRIMARY KEY (id)  
) ENGINE=InnoDB;  

INSERT INTO Movie (name,released) VALUES ('Gladiator',2000);  
INSERT INTO Movie (id,name,released) VALUES (NULL,'The Bourne Identity',1998);  
  • 1-2、在 ORACLE 是这样的使用序列对象+触发器来完成 MySQL 的自增长功能
CREATE TABLE Movie(  
 id          INT NOT NULL,  
 name     VARCHAR2(60) NOT NULL,  
 released INT NOT NULL,  
 PRIMARY KEY (id)  
);  
CREATE SEQUENCE MovieSeq;  
INSERT INTO Movie (id,name,released) VALUES (MovieSeq.NEXTVAL,'Gladiator',2000);  

在 Oracle 下为表添加一个触发器,就可以实现 MySQL 自增长功能:

1\.  CREATE OR REPLACE TRIGGER BRI_MOVIE_TRG  
2\.  BEFORE INSERT ON Movie  
3\.  FOR EACH ROW  
4\.  BEGIN  
5\.  SELECT MovieSeq.NEXTVAL INTO :new.id FROM DUAL;  
6\.  END BRI_MOVIE_TRG;  
7\.  .  
8\.  RUN;  

这样,插入记录就可以成为 MYSQL 风格:

INSERT INTO Movie (name,released) VALUES ('The Lion King',1994);  

下面我们来看看如何在 mysql 数据里使用 Oracle 序列语法 .NEXTVAL 和 .CURVAL。

二、MySQL 如何实现 Oracle 序列?

一般使用序列 (Sequence) 来处理主键字段,在 MySQL中 是没有序列的,但是 MySQL有提供了自增长 (increment) 来实现类似的目的,但也只是自增,而不能设置步长、开始索引、是否循环等,最重要的是一张表只能由一个字段使用自增,但有的时候我们需要两个或两个以上的字段实现自增(单表多字段自增),MySQL本身是实现不了的,但我们可以用创建一个序列表,使用函数来获取序列的值。

我们假设在 MySQL 中序列的语法是:

NEXTVAL(’sequence’);
CURRVAL(’sequence’);
SETVAL(’sequence’,value);
DROP TABLE IF EXISTS sequence;  
CREATE TABLE sequence (  
name              VARCHAR(50) NOT NULL,  
current_value INT NOT NULL,  
increment       INT NOT NULL DEFAULT 1,  
PRIMARY KEY (name)  
) ENGINE=InnoDB;  

 INSERT INTO sequence VALUES ('MovieSeq',3,5); 
测试一下结果:

测试 currval 函数使用

/* currval 函数的实现 */
 DROP FUNCTION IF EXISTS currval;  
 DELIMITER $  
 CREATE FUNCTION currval (seq_name VARCHAR(50))  
 RETURNS INTEGER  
 CONTAINS SQL  
 BEGIN  
 DECLARE value INTEGER;  
 SET value = 0;  
 SELECT current_value INTO value  
 FROM sequence  
 WHERE name = seq_name;  
 RETURN value;  
 END$  
 DELIMITER ;
1\.  mysql> SELECT currval('MovieSeq');  
2\.  +---------------------+  
3\.  | currval('MovieSeq') |  
4\.  +---------------------+  
5\.  |                   3 |  
6\.  +---------------------+  
7\.  1 row in set (0.00 sec)  
8\.  mysql> SELECT currval('x');  
9\.  +--------------+  
10\.  | currval('x') |  
11\.  +--------------+  
12\.  |            0 |  
13\.  +--------------+  
14\.  1 row in set, 1 warning (0.00 sec)  
15\.  mysql> show warnings;  
16\.  +---------+------+------------------+  
17\.  | Level   | Code | Message          |  
18\.  +---------+------+------------------+  
19\.  | Warning | 1329 | No data to FETCH |  
20\.  +---------+------+------------------+  
21\.  1 row in set (0.00 sec)  

测试 nextval 函数使用

/* nextval 函数的实现 */
DROP FUNCTION IF EXISTS nextval;  
DELIMITER $  
CREATE FUNCTION nextval (seq_name VARCHAR(50))  
RETURNS INTEGER  
CONTAINS SQL  
BEGIN  
UPDATE sequence  
SET          current_value = current_value + increment  
WHERE name = seq_name;  
RETURN currval(seq_name);  
END$  
DELIMITER ;  
1\.  mysql> select nextval('MovieSeq');  
2\.  +---------------------+  
3\.  | nextval('MovieSeq') |  
4\.  +---------------------+  
5\.  |                  15 |  
6\.  +---------------------+  
7\.  1 row in set (0.09 sec)  

9\.  mysql> select nextval('MovieSeq');  
10\.  +---------------------+  
11\.  | nextval('MovieSeq') |  
12\.  +---------------------+  
13\.  |                  20 |  
14\.  +---------------------+  
15\.  1 row in set (0.01 sec)  

17\.  mysql> select nextval('MovieSeq');  
18\.  +---------------------+  
19\.  | nextval('MovieSeq') |  
20\.  +---------------------+  
21\.  |                  25 |  
22\.  +---------------------+  
23\.  1 row in set (0.00 sec)  

测试 setval 函数的使用

/* setval 函数的实现 */
DROP FUNCTION IF EXISTS setval;  
DELIMITER $  
CREATE FUNCTION setval (seq_name VARCHAR(50), value INTEGER)  
RETURNS INTEGER  
CONTAINS SQL  
BEGIN  
UPDATE sequence  
SET          current_value = value  
WHERE name = seq_name;  
RETURN currval(seq_name);  
END$  
DELIMITER ;  
1\.  mysql> select setval('MovieSeq',150);  
2\.  +------------------------+  
3\.  | setval('MovieSeq',150) |  
4\.  +------------------------+  
5\.  |                    150 |  
6\.  +------------------------+  
7\.  1 row in set (0.06 sec)  

9\.  mysql> select curval('MovieSeq');  
10\.  +---------------------+  
11\.  | currval('MovieSeq') |  
12\.  +---------------------+  
13\.  |                 150 |  
14\.  +---------------------+  
15\.  1 row in set (0.00 sec)  

17\.  mysql> select nextval('MovieSeq');  
18\.  +---------------------+  
19\.  | nextval('MovieSeq') |  
20\.  +---------------------+  
21\.  |                 155 |  
22\.  +---------------------+  
23\.  1 row in set (0.00 sec)
三、MySQL 替代 Oracle 序列实例:
  • 1、问题场景:
    一般使用序列 (Sequence) 来处理主键字段,在 MySQL中 是没有序列的,但是 MySQL有提供了自增长 (increment) 来实现类似的目的,但也只是自增,而不能设置步长、开始索引、是否循环等,最重要的是一张表只能由一个字段使用自增,但有的时候我们需要两个或两个以上的字段实现自增(单表多字段自增),MySQL本身是实现不了的,但我们可以用创建一个序列表,使用函数来获取序列的值。

-- MySQL 给数据表某个字段创建序列。
-- 序列:自增(步长、开始索引、是否循环),暂不考虑是否循环自增(触发器可实现?)
select * from PAN_WF_HISTORYNODE;-- ORDER_NUMBER 字段创建序列

-- 创建代替序列的数据表

DROP TABLE IF EXISTS sequence;  
CREATE TABLE sequence (  
name              VARCHAR(50) NOT NULL, -- 序列 名称 50个字符最大值问题已够用,暂不考虑是否循环。
current_value INT NOT NULL,  -- 当前值
increment       INT NOT NULL DEFAULT 1,  -- 步长
PRIMARY KEY (name)  
) ENGINE=InnoDB;  
INSERT INTO sequence VALUES ('seq_hisnode',0,1);

-- 处理 序列的 currval 函数

Set global log_bin_trust_function_creators=1;-- 解决自定义函数报错:ERROR 1418-This function has none of DETERMINISTIC

DROP FUNCTION IF EXISTS currval;  
DELIMITER $  
CREATE FUNCTION currval (seq_name VARCHAR(50))  
RETURNS INTEGER  
CONTAINS SQL  
BEGIN  
  DECLARE value INTEGER;  
  SET value = 0;  
  SELECT current_value INTO value  
  FROM sequence  
  WHERE name = seq_name;  
  RETURN value;  
END$  
DELIMITER ;  

SELECT currval('seq_hisnode');-- 测试 该函数的使用。

-- 处理序列的 nextval 函数

DROP FUNCTION IF EXISTS nextval;  
DELIMITER $  
CREATE FUNCTION nextval (seq_name VARCHAR(50))  
RETURNS INTEGER  
CONTAINS SQL  
BEGIN  
   UPDATE sequence  
   SET          current_value = current_value + increment  
   WHERE name = seq_name;  
   RETURN currval(seq_name);  
END$  
DELIMITER ;

select nextval('seq_hisnode');
INSERT into PAN_WF_HISTORYNODE values()
posted @ 2021-08-21 21:52  星命定轨  阅读(707)  评论(0编辑  收藏  举报