前回、Java で36進数変換を書いたので、SQL で書いてみたくなった。
とりあえず、MySQLで。。しかしMySQL に ストアドFUNCTION を Oracle のように
パッケージでまとめられないのが残念です。
MySQL でシーケンスを構成する方法として1レコードのテーブルとストアド FUNCTION は、
よく見かける。以下のようなもの。。
CREATE TABLE sequence (id BIGINT UNSIGNED NOT NULL);
INSERT INTO sequence VALUES (0);
DELIMITER //
CREATE FUNCTION nextSequence() RETURNS INT
BEGIN
UPDATE sequence SET id=LAST_INSERT_ID(id+1);
RETURN LAST_INSERT_ID();
END;
//
-- 18桁の文字列
DELIMITER //
CREATE FUNCTION nextSeqcode() RETURNS CHAR(18)
BEGIN
UPDATE sequence SET id=LAST_INSERT_ID(id+1);
RETURN LPAD(CAST(LAST_INSERT_ID() AS CHAR),18,'0');
END; //
このシーケンス値を16進数では面白くないので、36進数表現での取得の
FUNCTION を書いてみた。
DELIMITER //
CREATE FUNCTION nextSeq36() RETURNS VARCHAR(11) CHARSET utf8
BEGIN
DECLARE v INT;
DECLARE t INT;
DECLARE p CHAR(1);
DECLARE c VARCHAR(11) DEFAULT '';
UPDATE sequence SET id=LAST_INSERT_ID(id+1);
SET v = LAST_INSERT_ID();
IF v = 0 THEN RETURN '0';
END IF;
WHILE v > 0 DO
SET t = MOD(v,36);
IF t <= 9 THEN SET p = CHAR(0x30 + t);
ELSE
SET p = CHAR(0x61 + (t - 10));
END IF;
SET c = CONCAT(p,c);
SET v = v DIV 36;
END WHILE;
RETURN c;
END;
//
======== '0' でパディングするなら、、、
DELIMITER //
CREATE FUNCTION nextSeq36code() RETURNS VARCHAR(12) CHARSET utf8
BEGIN
DECLARE v INT;
DECLARE t INT;
DECLARE p CHAR(1);
DECLARE c VARCHAR(11) DEFAULT '';
UPDATE sequence SET id=LAST_INSERT_ID(id+1);
SET v = LAST_INSERT_ID();
IF v = 0 THEN RETURN '0';
END IF;
WHILE v > 0 DO
SET t = MOD(v,36);
IF t <= 9 THEN SET p = CHAR(0x30 + t);
ELSE
SET p = CHAR(0x61 + (t - 10));
END IF;
SET c = CONCAT(p,c);
SET v = v DIV 36;
END WHILE;
RETURN LPAD(c,12,'0');
END;
//
iBATIS3 SQLMap を用意するなら、、
<select id="nextSeq36" resultType="string">
select nextSeq36() from dual
</select>
<select id="nextSeq36code" resultType="string">
select nextSeq36code() from dual
</select>