全商品の値段が0円に
新人の開発者が、ある商品の値段を1つだけ直すつもりでした。ところが、短い一言を書き忘れました。
表の全商品が0円になり、お昼まで、店はただで商品を売ってしまいました。
データを変えるのは簡単です。変えたいデータだけを変えるのが、技術です。
このレッスンのゴール
メモ
行を、安全に追加し、変更し、削除できる。
重要な言葉
| ことば | いみ |
|---|---|
| INSERT | 表に新しい行を足す |
| UPDATE | すでにある行の値を変える |
| DELETE | 表から行を取り除く |
| トランザクション | 全部が起こるか、全部が起こらないかの、変更のひとまとまり |
| コミット | トランザクションの変更を確定する |
| ロールバック | トランザクションの変更を取り消す |
学生が入力するセルは、このプレビューでは空白です。
店ではなく、写しで練習する
このレッスンではデータを変えます。ショップのデータは元のままにしたいので、先に写しを作ります。
次の Run で、ログインし、自分のデータベース student_depot を作り、ガーデン用品の4商品を shelf という表に写します。
やり直したいときは、何度でも最初から Run できます。
証明書を受け入れる設定
printf '[client]\nssl-verify-server-cert=0\n' > ~/.my.cnfここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
クライアント用の短い名前
alias db='mariadb -h db -u student -pstudent -t -e'ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
自分のデータベースを作る
db "CREATE DATABASE IF NOT EXISTS student_depot"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
古い写しを捨てる
db "DROP TABLE IF EXISTS student_depot.shelf"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
ガーデン用品を写す
db "CREATE TABLE student_depot.shelf AS SELECT id, name, price, stock FROM shop.products WHERE category_id = 3"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
INSERT は行を足す
INSERT INTO は、表と列を指します。VALUES は、新しい行ごとに、値を括弧で1組ずつ渡します。
値は、列と同じ順番で渡します。書かなかった列には、既定値か NULL が入ります。
キーの決まりに反すると、第1回のように、データベースは行を断ります。
軍手を1つ足す
db "INSERT INTO student_depot.shelf (id, name, price, stock) VALUES (100, 'Garden Gloves', 6.50, 25)"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
UPDATE は WHERE で行を選ぶ
UPDATE は表を指します。SET は新しい値を渡します。WHERE は、どの行かを選びます。
WHERE がないと、全部の行が変わります。
安全な習慣は3段階です。同じ WHERE の SELECT を書く。狙った行が出るか確かめる。それから SELECT を UPDATE に書き換える。
1段目: まず行を見る
db "SELECT id, name, stock FROM student_depot.shelf WHERE stock < 15 ORDER BY id"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
2段目: その行だけを変える
db "UPDATE student_depot.shelf SET stock = stock + 10 WHERE stock < 15"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
3段目: もう一度見る
db "SELECT id, name, stock FROM student_depot.shelf ORDER BY id"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
DELETE は行を完全に消す
DELETE FROM は、WHERE に合う行を取り除きます。WHERE がないと、表が空になります。
ごみ箱はありません。同じ3段階を守ります。先に SELECT、次に DELETE、最後にもう一度 SELECT です。
軍手を取り除く
db "DELETE FROM student_depot.shelf WHERE id = 100"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
よくある間違い
注意
UPDATE や DELETE は、頭に描いた1行だけを変えると思いがちです。実際には、合う行をすべて変えます。WHERE がなければ全部です。先に WHERE を書き、SELECT で確かめましょう。
間違いを、写しの上だけで
db "UPDATE student_depot.shelf SET stock = 0"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
何が起きたか見る
db "SELECT id, name, stock FROM student_depot.shelf ORDER BY id"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
トランザクションは全部かゼロ
2つの口座の間で5万円を動かすには、変更が2つ要ります。途中で機械が止まると、5万円が消えます。
トランザクションは、変更をひとまとめにします。COMMIT で全部を確定し、ROLLBACK で全部を取り消します。
コミットするまで、ほかの人には変更が見えません。次の Run は、1つのセッションで4つの文を送ります。トランザクションを始め、写しの行を全部消し、ロールバックしてから数えます。
全部消して、ロールバックする
db "START TRANSACTION; DELETE FROM student_depot.shelf; ROLLBACK; SELECT COUNT(*) AS still_there FROM student_depot.shelf"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
例: 途中で止まったら
| 段階 | 口座1 | 口座2 | トランザクションなし | トランザクションあり |
|---|---|---|---|---|
| 最初 | 20万円 | 10万円 | 問題なし | 問題なし |
| 1つ目の変更の後 | 15万円 | 10万円 | 5万円が消えている | まだ確定していない |
| ここで停止 | 15万円 | 10万円 | おかしいまま | 元の20万円と10万円に戻る |
| 2つの変更と COMMIT | 15万円 | 15万円 | 問題なし | 問題なし |
学生が入力するセルは、このプレビューでは空白です。
標準の動き方を見る
db "SELECT @@autocommit AS autocommit"ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。
答えが1になる理由
メモ
普通は、1つの文がそれぞれ小さなトランザクションで、すぐ確定されます。だから単独の UPDATE は取り消せません。ロールバックしたいなら、同じセッションの中で、先に START TRANSACTION を実行します。