Database JUNKY

MySQL,MariaDBを中心としたブログです

MySQL,MariaDBでタグ機能(TAG)を実現する(TOXI法)②タグデータ挿入

前回の、TOXI法による、MySQLのタグのしくみを説明しました。

hit.hateblo.jp

正規化として、これ以上ないくらいの完璧さなのですが、実際このタグ、複数のユーザーが任意に設定できるという、いわゆるソーシャルタグの場合はどうでしょう? 正規化とはうらはらに、データ登録の際は、若干面倒になってきます。 Aさんは、2016年10月というタグを作成し、全くのつながりの無い、Bさんも2016年10月というタグを作ったとしたら?レコードは二行になるの?とかとか。。

この手の若干面倒な作業は、ストアドプロシージャにすべて内包するのが私の主義です。

というわけで、例を作りつつ、ストアドプロシージャで楽ちんタグ作成について説明していきたいと思います。

f:id:hit10231023:20180309104332j:plain

前回のおさらい

前回簡単に、日記テーブルにタグをつけるなんていうのをやりました。あ、ER書いてなかったですが、イメージではこんな感じになります。

f:id:hit10231023:20161026151056j:plain

概要

  • 日記を書かないとタグは設定できない
  • タグの設定は、タグマスタになければ、新規登録、タグマスタにすでに存在すれば、そのタグidを取得する

といった流れにします。なので日記を書いて、タグを設定すれば、一気通貫で、tag_map、tagsテーブルの関連が作られるって構成ですね。

とりあえずtagsだけ考えて見る

tagを登録するストアドプロシージャを作ってみました。

DELIMITER $$

DROP PROCEDURE IF EXISTS sp_add_tags $$


CREATE PROCEDURE `sp_add_tags`(
IN _name varchar(200),
OUT _tag_id int(11),
OUT _result int(11)
) 
BEGIN

   DECLARE _not_found tinyint UNSIGNED DEFAULT 0;

   DECLARE EXIT HANDLER FOR SQLEXCEPTION
   BEGIN
     SET _result = -99;
   END;

   DECLARE CONTINUE HANDLER FOR NOT FOUND SET _not_found = 1;

   SET _result=0 ;

   SELECT id INTO _tag_id FROM tags 
   WHERE
     name = _name
   ;

   IF _not_found = 1 THEN
     INSERT INTO
         tags
       (name)
     VALUES
       (_name)
     ;

     SELECT LAST_INSERT_ID() INTO _tag_id ;
   END IF ;     

END $$

DELIMITER ;

実行確認

今回UIは一切作る気がない(いままでも作る気はないけど)ので、コンソールで動作確認してみます。

SET @name='abacus' ; CALL sp_add_tags(@name,@tag_id,@result) ; SELECT @name,@tag_id,@result ;
SET @name='abalone' ; CALL sp_add_tags(@name,@tag_id,@result) ; SELECT @name,@tag_id,@result ;
SET @name='abandonment' ; CALL sp_add_tags(@name,@tag_id,@result) ; SELECT @name,@tag_id,@result ;
SET @name='abbey' ; CALL sp_add_tags(@name,@tag_id,@result) ; SELECT @name,@tag_id,@result ;
SET @name='abbreviation' ; CALL sp_add_tags(@name,@tag_id,@result) ; SELECT @name,@tag_id,@result ;
SET @name='abdomen' ; CALL sp_add_tags(@name,@tag_id,@result) ; SELECT @name,@tag_id,@result ;
SET @name='aberration' ; CALL sp_add_tags(@name,@tag_id,@result) ; SELECT @name,@tag_id,@result ;
SET @name='ability' ; CALL sp_add_tags(@name,@tag_id,@result) ; SELECT @name,@tag_id,@result ;
SET @name='abolition' ; CALL sp_add_tags(@name,@tag_id,@result) ; SELECT @name,@tag_id,@result ;
SET @name='abomination' ; CALL sp_add_tags(@name,@tag_id,@result) ; SELECT @name,@tag_id,@result ;

登録結果

こんな感じになりました。

MariaDB [work]> SELECT * FROM tags ;
+----+---------------------+---------------------+--------------+
| id | created_at          | updated_at          | name         |
+----+---------------------+---------------------+--------------+
|  1 | 2016-10-26 16:04:02 | 2016-10-26 16:04:02 | abacus       |
|  3 | 2016-10-26 16:04:43 | 2016-10-26 16:04:43 | abalone      |
|  4 | 2016-10-26 16:04:43 | 2016-10-26 16:04:43 | abandonment  |
|  5 | 2016-10-26 16:04:43 | 2016-10-26 16:04:43 | abbey        |
|  6 | 2016-10-26 16:04:43 | 2016-10-26 16:04:43 | abbreviation |
|  7 | 2016-10-26 16:04:43 | 2016-10-26 16:04:43 | abdomen      |
|  8 | 2016-10-26 16:04:43 | 2016-10-26 16:04:43 | aberration   |
|  9 | 2016-10-26 16:04:43 | 2016-10-26 16:04:43 | ability      |
| 10 | 2016-10-26 16:04:43 | 2016-10-26 16:04:43 | abolition    |
| 11 | 2016-10-26 16:04:44 | 2016-10-26 16:04:44 | abomination  |
+----+---------------------+---------------------+--------------+
  • ちょっと余談ですが、すでにマスタに存在しているタグ名をCALLした場合はどうなるでしょうか?
SET @name='ability' ; CALL sp_add_tags(@name,@tag_id,@result) ; SELECT @name,@tag_id,@result ;
+---------+---------+---------+
| @name   | @tag_id | @result |
+---------+---------+---------+
| ability |       9 |       0 |
+---------+---------+---------+

ちゃんと、tag_id=9を持ってきてくれていますね!

  • もちろん新規の場合は、新規でtag_idを採番するはずです
SET @name='hello world' ; CALL sp_add_tags(@name,@tag_id,@result) ; SELECT @name,@tag_id,@result ;
+-------------+---------+---------+
| @name       | @tag_id | @result |
+-------------+---------+---------+
| hello world |      13 |       0 |
+-------------+---------+---------+

新規の採番をしてくれました。12番が登録されるっじゃないの???ですが、こちら単に最初の実行したストアドの記述が間違っていたからです。すみません。本来であれば12取得するはずでした

hit.hateblo.jp