SQLアンチパターンの1つであるマルチカラムアトリビュートを解決するためにテーブルを作り直してデータを移行する場合、カーソル処理以外だとどのような移行方法がありますでしょうか。
実現したいこと
以下のテーブルAを、テーブルBに作り直すとします。
テーブルA
氏名ID | 住所1 | 住所2 | 住所3 |
---|---|---|---|
0001 | A県 | B市 | C町 |
0002 | D県 | E郡 | NULL |
テーブルB
氏名ID | 住所ID | 住所 |
---|---|---|
0001 | 1 | A県 |
0001 | 2 | B市 |
0001 | 3 | C町 |
0002 | 1 | D県 |
0002 | 2 | E郡 |
※NULLのデータは移行しない
該当のソースコード
移行するためのSQLを実装するとき、1番最初に思い付いたのは以下のようなカーソル処理での場合分けですが、
1万件以上のデータを扱うと処理が極端に重くなってしまいます。
SQLServer
DECLARE @NameID INT; DECLARE crTriggerList CURSOR FOR SELECT [氏名ID] FROM テーブルA OPEN crTriggerList; FETCH NEXT FROM crTriggerList INTO @NameID WHILE @@FETCH_STATUS = 0 BEGIN DECLARE @Address1 INT --住所1 DECLARE @Address2 INT --住所2 DECLARE @Address3 INT --住所3 SELECT @Address1 = 住所1 ,@Address2 = 住所2 ,@Address3 = 住所3 FROM テーブルA WHERE 氏名ID = @NameID --氏名IDに紐づく住所を変数に代入 IF((@Address1 IS NOT NULL) --住所1がNULLでなければ住所IDを1として移行 BEGIN INSERT INTO テーブルB (氏名ID,住所ID,住所) SELECT 氏名ID ,'1' ,住所1 FROM テーブルA WHERE 氏名ID = @NameID END IF((@Address2 IS NOT NULL) --住所2がNULLでなければ住所IDを2として移行 BEGIN INSERT INTO テーブルB (氏名ID,住所ID,住所) SELECT 氏名ID ,'2' ,住所2 FROM テーブルA WHERE 氏名ID = @NameID END IF((@Address3 IS NOT NULL) --住所3がNULLでなければ住所IDを3として移行 BEGIN INSERT INTO テーブルB (氏名ID,住所ID,住所) SELECT 氏名ID ,'3' ,住所3 FROM テーブルA WHERE 氏名ID = @NameID END FETCH NEXT FROM crTriggerList INTO @NameID END CLOSE crTriggerList; DEALLOCATE crTriggerList;
カーソル処理を使わずにこのような移行が出来る方法がもしあるのであれば、教えていただきたいです。
よろしくお願いします。
補足情報(FW/ツールのバージョンなど)
Microsoft SQL Server Management Studio 18
Microsoft SQL Server 2019 (RTM-GDR) (KB4583458) - 15.0.2080.9 (X64) Nov 6 2020 16:50:01 Copyright (C) 2019 Microsoft Corporation Enterprise Edition (64-bit) on Windows Server 2019 Datacenter 10.0 <X64> (Build 17763: ) (Hypervisor)
まだ回答がついていません
会員登録して回答してみよう