SlideShare ist ein Scribd-Unternehmen logo
1 von 83
Downloaden Sie, um offline zu lesen
id   name    pass   is_deleted
1     ryu    xxx     FALSE
2     ken    xxx     FALSE
3    honda   xxx      TRUE
id   name    pass   is_deleted
1     ryu    xxx     FALSE
2     ken    xxx     FALSE
3    honda   xxx      TRUE



3    honda   xxx     FALSE
WHERE is_deleted = false
WHERE is_deleted = false
WHERE is_deleted = false
DELETE FROM users WHERE id = 2;
UPDATE user SET is_update = true WHERE id = 2;
id   name   pass   is_deleted
1    ryu    xxx      TRUE
2    ryu    xxx      TRUE
3    ryu    xxx     FALSE
4    ryu    xxx     FALSE
id   name   pass   is_deleted
1    ryu    xxx      TRUE
2    ryu    xxx      TRUE
3    ryu    xxx     FALSE
4    ryu    xxx     FALSE
--
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;
--	 テーブルを作成する
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;
--	 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)
--	 更にもう一件重複する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.
--	 削除フラグを立てて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)
--	 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)
--	 削除フラグを戻して削除した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.
--	 現在のデータを確認する
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)
☓☓
☓☓
--	 ユーザテーブルを作成する                     --	 エントリーテーブルを作成する
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      );
);
--	 一意な部分インデックスを張る(IDを利用)
CREATE	 UNIQUE	 INDEX	 users_valid_constraint
	 	 	 	 ON	 users	 (name)	 WHERE	 0	 <	 user_id;
--	 テストデータを投入する
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,	 '参加',	 'よろしく');
--	 テストデータを確認する
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)
--	 イベントを論理削除する
UPDATE	 events	 SET	 event_id	 =	 event_id	 *	 -1	 WHERE	 event_id	 =	 1;
--	 参照しているテーブルを確認する
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)
--	 ユーザを論理削除する
UPDATE	 users	 SET	 user_id	 =	 user_id	 *	 -1	 WHERE	 user_id	 =	 2;
--	 参照しているテーブルを確認する
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)
--	 ちなみに、物理削除すると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)
--	 ユーザテーブルを作成する                     --	 エントリーテーブルを作成する
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      );
);
--	 部分インデックスではなくユニークになる
CREATE	 UNIQUE	 INDEX	 unq_users_name	 ON	 users	 (name);
--	 削除されたユーザの保存先を作成する
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
);
--	 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;
--	 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();
--	 テストデータを投入する
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,	 '参加',	 'よろしく');
--	 テストデータを確認する
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)
--	 削除されたデータの保存先は空
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)
--	 ユーザを削除してみる
DELETE	 FROM	 users	 WHERE	 user_id	 =	 1;
--	 他の関連するレコードも連鎖的に削除されている
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)
--	 連鎖的に削除されたレコードは保存用のテーブルに退避されている
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)
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();

Weitere ähnliche Inhalte

Was ist angesagt?

金勘定のためのBigDecimalそしてMoney and Currency API
金勘定のためのBigDecimalそしてMoney and Currency API金勘定のためのBigDecimalそしてMoney and Currency API
金勘定のためのBigDecimalそしてMoney and Currency APITaku Miyakawa
 
MySQL 8.0で憶えておいてほしいこと
MySQL 8.0で憶えておいてほしいことMySQL 8.0で憶えておいてほしいこと
MySQL 8.0で憶えておいてほしいことyoku0825
 
C# コーディングガイドライン 2013/02/26
C# コーディングガイドライン 2013/02/26C# コーディングガイドライン 2013/02/26
C# コーディングガイドライン 2013/02/26Yoshihisa Ozaki
 
Go初心者がGoでコマンドラインツールの作成に挑戦した話
Go初心者がGoでコマンドラインツールの作成に挑戦した話Go初心者がGoでコマンドラインツールの作成に挑戦した話
Go初心者がGoでコマンドラインツールの作成に挑戦した話dcubeio
 
MySQLテーブル設計入門
MySQLテーブル設計入門MySQLテーブル設計入門
MySQLテーブル設計入門yoku0825
 
