MySQLのInnoDBでもPRIMARY KEYの2カラム目以降にAUTO_INCREMENTを使いたい
こんにちは、DBAのたなかです。
MyISAMエンジンには、Primary Keyの2カラム目以降にAUTO_INCREMENTを仕込んで1カラム目ごとに2カラム目をインクリメントさせる…なんて機能があります。
↑自分で書いててよくわからないですが、↓こんなやつです。
CREATE TABLE blog (
writer varchar(64) NOT NULL,
writer_seq tinyint unsigned NOT NULL AUTO_INCREMENT,
title varchar(255) NOT NULL,
post_date date NOT NULL,
PRIMARY KEY (writer, writer_seq)
) ENGINE=MyISAM;
INSERT INTO blog (writer, title, post_date) VALUES
('うつい', '「」', '2012/12/25'),
('あさい', 'slim3のプロジェクトをコマンドラインからビルド、デプロイするお話', '2012/12/27'),
('たなか', 'Galera Replicationはじめます', '2013/01/29'),
('あさい', 'Google App Engineで行動ログを記録・収集する方法', '2013/02/06'),
('あさい', '社内LT大会をやりましたというお話', '2013/05/07');
SELECT * FROM blog;
+-----------+------------+----------------------------------------------------------------------------------------------+------------+
| writer | writer_seq | title | post_date |
+-----------+------------+----------------------------------------------------------------------------------------------+------------+
| うつい | 1 | 「」 | 2012-12-25 |
| あさい | 1 | slim3のプロジェクトをコマンドラインからビルド、デプロイするお話 | 2012-12-27 |
| たなか | 1 | Galera Replicationはじめます | 2013-01-29 |
| あさい | 2 | Google App Engineで行動ログを記録・収集する方法 | 2013-02-06 |
| あさい | 3 | 社内LT大会をやりましたというお話 | 2013-05-07 |
+-----------+------------+----------------------------------------------------------------------------------------------+------------+
5 rows in set (0.00 sec)
Primary Keyが1カラム目のwriterがダブると、2カラム目のwriter_seqをインクリメントしてくれます。
(・∀・)ゞ 2時間くらい前まで知らなかったんですけどね! 脱稿した時から数えると2時間前だったんですが、大人の(?)事情で公開された時期から計算すると3ヶ月以上前ですね!
そしてInnoDBではこれができないので、MyISAMからの移行に踏ん切りのつかないプロダクトがあります。
「よーし、パパUDF書いちゃうぞー」
とか思ったんですが、よく考えるとUDF要らないですね。ストアドファンクションでいいじゃん。
CREATE TABLE blog (
writer varchar(64) NOT NULL,
writer_seq tinyint unsigned NOT NULL,
title varchar(255) NOT NULL,
post_date date NOT NULL,
PRIMARY KEY (writer, writer_seq)
) ENGINE=InnoDB;
DELIMITER //
CREATE FUNCTION incr (writer_name varchar(64)) RETURNS int unsigned READS SQL DATA SQL SECURITY INVOKER
BEGIN
DECLARE ret INT UNSIGNED;
SELECT MAX(writer_seq) + 1 FROM blog WHERE writer = writer_name INTO ret;
SELECT IFNULL(ret, 1) INTO ret;
RETURN ret;
end//
DELIMITER ;
INSERT INTO blog (writer, writer_seq, title, post_date) VALUES
('うつい', incr(writer), '「」', '2012/12/25'),
('あさい', incr(writer), 'slim3のプロジェクトをコマンドラインからビルド、デプロイするお話', '2012/12/27'),
('たなか', incr(writer), 'Galera Replicationはじめます', '2013/01/29'),
('あさい', incr(writer), 'Google App Engineで行動ログを記録・収集する方法', '2013/02/06'),
('あさい', incr(writer), '社内LT大会をやりましたというお話', '2013/05/07');
SELECT * FROM blog;
+-----------+------------+----------------------------------------------------------------------------------------------+------------+
| writer | writer_seq | title | post_date |
+-----------+------------+----------------------------------------------------------------------------------------------+------------+
| あさい | 1 | slim3のプロジェクトをコマンドラインからビルド、デプロイするお話 | 2012-12-27 |
| あさい | 2 | Google App Engineで行動ログを記録・収集する方法 | 2013-02-06 |
| あさい | 3 | 社内LT大会をやりましたというお話 | 2013-05-07 |
| うつい | 1 | 「」 | 2012-12-25 |
| たなか | 1 | Galera Replicationはじめます | 2013-01-29 |
+-----------+------------+----------------------------------------------------------------------------------------------+------------+
5 rows in set (0.00 sec)
これでごり押していくたぶん。 ごり押しバージョンアップ&InnoDB化計画進行中。