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
1 2 DECLARE @NameID INT; 3 DECLARE crTriggerList CURSOR 4 FOR 5 SELECT [氏名ID] 6 FROM テーブルA 7 8 OPEN crTriggerList; 9 10 FETCH NEXT FROM crTriggerList 11 INTO @NameID 12 13 WHILE @@FETCH_STATUS = 0 14 BEGIN 15 DECLARE @Address1 INT --住所1 16 DECLARE @Address2 INT --住所2 17 DECLARE @Address3 INT --住所3 18 19 SELECT 20 @Address1 = 住所1 21 ,@Address2 = 住所2 22 ,@Address3 = 住所3 23 FROM テーブルA 24 WHERE 氏名ID = @NameID --氏名IDに紐づく住所を変数に代入 25 26 27 IF((@Address1 IS NOT NULL) --住所1がNULLでなければ住所IDを1として移行 28 BEGIN 29 INSERT INTO テーブルB 30 (氏名ID,住所ID,住所) 31 SELECT 32 氏名ID 33 ,'1' 34 ,住所1 35 FROM テーブルA 36 WHERE 氏名ID = @NameID 37 END 38 39 IF((@Address2 IS NOT NULL) --住所2がNULLでなければ住所IDを2として移行 40 BEGIN 41 INSERT INTO テーブルB 42 (氏名ID,住所ID,住所) 43 SELECT 44 氏名ID 45 ,'2' 46 ,住所2 47 FROM テーブルA 48 WHERE 氏名ID = @NameID 49 END 50 51 IF((@Address3 IS NOT NULL) --住所3がNULLでなければ住所IDを3として移行 52 BEGIN 53 INSERT INTO テーブルB 54 (氏名ID,住所ID,住所) 55 SELECT 56 氏名ID 57 ,'3' 58 ,住所3 59 FROM テーブルA 60 WHERE 氏名ID = @NameID 61 END 62 63 64 FETCH NEXT FROM crTriggerList 65 INTO @NameID 66 67 END 68 69 CLOSE crTriggerList; 70 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)
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。