MySQL 5.7の罠があなたを狙っている
MySQL 5.7の罠があなたを狙っているMySQL 5.7の罠があなたを狙っている
MySQL 5.7の罠があなたを狙っているyoku0825
 
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」Takuto Wada
 
Batchは作ったことあるけど、 初めてSpring Batchを使ってみた
Batchは作ったことあるけど、 初めてSpring Batchを使ってみたBatchは作ったことあるけど、 初めてSpring Batchを使ってみた
Batchは作ったことあるけど、 初めてSpring Batchを使ってみたHideyuki SASAKURA
 
Introduction to SQL Antipatterns
Introduction to SQL AntipatternsIntroduction to SQL Antipatterns
Introduction to SQL AntipatternsKrishnakumar S
 
ハンドノート T字形ERモデル セミナー資料 (Author; S.Toriyabe SYSTEMS DESIGN Co.,Ltd. Japan)
ハンドノート T字形ERモデル セミナー資料 (Author; S.Toriyabe  SYSTEMS DESIGN Co.,Ltd. Japan) ハンドノート T字形ERモデル セミナー資料 (Author; S.Toriyabe  SYSTEMS DESIGN Co.,Ltd. Japan)
ハンドノート T字形ERモデル セミナー資料 (Author; S.Toriyabe SYSTEMS DESIGN Co.,Ltd. Japan) 聡 鳥谷部
 
Spring bootでweb セキュリティ(ログイン認証)編
Spring bootでweb セキュリティ(ログイン認証)編Spring bootでweb セキュリティ(ログイン認証)編
Spring bootでweb セキュリティ(ログイン認証)編なべ
 
とある診断員と色々厄介な脆弱性達
とある診断員と色々厄介な脆弱性達とある診断員と色々厄介な脆弱性達
とある診断員と色々厄介な脆弱性達zaki4649
 
Laravel の paginate は一体何をやっているのか
Laravel の paginate は一体何をやっているのかLaravel の paginate は一体何をやっているのか
Laravel の paginate は一体何をやっているのかShohei Okada
 
Spring bootでweb バリデート編
Spring bootでweb バリデート編Spring bootでweb バリデート編
Spring bootでweb バリデート編なべ
 
MySQLを割と一人で300台管理する技術
MySQLを割と一人で300台管理する技術MySQLを割と一人で300台管理する技術
MySQLを割と一人で300台管理する技術yoku0825
 
基本に戻ってInnoDBの話をします
基本に戻ってInnoDBの話をします基本に戻ってInnoDBの話をします
基本に戻ってInnoDBの話をしますyoku0825
 
MySQL 5.7にやられないためにおぼえておいてほしいこと
MySQL 5.7にやられないためにおぼえておいてほしいことMySQL 5.7にやられないためにおぼえておいてほしいこと
MySQL 5.7にやられないためにおぼえておいてほしいことyoku0825
 
RLSを用いたマルチテナント実装 for Django
RLSを用いたマルチテナント実装 for DjangoRLSを用いたマルチテナント実装 for Django
RLSを用いたマルチテナント実装 for DjangoTakayuki Shimizukawa
 
とある診断員とSQLインジェクション
とある診断員とSQLインジェクションとある診断員とSQLインジェクション
とある診断員とSQLインジェクションzaki4649
 
MySQLトラブル解析入門
MySQLトラブル解析入門MySQLトラブル解析入門
MySQLトラブル解析入門Mikiya Okuno
 

Was ist angesagt? (20)

金勘定のためのBigDecimalそしてMoney and Currency API
金勘定のためのBigDecimalそしてMoney and Currency API金勘定のためのBigDecimalそしてMoney and Currency API
金勘定のためのBigDecimalそしてMoney and Currency API
 
MySQL 8.0で憶えておいてほしいこと
MySQL 8.0で憶えておいてほしいことMySQL 8.0で憶えておいてほしいこと
MySQL 8.0で憶えておいてほしいこと
 
C# コーディングガイドライン 2013/02/26
C# コーディングガイドライン 2013/02/26C# コーディングガイドライン 2013/02/26
C# コーディングガイドライン 2013/02/26
 
Go初心者がGoでコマンドラインツールの作成に挑戦した話
Go初心者がGoでコマンドラインツールの作成に挑戦した話Go初心者がGoでコマンドラインツールの作成に挑戦した話
Go初心者がGoでコマンドラインツールの作成に挑戦した話
 
