Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

of

削除フラグのはなし Slide 1 削除フラグのはなし Slide 2 削除フラグのはなし Slide 3 削除フラグのはなし Slide 4 削除フラグのはなし Slide 5 削除フラグのはなし Slide 6 削除フラグのはなし Slide 7 削除フラグのはなし Slide 8 削除フラグのはなし Slide 9 削除フラグのはなし Slide 10 削除フラグのはなし Slide 11 削除フラグのはなし Slide 12 削除フラグのはなし Slide 13 削除フラグのはなし Slide 14 削除フラグのはなし Slide 15 削除フラグのはなし Slide 16 削除フラグのはなし Slide 17 削除フラグのはなし Slide 18 削除フラグのはなし Slide 19 削除フラグのはなし Slide 20 削除フラグのはなし Slide 21 削除フラグのはなし Slide 22 削除フラグのはなし Slide 23 削除フラグのはなし Slide 24 削除フラグのはなし Slide 25 削除フラグのはなし Slide 26 削除フラグのはなし Slide 27 削除フラグのはなし Slide 28 削除フラグのはなし Slide 29 削除フラグのはなし Slide 30 削除フラグのはなし Slide 31 削除フラグのはなし Slide 32 削除フラグのはなし Slide 33 削除フラグのはなし Slide 34 削除フラグのはなし Slide 35 削除フラグのはなし Slide 36 削除フラグのはなし Slide 37 削除フラグのはなし Slide 38 削除フラグのはなし Slide 39 削除フラグのはなし Slide 40 削除フラグのはなし Slide 41 削除フラグのはなし Slide 42 削除フラグのはなし Slide 43 削除フラグのはなし Slide 44 削除フラグのはなし Slide 45 削除フラグのはなし Slide 46 削除フラグのはなし Slide 47 削除フラグのはなし Slide 48 削除フラグのはなし Slide 49 削除フラグのはなし Slide 50 削除フラグのはなし Slide 51 削除フラグのはなし Slide 52 削除フラグのはなし Slide 53 削除フラグのはなし Slide 54 削除フラグのはなし Slide 55 削除フラグのはなし Slide 56 削除フラグのはなし Slide 57 削除フラグのはなし Slide 58 削除フラグのはなし Slide 59 削除フラグのはなし Slide 60 削除フラグのはなし Slide 61 削除フラグのはなし Slide 62 削除フラグのはなし Slide 63 削除フラグのはなし Slide 64 削除フラグのはなし Slide 65 削除フラグのはなし Slide 66 削除フラグのはなし Slide 67 削除フラグのはなし Slide 68 削除フラグのはなし Slide 69 削除フラグのはなし Slide 70 削除フラグのはなし Slide 71 削除フラグのはなし Slide 72 削除フラグのはなし Slide 73 削除フラグのはなし Slide 74 削除フラグのはなし Slide 75 削除フラグのはなし Slide 76 削除フラグのはなし Slide 77 削除フラグのはなし Slide 78 削除フラグのはなし Slide 79 削除フラグのはなし Slide 80 削除フラグのはなし Slide 81 削除フラグのはなし Slide 82 削除フラグのはなし Slide 83
Upcoming SlideShare
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
Next
Download to read offline and view in fullscreen.

99 Likes

Share

Download to read offline

削除フラグのはなし

Download to read offline

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all

