36進数でシーケンス値を参照すればよいかも

前回、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>