MySQLテーブル設計入門
MySQLテーブル設計入門MySQLテーブル設計入門
MySQLテーブル設計入門
 
MySQL 5.7の罠があなたを狙っている
MySQL 5.7の罠があなたを狙っているMySQL 5.7の罠があなたを狙っている
MySQL 5.7の罠があなたを狙っている
 
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
SQLアンチパターン 幻の第26章「とりあえず削除フラグ」
 
Batchは作ったことあるけど、 初めてSpring Batchを使ってみた
Batchは作ったことあるけど、 初めてSpring Batchを使ってみたBatchは作ったことあるけど、 初めてSpring Batchを使ってみた
Batchは作ったことあるけど、 初めてSpring Batchを使ってみた
 
Introduction to SQL Antipatterns
Introduction to SQL AntipatternsIntroduction to SQL Antipatterns
Introduction to SQL Antipatterns
 
ハンドノート T字形ERモデル セミナー資料 (Author; S.Toriyabe SYSTEMS DESIGN Co.,Ltd. Japan)
ハンドノート T字形ERモデル セミナー資料 (Author; S.Toriyabe  SYSTEMS DESIGN Co.,Ltd. Japan) ハンドノート T字形ERモデル セミナー資料 (Author; S.Toriyabe  SYSTEMS DESIGN Co.,Ltd. Japan)
ハンドノート T字形ERモデル セミナー資料 (Author; S.Toriyabe SYSTEMS DESIGN Co.,Ltd. Japan)
 
Spring bootでweb セキュリティ(ログイン認証)編
Spring bootでweb セキュリティ(ログイン認証)編Spring bootでweb セキュリティ(ログイン認証)編
Spring bootでweb セキュリティ(ログイン認証)編
 
とある診断員と色々厄介な脆弱性達
とある診断員と色々厄介な脆弱性達とある診断員と色々厄介な脆弱性達
とある診断員と色々厄介な脆弱性達
 
Laravel の paginate は一体何をやっているのか
Laravel の paginate は一体何をやっているのかLaravel の paginate は一体何をやっているのか
Laravel の paginate は一体何をやっているのか
 
Spring bootでweb バリデート編
Spring bootでweb バリデート編Spring bootでweb バリデート編
Spring bootでweb バリデート編
 
MySQLを割と一人で300台管理する技術
MySQLを割と一人で300台管理する技術MySQLを割と一人で300台管理する技術
MySQLを割と一人で300台管理する技術
 
基本に戻ってInnoDBの話をします
基本に戻ってInnoDBの話をします基本に戻ってInnoDBの話をします
基本に戻ってInnoDBの話をします
 
MySQL 5.7にやられないためにおぼえておいてほしいこと
MySQL 5.7にやられないためにおぼえておいてほしいことMySQL 5.7にやられないためにおぼえておいてほしいこと
MySQL 5.7にやられないためにおぼえておいてほしいこと
 
RLSを用いたマルチテナント実装 for Django
RLSを用いたマルチテナント実装 for DjangoRLSを用いたマルチテナント実装 for Django
RLSを用いたマルチテナント実装 for Django
 
とある診断員とSQLインジェクション
とある診断員とSQLインジェクションとある診断員とSQLインジェクション
とある診断員とSQLインジェクション
 
MySQLトラブル解析入門
MySQLトラブル解析入門MySQLトラブル解析入門
MySQLトラブル解析入門
 

Andere mochten auch

Layout analyzerでのgroovyの利用について
Layout analyzerでのgroovyの利用についてLayout analyzerでのgroovyの利用について
Layout analyzerでのgroovyの利用についてkimukou_26 Kimukou
 
Building scalablewebapps
Building scalablewebappsBuilding scalablewebapps
Building scalablewebappsAyumu Aizawa
 
ソフトウェアパッケージベンダーのためのクラウドソリューション「SQL Anywhere OnDemand Edition」
ソフトウェアパッケージベンダーのためのクラウドソリューション「SQL Anywhere OnDemand Edition」ソフトウェアパッケージベンダーのためのクラウドソリューション「SQL Anywhere OnDemand Edition」
ソフトウェアパッケージベンダーのためのクラウドソリューション「SQL Anywhere OnDemand Edition」nisobe58
 
