列から行への更新
今度は先ほどの逆パターンを考えます。つまり、表6のように列持ちのテーブルの情報を行持ちのテーブルへ更新するのです。更新後のScoreRowsテーブルは表7のようになります。
表6 サンプルテーブル(行から列へ)
ScoreCols:列持ち
student_id (学生ID) | score_en (点数- 英) | score_nl (点数- 国) | score_mt (点数- 数) |
A001 | 100 | 58 | 90 |
B002 | 77 | 60 | |
C003 | 52 | 49 | |
D004 | 10 | 70 | 100 |
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つの列にたたみこむようなイメージを持ってもらえばわかりやすいでしょう。
演習問題
さて、それではこの「列から行への更新」に関して、演習問題を2つ出しておきましょう。前回同様、解答はサポートサイトから確認してください。
問題1. いまScoreRowsテーブルのscoreはNULLを許可していますが、この列にNOT NULL制約を付けます(初期値は全行「0」で統一)。その場合でも列から行へ変換できるUPDATE文を考えてください(ヒント:リスト8をそのまま実行すると、「C003」の社会をNULLに更新しようとしてエラーになります)。
問題2. リスト8では、もともと更新先のテーブルに存在しない「D004」は更新後のテーブルにも存在しないままでした。そこで、この生徒の情報も追加できるようなSQLを考えてください。