SQLアタマアカデミー

第2回更新なんてこわくない! (3)列から行への更新

列から行への更新

今度は先ほどの逆パターンを考えます。つまり、表6のように列持ちのテーブルの情報を行持ちのテーブルへ更新するのです。更新後のScoreRowsテーブルは表7のようになります。

表6 サンプルテーブル(行から列へ)
ScoreCols:列持ち
student_id
(学生ID)
score_en
(点数- 英)
score_nl
(点数- 国)
score_mt
(点数- 数)
A0011005890
B0027760 
C0035249 
D0041070100

ScoreRows:行持ち
student_id
(学生ID)
subject
(教科)
score
(点数)
A001英語 
A001国語 
A001数学 
B002英語 
B002国語 
C001英語 
C003国語 
C003社会 
表7  ScoreRows:行持ち(更新後)
student_id
(学生ID)
subject
(教科)
score
(点数)
A001英語100
A001国語58
A001数学98
B002英語77
B002国語60
C001英語52
C003国語49
C003社会 

「C003」の社会の情報はScoreColsテーブルにありませんので、NULLのままです。また「C004」は更新先のScoreRowsテーブルにいないので、更新しても現れません。

今度は、各生徒について更新対象となる行を、subjectの値によって分岐させることになります。したがって、SET句のサブクエリ内で次のようにCASE式を使った分岐を行えばOKですリスト8⁠。score_en、score_nl、score_mtという3つの列を1つの列にたたみこむようなイメージを持ってもらえばわかりやすいでしょう。

リスト8 列→行の更新SQL
UPDATE ScoreRows
   SET score = (SELECT CASE ScoreRows.subject
                            WHEN '英語' THEN score_en
                            WHEN '国語' THEN score_nl
                            WHEN '数学' THEN score_mt
                            ELSE NULL
                        END
                  FROM ScoreCols
                  WHERE student_id = ScoreRows.student_id);

演習問題

さて、それではこの「列から行への更新」に関して、演習問題を2つ出しておきましょう。前回同様、解答はサポートサイトから確認してください。

問題1. いまScoreRowsテーブルのscoreはNULLを許可していますが、この列にNOT NULL制約を付けます(初期値は全行「0」で統一⁠⁠。その場合でも列から行へ変換できるUPDATE文を考えてください(ヒント:リスト8をそのまま実行すると、⁠C003」の社会をNULLに更新しようとしてエラーになります⁠⁠。

問題2. リスト8では、もともと更新先のテーブルに存在しない「D004」は更新後のテーブルにも存在しないままでした。そこで、この生徒の情報も追加できるようなSQLを考えてください。

おすすめ記事

記事・ニュース一覧