ngServer and-collaboratived-development-between-san-francisco-and-tokyo
ngServer and-collaboratived-development-between-san-francisco-and-tokyongServer and-collaboratived-development-between-san-francisco-and-tokyo
ngServer and-collaboratived-development-between-san-francisco-and-tokyoSatoshi Tanaka
 
17 E-5 震災とHackとクラウドと 亀渕分
17 E-5 震災とHackとクラウドと 亀渕分17 E-5 震災とHackとクラウドと 亀渕分
17 E-5 震災とHackとクラウドと 亀渕分Keiji Kamebuchi
 
アイデアを塩漬けにしない-世界中の人に手伝ってもらう方法-
アイデアを塩漬けにしない-世界中の人に手伝ってもらう方法-アイデアを塩漬けにしない-世界中の人に手伝ってもらう方法-
アイデアを塩漬けにしない-世界中の人に手伝ってもらう方法-nishio
 
Japan Developer Summit (jp) - Cloud Foundry, the Open Platform As A Service
Japan Developer Summit (jp) - Cloud Foundry, the Open Platform As A ServiceJapan Developer Summit (jp) - Cloud Foundry, the Open Platform As A Service
Japan Developer Summit (jp) - Cloud Foundry, the Open Platform As A ServicePatrick Chanezon
 
ngGoBuilder and collaborative development between San Francisco and Tokyo
ngGoBuilder and collaborative development between San Francisco and TokyongGoBuilder and collaborative development between San Francisco and Tokyo
ngGoBuilder and collaborative development between San Francisco and Tokyonotolab
 
大規模化するピグライフを支えるインフラ ~MongoDBとChefについて~ (後編)
大規模化するピグライフを支えるインフラ ~MongoDBとChefについて~ (後編)大規模化するピグライフを支えるインフラ ~MongoDBとChefについて~ (後編)
大規模化するピグライフを支えるインフラ ~MongoDBとChefについて~ (後編)Yuuki Namikawa
 
【17-E-3】 オンライン機械学習で実現する大規模データ処理
【17-E-3】 オンライン機械学習で実現する大規模データ処理【17-E-3】 オンライン機械学習で実現する大規模データ処理
【17-E-3】 オンライン機械学習で実現する大規模データ処理Developers Summit
 
Pursuit of happiness
Pursuit of happinessPursuit of happiness
Pursuit of happinessbioideology
 
Standing female nude’’
Standing female nude’’Standing female nude’’
Standing female nude’’may
 
大規模化するピグライフを支えるインフラ ~MongoDBとChefについて~ (前編)
大規模化するピグライフを支えるインフラ ~MongoDBとChefについて~ (前編)大規模化するピグライフを支えるインフラ ~MongoDBとChefについて~ (前編)
大規模化するピグライフを支えるインフラ ~MongoDBとChefについて~ (前編)Akihiro Kuwano
 
Ann Summers Cat 66 Slide Show
Ann Summers Cat 66 Slide ShowAnn Summers Cat 66 Slide Show
Ann Summers Cat 66 Slide ShowMargaret_R
 
17 A QuíMica Da Pele
17 A QuíMica Da Pele17 A QuíMica Da Pele
17 A QuíMica Da PeleClaudia Lage
 

Andere mochten auch (16)

Layout analyzerでのgroovyの利用について
Layout analyzerでのgroovyの利用についてLayout analyzerでのgroovyの利用について
Layout analyzerでのgroovyの利用について
 
Building scalablewebapps
Building scalablewebappsBuilding scalablewebapps
Building scalablewebapps
 
ソフトウェアパッケージベンダーのためのクラウドソリューション「SQL Anywhere OnDemand Edition」
ソフトウェアパッケージベンダーのためのクラウドソリューション「SQL Anywhere OnDemand Edition」ソフトウェアパッケージベンダーのためのクラウドソリューション「SQL Anywhere OnDemand Edition」
ソフトウェアパッケージベンダーのためのクラウドソリューション「SQL Anywhere OnDemand Edition」
 
ngServer and-collaboratived-development-between-san-francisco-and-tokyo
ngServer and-collaboratived-development-between-san-francisco-and-tokyongServer and-collaboratived-development-between-san-francisco-and-tokyo
ngServer and-collaboratived-development-between-san-francisco-and-tokyo
 
