• mysql里的序列应用详解


    相关知识库: MySQL知识库
                                            <div id="related_topics" style="position: relative;">相关文章: <span class="close"><a href="#" onclick="$('related_topics').hide();if($('hunter_recommended')){$('hunter_recommended').style.width='780px'};if($('topic_tags')){$('topic_tags').style.width='790px'};return false;" title="关闭">&nbsp;</a></span>
              <ul>
                                  <li><a href="http://www.iteye.com/topic/186233" title="ibatis中主键的返回" target="_blank">ibatis中主键的返回</a></li>
                                  <li><a href="http://www.iteye.com/topic/1126814" title="oracle 实现自增auto_increament" target="_blank">oracle 实现自增auto_increament</a></li>
                                  <li><a href="http://www.iteye.com/topic/267" title="用oracle的trigger生成主键的时候和hibernate冲突的讨论" target="_blank">用oracle的trigger生成主键的时候和hibernate冲突的讨论</a></li>
                              </ul>
              <br><span>推荐群组: <a href="http://grails.group.iteye.com" target="_blank">Groovy on Grails </a></span>
              <br><a href="/wiki/topic/1114280" target="_blank">更多相关推荐</a>
            </div>
            <script type="text/javascript">
              document.observe("dom:loaded", function() {
                if($('hunter_recommended')) {
                  $('hunter_recommended').setStyle({cssFloat: 'left',  '557px'})
                }
                if($('topic_tags')) {
                  $('topic_tags').setStyle({ '567px'})
                }
                new Draggable("related_topics");
              });
            </script>
                          
          <div id="topic_tags" class="news_tag" style=" 567px;">
                          <a href="/forums/tag/MySQL">MySQL</a>
                          <a href="/forums/tag/%E6%95%B0%E6%8D%AE%E5%BA%93">数据库</a>
                      </div>
        
      
      提到mysql,我顺便讲讲序列。用过oracle的人都知道,orale没有类似mysql的AUTO_INCREMENT这样的自增长字段,实现插入一条记录,自动增加1.oracle是通过sequence(序列)来完成的。这样看起来,似乎mysql的自增长要比oracle序列的实现更好更方便。那我为什么还要提序列呢?有必要吗?
    


    (1)首先mysql的自增长“序列”和序列是两回事,mysql本身不提供序列机制。



    (2)mysql的AUTO_INCREMENT可以设置起始值,但是不能设置步长,其步长默认就是1.



    (3)mysql一个表只能有一个自增长字段。自增长只能被分配给固定表的固定的某一字段,不能被多个表共用。并且只能是数字型。



    (4)在历史表和数据迁移时,经常会遇到自增主键重复的问题。



    (5)自增主键往往是没意义的。

    在下列情况下可能你需要使用序列:

    (1)业务复杂,你需要高度定制和控制主键(自增主键只能是按数字递增的,但是序列可以随心所欲的变化,比如按照年月日生成主键。。。)

    (2)你希望手工维护自增长,方便数据迁移;

    (3)当事务跨多表时,期望事务可靠性;



    (4)当你需要一个业务上有意义的主键时,比如单据号等(若你需要的只是一个流水号,那么用自增更方便);



    (5)当你的主键很明确地需要和其他表关联时(若你的表不与其他表关联时,如日志表,自增更方便)



    (6)你期望这个主键是唯一的,不需要重复利用的。

        当然,序列也有缺点,主要就是程序处理麻烦,不如自增方便。oracle的自增有缓存,不用担心效率问题,而mysql只能通过触发器模拟,可能会有性能损失。



    下面,我们就来实现一下mysql中的序列。



    先建一个序列表,如下:



    Java代码  收藏代码
    1. DROP TABLE IF EXISTS sequence;  
    2.   
    3. CREATE TABLE IF NOT EXISTS sequence (  
    4.   
    5.   name varchar(50) NOT NULL,  
    6.   
    7.   current_value int(11) NOT NULL,  
    8.   
    9.   increment int(11) NOT NULL DEFAULT '1'  
    10.   
    11. ) ENGINE=MyISAM DEFAULT CHARSET=utf8 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC COMMENT='序列表,命名s_[table_name]';  
    12.   
    13. INSERT INTO sequence (namecurrent_valueincrement) VALUES  
    14.   
    15. ('s_blog_account'01)  




    name是序列的名字,current_value是序列当前值,increment是每次增长的步长。

    再来写几个函数(取当前值):



    Java代码  收藏代码
    1. DROP FUNCTION IF EXISTS currval;  
    2.   
    3. DELIMITER //  
    4.   
    5. CREATE DEFINER=TEST@% FUNCTION currval(seq_name VARCHAR(50)) RETURNS int(11)  
    6.   
    7.     READS SQL DATA  
    8.   
    9.     DETERMINISTIC  
    10.   
    11. BEGIN  
    12.   
    13. DECLARE VALUE INTEGER;  
    14.   
    15. SET VALUE = 0;  
    16.   
    17. SELECT current_value INTO VALUE FROM sequence WHERE NAME = seq_name;  
    18.   
    19. RETURN VALUE;  
    20.   
    21. END//  
    22.   
    23. DELIMITER ;  




    取下一个值:



    Java代码  收藏代码
    1. DROP FUNCTION IF EXISTS nextval;  
    2.   
    3. DELIMITER //  
    4.   
    5. CREATE DEFINER=TEST@% FUNCTION nextval(seq_name VARCHAR(50)) RETURNS int(11)  
    6.   
    7.     DETERMINISTIC  
    8.   
    9. BEGIN  
    10.   
    11. UPDATE sequence SET current_value = current_value + increment WHERE NAME = seq_name;  
    12.   
    13. RETURN currval(seq_name);  
    14.   
    15. END//  
    16.   
    17. DELIMITER ;  


        当我们需要插入时,只用加一句select nextval("s_blog_account"),然后用这个返回值作为主键,插入到对应的表中。我提到了"插入时",那么是不是我们还可以用触发器来实现呢?这个就归你有兴趣时看看了。我估计绝大部分程序员都只在使用自增主键,如果你对这个问题思考的再深一点,那么你会发现,序列很不错。目前,在我的开发中,我只在LOG表和无意义的字段中使用自增,凡是有意义的主键,我都是用的序列维护。神马?你说虚拟主机不支持mysql的这些高级特性?对不起,我从不考虑虚拟主机,也请你不要把目光局限在针对虚拟主机的开发。

  • 相关阅读:
    Virtuabox 虚拟机克隆方法
    CentOS 7 防火墙 出现Failed to start iptables.service: Unit iptables.service failed to load
    Linux系统下安装rz/sz命令及使用说明
    os、sys模块
    collections、random、hashlib、configparser、logging模块
    time、datatime模块
    正则表达式、re模块
    递归、二分查找法
    内置函数、匿名函数
    生成器进阶、生成器表达式
  • 原文地址:https://www.cnblogs.com/jobs-lgy/p/6510224.html
Copyright © 2020-2023  润新知