削除フラグのはなし

  1. 1. id name pass is_deleted 1 ryu xxx FALSE 2 ken xxx FALSE 3 honda xxx TRUE
  2. 2. id name pass is_deleted 1 ryu xxx FALSE 2 ken xxx FALSE 3 honda xxx TRUE 3 honda xxx FALSE
  3. 3. WHERE is_deleted = false WHERE is_deleted = false WHERE is_deleted = false
  4. 4. DELETE FROM users WHERE id = 2; UPDATE user SET is_update = true WHERE id = 2;
  5. 5. id name pass is_deleted 1 ryu xxx TRUE 2 ryu xxx TRUE 3 ryu xxx FALSE 4 ryu xxx FALSE
  6. 6. id name pass is_deleted 1 ryu xxx TRUE 2 ryu xxx TRUE 3 ryu xxx FALSE 4 ryu xxx FALSE
  7. 7. -- CREATE TABLE users ( id SERIAL PRIMARY KEY, name TEXT, pass TEXT, is_deleted BOOL DEFAULT false ); -- CREATE UNIQUE INDEX users_valid_constraint ON users (name) WHERE NOT is_deleted;
  8. 8. -- テーブルを作成する CREATE TABLE users ( id SERIAL PRIMARY KEY, name TEXT, pass TEXT, is_deleted BOOL DEFAULT false ); -- 一意な部分インデックスを張る CREATE UNIQUE INDEX users_valid_constraint ON users (name) WHERE NOT is_deleted;
  9. 9. -- ryuを登録する testdb=# INSERT INTO users (name, pass, is_deleted) testdb-# VALUES ('ryu', 'xxx', false); INSERT 0 1 -- 登録したデータを確認 testdb=# SELECT * FROM users; id | name | pass | is_deleted ----+------+------+------------ 1 | ryu | xxx | f (1 row)
  10. 10. -- 更にもう一件重複するryuを登録する testdb=# INSERT INTO users (name, pass, is_deleted) testdb-# VALUES ('ryu', 'xxx', false); ERROR: duplicate key value violates unique constraint "users_valid_constraint" DETAIL: Key (name)=(ryu) already exists.
  11. 11. -- 削除フラグを立ててryuを削除したことにする testdb=# UPDATE users SET is_deleted = true testdb-# WHERE id = 1; UPDATE 1 -- ryuが論理削除されたことを確認 testdb=# SELECT * FROM users; id | name | pass | is_deleted ----+------+------+------------ 1 | ryu | xxx | t (1 row)
  12. 12. -- ryuは削除されているのでryuを登録する testdb=# INSERT INTO users (name, pass, is_deleted) testdb-# VALUES ('ryu', 'xxx', false); INSERT 0 1 -- 登録したデータを確認する testdb=# SELECT * FROM users; id | name | pass | is_deleted ----+------+------+------------ 1 | ryu | xxx | t 3 | ryu | xxx | f (2 rows)
  13. 13. -- 削除フラグを戻して削除したryuを復活させる testdb=# UPDATE users SET is_deleted = false testdb-# WHERE id = 1; ERROR: duplicate key value violates unique constraint "users_valid_constraint" DETAIL: Key (name)=(ryu) already exists.
  14. 14. -- 現在のデータを確認する testdb=# SELECT * FROM users; id | name | pass | is_deleted ----+------+------+------------ 1 | ryu | xxx | t 3 | ryu | xxx | f (2 rows) -- 削除されていない方のryuを論理削除する testdb=# UPDATE users SET is_deleted = true testdb-# WHERE id = 3; -- 論理削除されたryuは2件あることを確認 testdb=# SELECT * FROM users; id | name | pass | is_deleted ----+------+------+------------ 1 | ryu | xxx | t 3 | ryu | xxx | t (2 rows)
  15. 15. ☓☓
  16. 16. ☓☓
  17. 17. -- ユーザテーブルを作成する -- エントリーテーブルを作成する CREATE TABLE users ( CREATE TABLE entries ( user_id SERIAL NOT NULL, entry_id SERIAL NOT NULL, name TEXT, user_id INTEGER NOT NULL, pass TEXT, event_id INTEGER NOT NULL, PRIMARY KEY(user_id) stat TEXT NOT NULL, ); message TEXT, PRIMARY KEY(entry_id), -- イベントテーブルを作成する FOREIGN KEY(user_id) CREATE TABLE events ( REFERENCES users(user_id) event_id SERIAL NOT NULL, ON DELETE CASCADE user_id INTEGER NOT NULL, ON UPDATE CASCADE, name TEXT, FOREIGN KEY(event_id) PRIMARY KEY(event_id), REFERENCES events(event_id) FOREIGN KEY(user_id) ON DELETE CASCADE REFERENCES users(user_id) ON UPDATE CASCADE, ON DELETE CASCADE UNIQUE(user_id, event_id) ON UPDATE CASCADE ); );
  18. 18. -- 一意な部分インデックスを張る(IDを利用) CREATE UNIQUE INDEX users_valid_constraint ON users (name) WHERE 0 < user_id;
  19. 19. -- テストデータを投入する INSERT INTO users (name, pass) VALUES ('ryu', 'xxx'); INSERT INTO users (name, pass) VALUES ('ken', 'xxx'); INSERT INTO events (user_id, name) VALUES (1, '〇〇勉強会'); INSERT INTO events (user_id, name) VALUES (1, '××勉強会'); INSERT INTO events (user_id, name) VALUES (2, '△△勉強会'); INSERT INTO entries (event_id, user_id, stat, message) VALUES (1, 1, '参加', 'いち'); INSERT INTO entries (event_id, user_id, stat, message) VALUES (1, 2, '参加', '参加します'); INSERT INTO entries (event_id, user_id, stat, message) VALUES (2, 1, 'キャンセル', 'ごめんね'); INSERT INTO entries (event_id, user_id, stat, message) VALUES (2, 2, '参加', 'にばん'); INSERT INTO entries (event_id, user_id, stat, message) VALUES (3, 2, '参加', 'よろしく');
  20. 20. -- テストデータを確認する testdb=# SELECT * FROM users; user_id | name | pass ---------+------+------ 1 | ryu | xxx 2 | ken | xxx (2 rows) testdb=# SELECT * FROM events; event_id | user_id | name ----------+---------+------------ 1 | 1 | 〇〇勉強会 2 | 1 | ××勉強会 3 | 2 | △△勉強会 (3 rows) testdb=# SELECT * FROM entries;; entry_id | user_id | event_id | stat | message ----------+---------+----------+------------+------------ 1 | 1 | 1 | 参加 | いち 2 | 2 | 1 | 参加 | 参加します 3 | 1 | 2 | キャンセル | ごめんね 4 | 2 | 2 | 参加 | にばん 5 | 2 | 3 | 参加 | よろしく (5 rows)
  21. 21. -- イベントを論理削除する UPDATE events SET event_id = event_id * -1 WHERE event_id = 1;
  22. 22. -- 参照しているテーブルを確認する testdb=# SELECT * FROM users; user_id | name | pass ---------+------+------ 1 | ryu | xxx 2 | ken | xxx (2 rows) testdb=# SELECT * FROM events; event_id | user_id | name ----------+---------+------------ 2 | 1 | ××勉強会 3 | 2 | △△勉強会 -1 | 1 | 〇〇勉強会 (3 rows) testdb=# SELECT * FROM entries; entry_id | user_id | event_id | stat | message ----------+---------+----------+------------+------------ 3 | 1 | 2 | キャンセル | ごめんね 4 | 2 | 2 | 参加 | にばん 5 | 2 | 3 | 参加 | よろしく 1 | 1 | -1 | 参加 | いち 2 | 2 | -1 | 参加 | 参加します (5 rows)
  23. 23. -- ユーザを論理削除する UPDATE users SET user_id = user_id * -1 WHERE user_id = 2;
  24. 24. -- 参照しているテーブルを確認する testdb=# SELECT * FROM users; user_id | name | pass ---------+------+------ 1 | ryu | xxx -2 | ken | xxx (2 rows) testdb=# SELECT * FROM events; event_id | user_id | name ----------+---------+------------ 2 | 1 | ××勉強会 -1 | 1 | 〇〇勉強会 3 | -2 | △△勉強会 (3 rows) testdb=# SELECT * FROM entries; entry_id | user_id | event_id | stat | message ----------+---------+----------+------------+------------ 3 | 1 | 2 | キャンセル | ごめんね 1 | 1 | -1 | 参加 | いち 4 | -2 | 2 | 参加 | にばん 5 | -2 | 3 | 参加 | よろしく 2 | -2 | -1 | 参加 | 参加します (5 rows)
  25. 25. -- ちなみに、物理削除するとON DELETE CASCADEで連鎖削除される testdb=# DELETE FROM users WHERE user_id = 1; DELETE 1 testdb=# SELECT * FROM users; user_id | name | pass ---------+------+------ -2 | ken | xxx (1 row) testdb=# SELECT * FROM events; event_id | user_id | name ----------+---------+---------- 3 | -2 | △△勉強会 (1 row) testdb=# SELECT * FROM entries; entry_id | user_id | event_id | stat | message ----------+---------+----------+------+---------- 5 | -2 | 3 | 参加 | よろしく (1 row)
  26. 26. -- ユーザテーブルを作成する -- エントリーテーブルを作成する CREATE TABLE users ( CREATE TABLE entries ( user_id SERIAL NOT NULL, entry_id SERIAL NOT NULL, name TEXT, user_id INTEGER NOT NULL, pass TEXT, event_id INTEGER NOT NULL, PRIMARY KEY(user_id) stat TEXT NOT NULL, ); message TEXT, PRIMARY KEY(entry_id), -- イベントテーブルを作成する FOREIGN KEY(user_id) CREATE TABLE events ( REFERENCES users(user_id) event_id SERIAL NOT NULL, ON DELETE CASCADE user_id INTEGER NOT NULL, ON UPDATE CASCADE, name TEXT, FOREIGN KEY(event_id) PRIMARY KEY(event_id), REFERENCES events(event_id) FOREIGN KEY(user_id) ON DELETE CASCADE REFERENCES users(user_id) ON UPDATE CASCADE, ON DELETE CASCADE UNIQUE(user_id, event_id) ON UPDATE CASCADE ); );
  27. 27. -- 部分インデックスではなくユニークになる CREATE UNIQUE INDEX unq_users_name ON users (name);
  28. 28. -- 削除されたユーザの保存先を作成する CREATE TABLE deleted_users ( user_id SERIAL NOT NULL, name TEXT, pass TEXT ); -- 削除されたイベントの保存先を作成する CREATE TABLE deleted_events ( event_id SERIAL NOT NULL, user_id INTEGER NOT NULL, name TEXT ); -- 削除されたエントリの保存先を作成する CREATE TABLE deleted_entries ( entry_id SERIAL NOT NULL, user_id INTEGER NOT NULL, event_id INTEGER NOT NULL, stat TEXT NOT NULL, message TEXT );
  29. 29. -- DELETE実行時に実行するFUNCTIONを定義する CREATE OR REPLACE FUNCTION process_deleted() RETURNS TRIGGER AS $$ BEGIN IF (TG_OP = 'DELETE') THEN EXECUTE 'INSERT INTO deleted_' || TG_RELNAME || ' VALUES(($1).*)' USING OLD; RETURN OLD; END IF; RETURN NULL; END; $$ LANGUAGE plpgsql;
  30. 30. -- DELETE時に実行するTRIGGERを仕掛ける CREATE TRIGGER trigger_users_deleted AFTER DELETE ON users FOR EACH ROW EXECUTE PROCEDURE process_deleted(); CREATE TRIGGER trigger_events_deleted AFTER DELETE ON events FOR EACH ROW EXECUTE PROCEDURE process_deleted(); CREATE TRIGGER trigger_entries_deleted AFTER DELETE ON entries FOR EACH ROW EXECUTE PROCEDURE process_deleted();
  31. 31. -- テストデータを投入する INSERT INTO users (name, pass) VALUES ('ryu', 'xxx'); INSERT INTO users (name, pass) VALUES ('ken', 'xxx'); INSERT INTO events (user_id, name) VALUES (1, '〇〇勉強会'); INSERT INTO events (user_id, name) VALUES (1, '××勉強会'); INSERT INTO events (user_id, name) VALUES (2, '△△勉強会'); INSERT INTO entries (event_id, user_id, stat, message) VALUES (1, 1, '参加', 'いち'); INSERT INTO entries (event_id, user_id, stat, message) VALUES (1, 2, '参加', '参加します'); INSERT INTO entries (event_id, user_id, stat, message) VALUES (2, 1, 'キャンセル', 'ごめんね'); INSERT INTO entries (event_id, user_id, stat, message) VALUES (2, 2, '参加', 'にばん'); INSERT INTO entries (event_id, user_id, stat, message) VALUES (3, 2, '参加', 'よろしく');
  32. 32. -- テストデータを確認する testdb=# SELECT * FROM users; user_id | name | pass ---------+------+------ 1 | ryu | xxx 2 | ken | xxx (2 rows) testdb=# SELECT * FROM events; event_id | user_id | name ----------+---------+------------ 1 | 1 | 〇〇勉強会 2 | 1 | ××勉強会 3 | 2 | △△勉強会 (3 rows) testdb=# SELECT * FROM entries;; entry_id | user_id | event_id | stat | message ----------+---------+----------+------------+------------ 1 | 1 | 1 | 参加 | いち 2 | 2 | 1 | 参加 | 参加します 3 | 1 | 2 | キャンセル | ごめんね 4 | 2 | 2 | 参加 | にばん 5 | 2 | 3 | 参加 | よろしく (5 rows)
  33. 33. -- 削除されたデータの保存先は空 testdb=# SELECT * FROM deleted_users; user_id | name | pass ---------+------+------ (0 rows) testdb=# SELECT * FROM deleted_events; event_id | user_id | name ----------+---------+------ (0 rows) testdb=# SELECT * FROM deleted_entries; entry_id | user_id | event_id | stat | message ----------+---------+----------+------+--------- (0 rows)
  34. 34. -- ユーザを削除してみる DELETE FROM users WHERE user_id = 1;
  35. 35. -- 他の関連するレコードも連鎖的に削除されている testdb2=# SELECT * FROM users; user_id | name | pass ---------+------+------ 2 | ken | xxx (1 row) testdb2=# SELECT * FROM events; event_id | user_id | name ----------+---------+---------- 3 | 2 | △△勉強会 (1 row) testdb2=# SELECT * FROM entries; entry_id | user_id | event_id | stat | message ----------+---------+----------+------+---------- 5 | 2 | 3 | 参加 | よろしく (1 row)
  36. 36. -- 連鎖的に削除されたレコードは保存用のテーブルに退避されている testdb2=# SELECT * FROM deleted_users; user_id | name | pass ---------+------+------ 1 | ryu | xxx (1 row) testdb2=# SELECT * FROM deleted_events; event_id | user_id | name ----------+---------+------------ 1 | 1 | 〇〇勉強会 2 | 1 | ××勉強会 (2 rows) testdb2=# SELECT * FROM deleted_entries; entry_id | user_id | event_id | stat | message ----------+---------+----------+------------+------------ 1 | 1 | 1 | 参加 | いち 3 | 1 | 2 | キャンセル | ごめんね 2 | 2 | 1 | 参加 | 参加します 4 | 2 | 2 | 参加 | にばん (4 rows)
  37. 37. CREATE TABLE emp ( empname text NOT NULL, salary integer ); CREATE TABLE emp_audit( operation char(1) NOT NULL, stamp timestamp NOT NULL, userid text NOT NULL, empname text NOT NULL, salary integer ); CREATE OR REPLACE FUNCTION process_emp_audit() RETURNS TRIGGER AS $emp_audit$ BEGIN -- -- Create a row in emp_audit to reflect the operation performed on emp, -- make use of the special variable TG_OP to work out the operation. -- IF (TG_OP = 'DELETE') THEN INSERT INTO emp_audit SELECT 'D', now(), user, OLD.*; RETURN OLD; ELSIF (TG_OP = 'UPDATE') THEN INSERT INTO emp_audit SELECT 'U', now(), user, NEW.*; RETURN NEW; ELSIF (TG_OP = 'INSERT') THEN INSERT INTO emp_audit SELECT 'I', now(), user, NEW.*; RETURN NEW; END IF; RETURN NULL; -- result is ignored since this is an AFTER trigger END; $emp_audit$ LANGUAGE plpgsql; CREATE TRIGGER emp_audit AFTER INSERT OR UPDATE OR DELETE ON emp FOR EACH ROW EXECUTE PROCEDURE process_emp_audit();
  • uokada

    Feb. 12, 2019
  • dcomrpc

    Nov. 16, 2018
  • MilanBiswakarma

    Jun. 7, 2017
  • HidekiTanaka9

    Dec. 19, 2016
  • clicktx

    Sep. 12, 2016
  • nymnymhakase

    Aug. 4, 2016
  • RyoMurakami

    Aug. 3, 2016
  • ShuichiOhkubo

    Dec. 19, 2015
  • AsakoOmura

    Oct. 23, 2015
  • TakehiroHagiwara1

    Sep. 28, 2015
  • mitsuhirokoga75

    Sep. 28, 2015
  • hashikiikuwow

    Sep. 25, 2015
  • nakashin360

    May. 11, 2015
  • yugmix

    Mar. 25, 2015
  • hiro_ist

    Mar. 23, 2015
  • shiraco

    Jan. 16, 2015
  • satoryu

    Oct. 19, 2014
  • hsbt

    Oct. 17, 2014
  • tomochika1985

    Oct. 16, 2014
  • hisomura

    Sep. 2, 2014

Views

Total views

45,795

On Slideshare

0

From embeds

0

Number of embeds

1,278

Actions

Downloads

221

Shares

0

Comments

0

Likes

99

×