17 E-5 震災とHackとクラウドと 亀渕分
17 E-5 震災とHackとクラウドと 亀渕分17 E-5 震災とHackとクラウドと 亀渕分
17 E-5 震災とHackとクラウドと 亀渕分
 
アイデアを塩漬けにしない-世界中の人に手伝ってもらう方法-
アイデアを塩漬けにしない-世界中の人に手伝ってもらう方法-アイデアを塩漬けにしない-世界中の人に手伝ってもらう方法-
アイデアを塩漬けにしない-世界中の人に手伝ってもらう方法-
 
Japan Developer Summit (jp) - Cloud Foundry, the Open Platform As A Service
Japan Developer Summit (jp) - Cloud Foundry, the Open Platform As A ServiceJapan Developer Summit (jp) - Cloud Foundry, the Open Platform As A Service
Japan Developer Summit (jp) - Cloud Foundry, the Open Platform As A Service
 
ngGoBuilder and collaborative development between San Francisco and Tokyo
ngGoBuilder and collaborative development between San Francisco and TokyongGoBuilder and collaborative development between San Francisco and Tokyo
ngGoBuilder and collaborative development between San Francisco and Tokyo
 
大規模化するピグライフを支えるインフラ ~MongoDBとChefについて~ (後編)
大規模化するピグライフを支えるインフラ ~MongoDBとChefについて~ (後編)大規模化するピグライフを支えるインフラ ~MongoDBとChefについて~ (後編)
大規模化するピグライフを支えるインフラ ~MongoDBとChefについて~ (後編)
 
【17-E-3】 オンライン機械学習で実現する大規模データ処理
【17-E-3】 オンライン機械学習で実現する大規模データ処理【17-E-3】 オンライン機械学習で実現する大規模データ処理
【17-E-3】 オンライン機械学習で実現する大規模データ処理
 
Pursuit of happiness
Pursuit of happinessPursuit of happiness
Pursuit of happiness
 
Standing female nude’’
Standing female nude’’Standing female nude’’
Standing female nude’’
 
Fuck PPT
Fuck PPTFuck PPT
Fuck PPT
 
大規模化するピグライフを支えるインフラ ~MongoDBとChefについて~ (前編)
大規模化するピグライフを支えるインフラ ~MongoDBとChefについて~ (前編)大規模化するピグライフを支えるインフラ ~MongoDBとChefについて~ (前編)
大規模化するピグライフを支えるインフラ ~MongoDBとChefについて~ (前編)
 
Ann Summers Cat 66 Slide Show
Ann Summers Cat 66 Slide ShowAnn Summers Cat 66 Slide Show
Ann Summers Cat 66 Slide Show
 
17 A QuíMica Da Pele
17 A QuíMica Da Pele17 A QuíMica Da Pele
17 A QuíMica Da Pele
 

Ähnlich wie 削除フラグのはなし

20181110 fok2018-pg-extension
20181110 fok2018-pg-extension20181110 fok2018-pg-extension
20181110 fok2018-pg-extensionToshi Harada
 
5 古雷my sql源碼與資料庫規範
5 古雷my sql源碼與資料庫規範5 古雷my sql源碼與資料庫規範
5 古雷my sql源碼與資料庫規範Ivan Tu
 
20190119 aws-study-pg-extension
20190119 aws-study-pg-extension20190119 aws-study-pg-extension
20190119 aws-study-pg-extensionToshi Harada
 
MySQLとPostgreSQLの基本的な実行プラン比較
MySQLとPostgreSQLの基本的な実行プラン比較MySQLとPostgreSQLの基本的な実行プラン比較
MySQLとPostgreSQLの基本的な実行プラン比較Shinya Sugiyama
 
F#入門 ~関数プログラミングとは何か~
F#入門 ~関数プログラミングとは何か~F#入門 ~関数プログラミングとは何か~
F#入門 ~関数プログラミングとは何か~Nobuhisa Koizumi
 
03 kueripahuomansuchiyuninguno shou_fa_
03 kueripahuomansuchiyuninguno shou_fa_03 kueripahuomansuchiyuninguno shou_fa_
03 kueripahuomansuchiyuninguno shou_fa_Kaito Tonooka
 

Ähnlich wie 削除フラグのはなし (7)

