`

mysql使用触发器或函数实现自增序列

 
阅读更多

转自:http://foolraty.iteye.com/blog/777215

http://www.blogjava.net/Skynet/archive/2011/03/23/301847.html

http://sulong.me/2011/11/14/spring_mysql_sequence

MySQL This function has none of DETERMINISTIC, NO SQL...错误1418 的原因分析及解决方法

http://blog.csdn.net/ty_soft/article/details/6940190 

 

 

一、 单独的数据表+函数:

 如果你不想使用mysql的自动递增,但又想实现主键序列号的功能,可以使用下面的方法,通过函数用一张表去维护生成多个表的序列号,简单又实用

1.创建生成多个表的序列号的数据维护表

CREATE TABLE seq (
  name varchar(20) NOT NULL,
  val int(10) UNSIGNED NOT NULL,
  PRIMARY KEY  (name)
) ENGINE=InnoDB DEFAULT CHARSET=UTF8;

 

2.插入几条初始化数据

INSERT INTO seq VALUES('one',100);
INSERT INTO seq VALUES('two',1000);

 

3.创建函数以生成序列号

CREATE FUNCTION seq(seq_name char (20)) returns int
begin
 UPDATE seq SET val=last_insert_id(val+1) WHERE name=seq_name;
 RETURN last_insert_id();
end

 

4.测试

  1. mysql> SELECT seq('one'),seq('two'),seq('one'),seq('one');
  2. +------------+------------+------------+------------+
  3. | seq('one') | seq('two') | seq('one') | seq('one') |
  4. +------------+------------+------------+------------+
  5. |        102 |       1002 |        103 |        104 |
  6. +------------+------------+------------+------------+
  7. 1 row IN SET (0.00 sec)


 

二、触发器

 
原理是在建立一个触发器TRIGGER tri_NewBH 在table插入时执行序列计算 
mysql> CREATE TABLE tb(BH CHAR(16),content VARCHAR(20),`date` DATETIME,val INT);
Query OK, 0 rows affected (0.05 sec)

mysql>
mysql>
mysql> DELIMITER $$
mysql> DROP TRIGGER IF EXISTS tri_NewBH $$
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql>
mysql> CREATE TRIGGER tri_NewBH BEFORE INSERT ON tb
    -> FOR EACH ROW
    -> BEGIN
    ->     DECLARE dt CHAR(8);
    ->     DECLARE bh_id CHAR(16);
    ->     DECLARE number INT;
    ->     DECLARE new_bh VARCHAR(16);
    ->
    ->     SET dt = DATE_FORMAT(CURDATE(),'%Y%m%d');
    ->
    ->     SELECT
    ->         MAX(BH) INTO bh_id
    ->     FROM tb
    ->     WHERE BH LIKE CONCAT(dt,'%');
    ->
    ->     IF bh_id = '' OR bh_id IS NULL THEN
    ->         SET new_bh = CONCAT(dt,'00000001');
    ->     ELSE
    ->         SET number = RIGHT(bh_id,8) + 1;
    ->         SET new_bh =  RIGHT(CONCAT('00000000',number),8);
    ->         SET new_bh=CONCAT(dt,new_bh);
    ->     END IF;
    ->
    ->     SET NEW.BH = new_bh;
    -> END$$
Query OK, 0 rows affected (0.09 sec)

mysql>
mysql> DELIMITER ;
mysql> INSERT INTO tb(content,`date`,val) VALUES('LiangCK','2009-05-11',20);
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO tb(content,`date`,val) VALUES('LiangCK','2009-05-11',20);
Query OK, 1 row affected (0.01 sec)

mysql> INSERT INTO tb(content,`date`,val) VALUES('LiangCK','2009-05-11',20);
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO tb(content,`date`,val) VALUES('LiangCK','2009-05-11',20);
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO tb(content,`date`,val) VALUES('LiangCK','2009-05-11',20);
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO tb(content,`date`,val) VALUES('LiangCK','2009-05-11',20);
Query OK, 1 row affected (0.01 sec)

mysql> INSERT INTO tb(content,`date`,val) VALUES('LiangCK','2009-05-11',20);
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM tb;
+------------------+---------+---------------------+------+
| BH               | content | date                | val  |
+------------------+---------+---------------------+------+
| 2009051100000001 | LiangCK | 2009-05-11 00:00:00 |   20 |
| 2009051100000002 | LiangCK | 2009-05-11 00:00:00 |   20 |
| 2009051100000003 | LiangCK | 2009-05-11 00:00:00 |   20 |
| 2009051100000004 | LiangCK | 2009-05-11 00:00:00 |   20 |
| 2011051200000001 | LiangCK | 2009-05-11 00:00:00 |   20 |
| 2011051200000002 | LiangCK | 2009-05-11 00:00:00 |   20 |
| 2011051200000003 | LiangCK | 2009-05-11 00:00:00 |   20 |
+------------------+---------+---------------------+------+
7 rows in set (0.00 sec)
  

三、下面就是另外一个的实现方案: 

原理是创建一个专门记录序列的表sequence,记录有当前序列号,序列的间隔如+1

 

Sql代码   收藏代码
  1. DROP TABLE IF EXISTS sequence;/*创建记录当前序列的表*/  
  2. CREATE TABLE sequence (  
  3. name              VARCHAR(50) NOT NULL,  
  4. current_value INT NOT NULL,  
  5. increment       INT NOT NULL DEFAULT 1,  
  6. PRIMARY KEY (name)  
  7. ) ENGINE=InnoDB;  
  8. INSERT INTO sequence VALUES ('MovieSeq',3,5);  
  9. DROP FUNCTION IF EXISTS currval;  
  10. DELIMITER $/*创建一个获取当前序列的function*/  
  11. CREATE FUNCTION currval (seq_name VARCHAR(50))  
  12. RETURNS INTEGER  
  13. CONTAINS SQL  
  14. BEGIN  
  15.   DECLARE value INTEGER;  
  16.   SET value = 0;  
  17.   SELECT current_value INTO value  
  18.   FROM sequence  
  19.   WHERE name = seq_name;  
  20.   RETURN value;  
  21. END$  
  22. DELIMITER ;  

 测试一下结果:

 

 

Sql代码   收藏代码
  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 

//获取下一个数值..先在sequence里面调用update当前最大数值+1然后再调用currval获得当前数值
Sql代码   收藏代码
  1. DROP FUNCTION IF EXISTS nextval;  
  2. DELIMITER $  
  3. CREATE FUNCTION nextval (seq_name VARCHAR(50))  
  4. RETURNS INTEGER  
  5. CONTAINS SQL  
  6. BEGIN  
  7.    UPDATE sequence  
  8.    SET          current_value = current_value + increment  
  9.    WHERE name = seq_name;  
  10.    RETURN currval(seq_name);  
  11. END$  
  12. DELIMITER ;  
 mysql> select nextval('MovieSeq');
Sql代码   收藏代码
  1. +---------------------+  
  2. | nextval('MovieSeq') |  
  3. +---------------------+  
  4. |                  15 |  
  5. +---------------------+  
  6. 1 row in set (0.09 sec)  
  7.   
  8. mysql> select nextval('MovieSeq');  
  9. +---------------------+  
  10. | nextval('MovieSeq') |  
  11. +---------------------+  
  12. |                  20 |  
  13. +---------------------+  
  14. 1 row in set (0.01 sec)  
  15.   
  16. mysql> select nextval('MovieSeq');  
  17. +---------------------+  
  18. | nextval('MovieSeq') |  
  19. +---------------------+  
  20. |                  25 |  
  21. +---------------------+  
  22. 1 row in set (0.00 sec)  
 setval 
Sql代码   收藏代码
  1. DROP FUNCTION IF EXISTS setval;  
  2. DELIMITER $  
  3. CREATE FUNCTION setval (seq_name VARCHAR(50), value INTEGER)  
  4. RETURNS INTEGER  
  5. CONTAINS SQL  
  6. BEGIN  
  7.    UPDATE sequence  
  8.    SET          current_value = value  
  9.    WHERE name = seq_name;  
  10.    RETURN currval(seq_name);  
  11. END$  
  12. DELIMITER ;  
 mysql> select setval('MovieSeq',150);
Sql代码   收藏代码
  1. +------------------------+  
  2. | setval('MovieSeq',150) |  
  3. +------------------------+  
  4. |                    150 |  
  5. +------------------------+  
  6. 1 row in set (0.06 sec)  
  7.   
  8. mysql> select curval('MovieSeq');  
  9. +---------------------+  
  10. | currval('MovieSeq') |  
  11. +---------------------+  
  12. |                 150 |  
  13. +---------------------+  
  14. 1 row in set (0.00 sec)  
  15.   
  16. mysql> select nextval('MovieSeq');  
  17. +---------------------+  
  18. | nextval('MovieSeq') |  
  19. +---------------------+  
  20. |                 155 |  
  21. +---------------------+  
  22. 1 row in set (0.00 sec)  
 
分享到:
评论

相关推荐

    在MySQL中创建实现自增的序列(Sequence)的教程

    主要介绍了在MySQL中创建实现自增的序列(Sequence)的教程,分别列举了两个实例并简单讨论了一些限制因素,需要的朋友可以参考下

    事务、触发器、函数、视图、存储过程

    ​ 所谓事务,就是把多个事情按照一个事情来处理,在mysql中是用户定义的一个操作序列,这些操作要么都做,要么都不做,是一个不可分割的单位。例如,你去银行取钱,输密码、填单子、工作人员操作电脑、验钞机验钞、...

    Navicat Premium操作手册.7z

    3Oracle 外部表访问参数59Oracle 索引组织表59Oracle 索引组织表选项59Oracle 视图60Oracle 函数或过程61Oracle 数据库链接62Oracle 索引63Oracle Java65Oracle 实体化视图66Oracle 实体化视图日志68Oracle 包69...

    navicat html help

    它可以用于任何版本 3.21 或以上的 MySQL 数据库服务器,并支持大部份 MySQL 最新版本的功能,包括触发器、存储过程、函数、事件、视图、管理用户等。 Navicat for Oracle Navicat for Oracle 是一套专为 Oracle...

    Java开发实战1200例(第1卷).(清华出版.李钟尉.陈丹丹).part3

    实例033 使用while与自增运算符循环遍历 数组 43 实例034 使用for循环输出杨辉三角 43 实例035 使用嵌套循环在控制台上输出 九九乘法表 44 实例036 用while循环计算1+1/2!+1/3!…1/20! 45 实例037 for循环输出空心的...

    urlshortener:网址缩短器

    网址缩短器芬兰语简短用户指南### 文件: 一个网页(index.html),其中输入了一个长网址以进行缩写也访问数据库的服务器 (app.js) MySQL 数据库(database.sql),带有长短 url 表和 url 截断触发器函数文件 ...

    经典SQL脚本大全

    卷序列号码为 00000030 4489:1826 C:. │ sqlserver2000.txt │ ├─第01章 │ 1.9.1 设置内存选项.sql │ 1.9.2(2) 使用文件及文件组.sql │ 1.9.2(3) 调整tempdb数据库的文件属性.sql │ ├─第02章 │ │ 2.1 ...

    Hibernate注解

    * 5.identity 使用SQL Server和MySQL的自增字段,这个方法不能放到Oracle中,Oracle不支持自增字段,要设定sequence(MySQL和SQL Server中很常用)。等同于JPA中的IDENTITY * 例:@GeneratedValue(generator = ...

    asp.net知识库

    在 SQL Server 2005 中使用表值函数来实现空间数据库 SQL Server 2005的30个最重要特点 同时安装sql2000和sql2005的经验 类如何与界面绑定 在Asp.net中如何用SQLDMO来获取SQL Server中的对象信息 使用Relations建立...

    数据库知识点整理,很详细完整,适合入门或者复习。

    数据库知识点整理,包括数据库和表的创建,增删改查,子查询,关联查询,连接,交并差集,索引,序列,视图,各种函数,DDL、DML、DQL的实例。 存储过程,触发器,PL/SQL的基本使用。 每个知识点都有基于ORACLE ...

    Java面试宝典2020修订版V1.0.1.doc

    11、什么是java序列化,如何实现java序列化? 59 12、编写一个程序,将d:\java目录下的所有.java文件复制到d:\jad目录下,并将原来文件的扩展名从.java改为.jad。 60 13、java中有几种类型的流?JDK为每种类型的流...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part4

     18.3.1 使用聚集函数  18.3.2 分组查询  18.3.3 优化报表查询的性能  18.4 高级查询技巧  18.4.1 动态查询  18.4.2 集合过滤  18.4.3 子查询  18.4.4 本地SQL查询  18.4.5 查询结果转换器  18.5 查询性能...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part2

     18.3.1 使用聚集函数  18.3.2 分组查询  18.3.3 优化报表查询的性能  18.4 高级查询技巧  18.4.1 动态查询  18.4.2 集合过滤  18.4.3 子查询  18.4.4 本地SQL查询  18.4.5 查询结果转换器  18.5 查询性能...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part3

     18.3.1 使用聚集函数  18.3.2 分组查询  18.3.3 优化报表查询的性能  18.4 高级查询技巧  18.4.1 动态查询  18.4.2 集合过滤  18.4.3 子查询  18.4.4 本地SQL查询  18.4.5 查询结果转换器  18.5 查询性能...

    精通 Hibernate:Java 对象持久化技术详解(第2版).part1.rar

     18.3.1 使用聚集函数  18.3.2 分组查询  18.3.3 优化报表查询的性能  18.4 高级查询技巧  18.4.1 动态查询  18.4.2 集合过滤  18.4.3 子查询  18.4.4 本地SQL查询  18.4.5 查询结果转换器  18.5 查询性能...

Global site tag (gtag.js) - Google Analytics