mysql中的序列_mysql里的序列应用详解

本文探讨了MySQL中自增主键与Oracle序列的区别,并解释了在特定情况下使用序列的必要性,如业务定制、数据迁移等。文章介绍了如何在MySQL中模拟序列,包括创建序列表、定义获取当前值和下一个值的函数,并建议在有意义的主键场景下使用序列。
摘要由CSDN通过智能技术生成

document.observe("dom:loaded", function() {

if($('hunter_recommended')) {

$('hunter_recommended').setStyle({cssFloat: 'left', width: '557px'})

}

if($('topic_tags')) {

$('topic_tags').setStyle({width: '567px'})

}

new Draggable("related_topics");

});

提到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代码  icon_star.png

spinner.gifDROP TABLE IF EXISTS sequence;

CREATE TABLE IF NOT EXISTS sequence (

name varchar(50) NOT NULL,

current_value int(11) NOT NULL,

increment int(11) NOT NULL DEFAULT'1'

) ENGINE=MyISAM DEFAULT CHARSET=utf8 CHECKSUM=1DELAY_KEY_WRITE=1ROW_FORMAT=DYNAMIC COMMENT='序列表,命名s_[table_name]';

INSERT INTO sequence (name, current_value, increment) VALUES

('s_blog_account',0,1)DROP TABLE IF EXISTS sequence;

CREATE TABLE IF NOT EXISTS sequence (

name varchar(50) NOT NULL,

current_value int(11) NOT NULL,

increment int(11) NOT NULL DEFAULT '1'

) ENGINE=MyISAM DEFAULT CHARSET=utf8 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC COMMENT='序列表,命名s_[table_name]';

INSERT INTO sequence (name, current_value, increment) VALUES

('s_blog_account', 0, 1)

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

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

Java代码  icon_star.png

spinner.gifDROP FUNCTION IF EXISTS currval;

DELIMITER //

CREATE DEFINER=TEST@% FUNCTION currval(seq_name VARCHAR(50)) RETURNSint(11)

READS SQL DATA

DETERMINISTIC

BEGIN

DECLARE VALUE INTEGER;

SET VALUE = 0;

SELECT current_value INTO VALUE FROM sequence WHERE NAME = seq_name;

RETURN VALUE;

END//

DELIMITER ;DROP FUNCTION IF EXISTS currval;

DELIMITER //

CREATE DEFINER=TEST@% FUNCTION currval(seq_name VARCHAR(50)) RETURNS int(11)

READS SQL DATA

DETERMINISTIC

BEGIN

DECLARE VALUE INTEGER;

SET VALUE = 0;

SELECT current_value INTO VALUE FROM sequence WHERE NAME = seq_name;

RETURN VALUE;

END//

DELIMITER ;

取下一个值:

Java代码  icon_star.png

spinner.gifDROP FUNCTION IF EXISTS nextval;

DELIMITER //

CREATE DEFINER=TEST@% FUNCTION nextval(seq_name VARCHAR(50)) RETURNSint(11)

DETERMINISTIC

BEGIN

UPDATE sequence SET current_value = current_value + increment WHERE NAME = seq_name;

RETURN currval(seq_name);

END//

DELIMITER ;DROP FUNCTION IF EXISTS nextval;

DELIMITER //

CREATE DEFINER=TEST@% FUNCTION nextval(seq_name VARCHAR(50)) RETURNS int(11)

DETERMINISTIC

BEGIN

UPDATE sequence SET current_value = current_value + increment WHERE NAME = seq_name;

RETURN currval(seq_name);

END//

DELIMITER ;

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值