20181110 fok2018-pg-extension
20181110 fok2018-pg-extension20181110 fok2018-pg-extension
20181110 fok2018-pg-extension
 
5 古雷my sql源碼與資料庫規範
5 古雷my sql源碼與資料庫規範5 古雷my sql源碼與資料庫規範
5 古雷my sql源碼與資料庫規範
 
20190119 aws-study-pg-extension
20190119 aws-study-pg-extension20190119 aws-study-pg-extension
20190119 aws-study-pg-extension
 
MySQLとPostgreSQLの基本的な実行プラン比較
MySQLとPostgreSQLの基本的な実行プラン比較MySQLとPostgreSQLの基本的な実行プラン比較
MySQLとPostgreSQLの基本的な実行プラン比較
 
メッチャ役に立つauto_incrementの話
メッチャ役に立つauto_incrementの話メッチャ役に立つauto_incrementの話
メッチャ役に立つauto_incrementの話
 
F#入門 ~関数プログラミングとは何か~
F#入門 ~関数プログラミングとは何か~F#入門 ~関数プログラミングとは何か~
F#入門 ~関数プログラミングとは何か~
 
03 kueripahuomansuchiyuninguno shou_fa_
03 kueripahuomansuchiyuninguno shou_fa_03 kueripahuomansuchiyuninguno shou_fa_
03 kueripahuomansuchiyuninguno shou_fa_
 

Kürzlich hochgeladen

シンフォニティ株式会社(SYMPHONITY , Inc.) 会社説明・人材採用資料
シンフォニティ株式会社(SYMPHONITY , Inc.) 会社説明・人材採用資料シンフォニティ株式会社(SYMPHONITY , Inc.) 会社説明・人材採用資料
シンフォニティ株式会社(SYMPHONITY , Inc.) 会社説明・人材採用資料シンフォニティ 株式会社
 
ストックマーク株式会社がご提供しているAnews(エーニュース)概要紹介.pdf
ストックマーク株式会社がご提供しているAnews(エーニュース)概要紹介.pdfストックマーク株式会社がご提供しているAnews(エーニュース)概要紹介.pdf
ストックマーク株式会社がご提供しているAnews(エーニュース)概要紹介.pdfmasakisaito12
 
UP103シリーズ パワーコメット ユニパー スライドレールタイプ 瓦揚げ機 ウインチ
UP103シリーズ パワーコメット ユニパー スライドレールタイプ 瓦揚げ機 ウインチUP103シリーズ パワーコメット ユニパー スライドレールタイプ 瓦揚げ機 ウインチ
UP103シリーズ パワーコメット ユニパー スライドレールタイプ 瓦揚げ機 ウインチユニパー株式会社
 
202405_VISIONARYJAPAN_engineerteam_entrancebook(ver2.1)
202405_VISIONARYJAPAN_engineerteam_entrancebook(ver2.1)202405_VISIONARYJAPAN_engineerteam_entrancebook(ver2.1)
202405_VISIONARYJAPAN_engineerteam_entrancebook(ver2.1)KayaSuetake1
 
Service-introduction-materials-misorae-leadership
Service-introduction-materials-misorae-leadershipService-introduction-materials-misorae-leadership
Service-introduction-materials-misorae-leadershipYasuyoshi Minehisa
 
20240427 zaim academy counseling lesson .pdf
20240427 zaim academy counseling lesson .pdf20240427 zaim academy counseling lesson .pdf
20240427 zaim academy counseling lesson .pdfssuser80a51f
 

Kürzlich hochgeladen (6)

シンフォニティ株式会社(SYMPHONITY , Inc.) 会社説明・人材採用資料
シンフォニティ株式会社(SYMPHONITY , Inc.) 会社説明・人材採用資料シンフォニティ株式会社(SYMPHONITY , Inc.) 会社説明・人材採用資料
シンフォニティ株式会社(SYMPHONITY , Inc.) 会社説明・人材採用資料
 
ストックマーク株式会社がご提供しているAnews(エーニュース)概要紹介.pdf
ストックマーク株式会社がご提供しているAnews(エーニュース)概要紹介.pdfストックマーク株式会社がご提供しているAnews(エーニュース)概要紹介.pdf
ストックマーク株式会社がご提供しているAnews(エーニュース)概要紹介.pdf
 
