0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

多対多リレーションを修正するストアドプロシージャ

Posted at

下の画像の右側と左側が多対多のテーブルのレコードで、真ん中の薬のカプセルみたいなやつが、中間テーブルのレコードとします。

具体的にいうと、左側の「LIZ」、「LITA」はアーティストで、右側の「KING」というのは楽曲です。

「KING」という2つのレコードは同じものを意図しているのにもかかわらず、IDが異なるので違うものとして扱われてしまっています。

なのでMAINを残し、SUBを消すために、以下のように中間テーブルをUPDATEしたのち、いらなくなったSUBレコードを削除します。

IMG_8042.jpg

これをするSQLは以下のようになります。

-- 左側のテーブル : artists
-- 中間テーブル : music_artists
-- 右側のテーブル : music
update music_artists set music_id = {main} where music_id = {sub};
delete from music where id = sub;

これでうまくいきそうですが、以下のような場合にうまくいきません。
UPDATEすると複合主キーの主キー制約に反するので、UPDATEできないのです。

IMG_8043.jpg

上記のパターンが

  • UPDATE → DELETE

のパターンが必要であるのに対し、今回のパターンでは

  • DELETE → DELETE

する必要があります。

IMG_8044.jpg

これを振り分けるためには、ストアドプロシージャでカーソル操作する必要があります。
MySQLです。

CREATE PROCEDURE `join_music`(main INT, sub INT)
BEGIN
  DECLARE current_artist_id INT;
  
  DECLARE done INT DEFAULT FALSE;
  
  DECLARE cur CURSOR FOR SELECT artist_id FROM music_artists WHERE music_id = sub;
  
  DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;

  OPEN cur;


  cur_loop: LOOP
    IF done THEN
      LEAVE cur_loop;
    END IF;
    
    FETCH cur INTO current_artist_id;
    
    IF EXISTS (SELECT * FROM music_artists WHERE artist_id = current_artist_id AND music_id = main) THEN
		DELETE FROM music_artists WHERE artist_id = current_artist_id AND music_id = sub;
	ELSE
		UPDATE music_artists SET music_id = main WHERE artist_id = current_artist_id AND music_id = sub;
    END IF;
  END LOOP;
  
  CLOSE cur;

  DELETE FROM music WHERE id = sub;
END

ちょっとパターンを考慮するだけでこんな複雑になるんですね。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?