提到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中的序列。
先建一個序列表,如下:
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)
DROP FUNCTION IF EXISTS `currval`;
DELIMITER //
CREATE 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 ;
DROP FUNCTION IF EXISTS `nextval`;
DELIMITER //
CREATE 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")即可得到下一個值