UP103シリーズ パワーコメット ユニパー スライドレールタイプ 瓦揚げ機 ウインチ
UP103シリーズ パワーコメット ユニパー スライドレールタイプ 瓦揚げ機 ウインチUP103シリーズ パワーコメット ユニパー スライドレールタイプ 瓦揚げ機 ウインチ
UP103シリーズ パワーコメット ユニパー スライドレールタイプ 瓦揚げ機 ウインチ
 
202405_VISIONARYJAPAN_engineerteam_entrancebook(ver2.1)
202405_VISIONARYJAPAN_engineerteam_entrancebook(ver2.1)202405_VISIONARYJAPAN_engineerteam_entrancebook(ver2.1)
202405_VISIONARYJAPAN_engineerteam_entrancebook(ver2.1)
 
Service-introduction-materials-misorae-leadership
Service-introduction-materials-misorae-leadershipService-introduction-materials-misorae-leadership
Service-introduction-materials-misorae-leadership
 
20240427 zaim academy counseling lesson .pdf
20240427 zaim academy counseling lesson .pdf20240427 zaim academy counseling lesson .pdf
20240427 zaim academy counseling lesson .pdf
 

削除フラグのはなし

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6. id name pass is_deleted 1 ryu xxx FALSE 2 ken xxx FALSE 3 honda xxx TRUE
  • 7.
  • 8. id name pass is_deleted 1 ryu xxx FALSE 2 ken xxx FALSE 3 honda xxx TRUE 3 honda xxx FALSE
  • 9.
  • 10. WHERE is_deleted = false WHERE is_deleted = false WHERE is_deleted = false
  • 11. DELETE FROM users WHERE id = 2; UPDATE user SET is_update = true WHERE id = 2;
  • 12.
  • 13.
  • 14.
  • 15.
  • 16. id name pass is_deleted 1 ryu xxx TRUE 2 ryu xxx TRUE 3 ryu xxx FALSE 4 ryu xxx FALSE
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30. id name pass is_deleted 1 ryu xxx TRUE 2 ryu xxx TRUE 3 ryu xxx FALSE 4 ryu xxx FALSE
  • 31. -- 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;
  • 32.
  • 33. -- テーブルを作成する 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;
  • 34. -- 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)
  • 35. -- 更にもう一件重複する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.
  • 36. -- 削除フラグを立てて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)
  • 37. -- 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)
  • 38. -- 削除フラグを戻して削除した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.
  • 39. -- 現在のデータを確認する 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)
  • 40.
  • 41.
  • 42.
  • 45.
  • 46. -- ユーザテーブルを作成する -- エントリーテーブルを作成する 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 ); );
  • 47. -- 一意な部分インデックスを張る(IDを利用) CREATE UNIQUE INDEX users_valid_constraint ON users (name) WHERE 0 < user_id;
  • 48. -- テストデータを投入する 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, '参加', 'よろしく');
  • 49. -- テストデータを確認する 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)
  • 50. -- イベントを論理削除する UPDATE events SET event_id = event_id * -1 WHERE event_id = 1;
  • 51. -- 参照しているテーブルを確認する 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)
  • 52. -- ユーザを論理削除する UPDATE users SET user_id = user_id * -1 WHERE user_id = 2;
  • 53. -- 参照しているテーブルを確認する 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)
  • 54. -- ちなみに、物理削除すると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)
  • 55.
  • 56.
  • 57.
  • 58.
  • 59. -- ユーザテーブルを作成する -- エントリーテーブルを作成する 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 ); );
  • 61. -- 削除されたユーザの保存先を作成する 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 );
  • 62. -- 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;
  • 63. -- 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();
  • 64. -- テストデータを投入する 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, '参加', 'よろしく');
  • 65. -- テストデータを確認する 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)
  • 66. -- 削除されたデータの保存先は空 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)
  • 68. -- 他の関連するレコードも連鎖的に削除されている 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)
  • 69. -- 連鎖的に削除されたレコードは保存用のテーブルに退避されている 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)
  • 70.
  • 71.
  • 72.
  • 73.
  • 74.
  • 75.
  • 76.
  • 77.
  • 78.
  • 79.
  • 80.
  • 81.
  • 82.
  • 83. 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();