A tutorial on creating a self-incrementing sequence in MySQL

In the project application, there was the following scenario:
an int type serial number is required to be sent in the interface. Due to the multi-threading mode, if timestamps are used, there may be duplicates (of course, the probability is very small).
So I thought of using an independent self-incrementing sequence to solve this problem.
The current database is: mysql
, because mysql is not the same as oracle, and does not support direct sequence, so it is necessary to create a table to simulate the function of sequence. The reason for the sql statement is as follows:
Step 1: Create the --Sequence management table

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;


 
Step 2: Create -- a function that takes the current value

?

 

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


Step 3: Create -- a function that takes the next value

?

 

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


Step 4: Create -- a function to update the current value

?

 

DROP FUNCTION IF EXISTS setval;
DELIMITER $
CREATE FUNCTION setval (seq_name VARCHAR(50), value INTEGER)
     RETURNS INTEGER
     LANGUAGE SQL
     DETERMINISTIC
     CONTAINS SQL
     SQL SECURITY DEFINER
     COMMENT ''
BEGIN
     UPDATE sequence
          SET current_value = value
          WHERE name = seq_name;
     RETURN currval(seq_name);
END
$
DELIMITER ;


Step 5: Test the function function
When the above four steps are completed, you can use the following data to set the name of the sequence to be created, set the initial value, and get the current value and the next value.
 

  • INSERT INTO sequence VALUES ('TestSeq', 0, 1);----Add a sequence name and initial value, as well as the self-amplification degree
  • SELECT SETVAL('TestSeq', 10);---Set the initial value of the specified sequence
  • SELECT CURRVAL('TestSeq');--查询指定sequence的当前值
  • SELECT NEXTVAL('TestSeq');--查询指定sequence的下一个值

 

 
在java代码中,可直接创建sql语句查询下一个值,这样就解决了流水号唯一的问题。
贴出部分代码(已测试通过)

?

 

public void testGetSequence() { 
  Connection conn = JDBCUtils.getConnection(url, userName, password); 
  String sql = "SELECT CURRVAL('TestSeq');"; 
  PreparedStatement ptmt = null; 
  ResultSet rs = null; 
  try { 
    ptmt = conn.prepareStatement(sql); 
    rs = ptmt.executeQuery(); 
    int count = 0; 
    while (rs.next()) { 
      count = rs.getInt(1); 
    } 
    System.out.println(count); 
  } catch (SQLException e) { 
    e.printStackTrace(); 
  } finally { 
    JDBCUtils.close(rs, ptmt, conn); 
  } 
} 


ps: In the application, there is also a way to use java code to simulate the self-incrementing sequence. The specific idea is to create a table to store the sequence, and then call the sql statement through java to query and modify the value of the specified sequence name in this table. , please add synchronized in this way. The specific code will not be uploaded here, because it has been implemented and has not been tested.

In oracle, sequence provides multiple tables and multiple fields that can share a unique value. There are self-increasing columns in Mysql, which can basically meet the requirements of PK. However, there are restrictions on auto-incrementing columns:

a. It can only be used for one field in the table, and one cannot have more than two auto-increment columns at the same time;

b. Self-incrementing columns must be defined as key (PK or FK);

c. Self-incrementing columns cannot be shared by multiple tables;

d. When the insert statement does not include an auto-increment field or sets its value to NULL, the value will be filled in automatically.

In the case where the order of the fields is not required to increase, the sequence can be implemented in Mysql. Let's look at the following example:

DROPTABLE IF EXISTS sequence;
  
-- Build a sequence table and specify that the seq column is an unsigned large integer that supports unsigned values: 0 (default) to 18446744073709551615 (0 to 2^64–1).
CREATETABLE sequence (
   name      VARCHAR(50)NOTNULL,
     current_value  BIGINTUNSIGNED NOTNULL DEFAULT 0,
     increment    INTNOT NULL DEFAULT 1,
     PRIMARYKEY (name) – The existence of duplicate seqs is not allowed.
) ENGINE=InnoDB;
  
  
DELIMITER /
  
DROPFUNCTION IF EXISTS currval /
  
CREATEFUNCTION currval(seq_name VARCHAR(50))
RETURNSBIGINT
BEGIN
     DECLAREvalue BIGINT;
     SELECTcurrent_value INTOvalue
     FROMsequence
     WHEREupper(name) = upper(seq_name);-- 大小写不区分.
     RETURNvalue;
END;
/
  
DELIMITER ; 
  
  
DELIMITER /
  
DROPFUNCTION IF EXISTS nextval /
  
CREATEFUNCTION nextval (seq_name VARCHAR(50))
RETURNSBIGINT
BEGIN
     DECLAREvalue BIGINT;
     UPDATEsequence
     SETcurrent_value = current_value + increment 
     WHEREupper(name) = upper(seq_name);
     RETURNcurrval(seq_name); 
END;
/
  
DELIMITER ; 
  
DELIMITER /
  
DROPFUNCTION IF EXISTS setval / 
  
CREATEFUNCTION setval (seq_name VARCHAR(50), value BIGINT)
RETURNSBIGINT
BEGIN
     UPDATEsequence
     SETcurrent_value = value 
     WHEREupper(name) = upper(seq_name);
     RETURNcurrval(seq_name); 
END;
/
  
DELIMITER ;


?

 在 SQL 中使用序列:
创建序列,往sequence表插入值即可:

mysql>insertinto sequence set name='myseq';


?

查看当前已建序列:

mysql>select* fromsequence;

+-------+---------------+-----------+
| name | current_value | increment |
+-------+---------------+-----------+
| myseq |       0 |     1 |
+-------+---------------+-----------+
1 row in set (0.00 sec)


?
?

获得序列的下一个值,第一次使用,因此值为1:

mysql>selectnextval('myseq');
+------------------+
| nextval('myseq') |
+------------------+
|        1 |
+------------------+
1 row in set (0.00 sec)


?

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325479909&siteId=291194637