SlideShare a Scribd company logo
1 of 83
Download to read offline
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();

More Related Content

What's hot

イミュータブルデータモデル(世代編)
イミュータブルデータモデル(世代編)イミュータブルデータモデル(世代編)
イミュータブルデータモデル(世代編)Yoshitaka Kawashima
 
SQLアンチパターン メンター用資料
SQLアンチパターン メンター用資料SQLアンチパターン メンター用資料
SQLアンチパターン メンター用資料Hironori Miura
 
GoによるWebアプリ開発のキホン
GoによるWebアプリ開発のキホンGoによるWebアプリ開発のキホン
GoによるWebアプリ開発のキホンAkihiko Horiuchi
 
イミュータブルデータモデル(入門編)
イミュータブルデータモデル(入門編)イミュータブルデータモデル(入門編)
イミュータブルデータモデル(入門編)Yoshitaka Kawashima
 
SQLアンチパターン読書会 4章 キーレスエンエントリ(外部キー嫌い)
SQLアンチパターン読書会 4章 キーレスエンエントリ(外部キー嫌い)SQLアンチパターン読書会 4章 キーレスエンエントリ(外部キー嫌い)
SQLアンチパターン読書会 4章 キーレスエンエントリ(外部キー嫌い)makopi 23
 
Where狙いのキー、order by狙いのキー
Where狙いのキー、order by狙いのキーWhere狙いのキー、order by狙いのキー
Where狙いのキー、order by狙いのキーyoku0825
 
Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方Taku Miyakawa
 
Java ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsugJava ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsugMasatoshi Tada
 
PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~
PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~
PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~Miki Shimogai
 
Rails A/B testing by split gem
Rails A/B testing by split gemRails A/B testing by split gem
Rails A/B testing by split gemRyuma Tsukano
 
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話Daichi Koike
 
DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!kwatch
 
分散トレーシングAWS:X-Rayとの上手い付き合い方
分散トレーシングAWS:X-Rayとの上手い付き合い方分散トレーシングAWS:X-Rayとの上手い付き合い方
分散トレーシングAWS:X-Rayとの上手い付き合い方Recruit Lifestyle Co., Ltd.
 
Laravel の paginate は一体何をやっているのか
Laravel の paginate は一体何をやっているのかLaravel の paginate は一体何をやっているのか
Laravel の paginate は一体何をやっているのかShohei Okada
 
データベース設計徹底指南
データベース設計徹底指南データベース設計徹底指南
データベース設計徹底指南Mikiya Okuno
 
文字コードに起因する脆弱性とその対策(増補版)
文字コードに起因する脆弱性とその対策(増補版)文字コードに起因する脆弱性とその対策(増補版)
文字コードに起因する脆弱性とその対策(増補版)Hiroshi Tokumaru
 
オブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメオブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメYoji Kanno
 

What's hot (20)

イミュータブルデータモデル(世代編)
イミュータブルデータモデル(世代編)イミュータブルデータモデル(世代編)
イミュータブルデータモデル(世代編)
 
SQLアンチパターン メンター用資料
SQLアンチパターン メンター用資料SQLアンチパターン メンター用資料
SQLアンチパターン メンター用資料
 
GoによるWebアプリ開発のキホン
GoによるWebアプリ開発のキホンGoによるWebアプリ開発のキホン
GoによるWebアプリ開発のキホン
 
Keycloakのステップアップ認証について
Keycloakのステップアップ認証についてKeycloakのステップアップ認証について
Keycloakのステップアップ認証について
 
イミュータブルデータモデル(入門編)
イミュータブルデータモデル(入門編)イミュータブルデータモデル(入門編)
イミュータブルデータモデル(入門編)
 
SQLアンチパターン読書会 4章 キーレスエンエントリ(外部キー嫌い)
SQLアンチパターン読書会 4章 キーレスエンエントリ(外部キー嫌い)SQLアンチパターン読書会 4章 キーレスエンエントリ(外部キー嫌い)
SQLアンチパターン読書会 4章 キーレスエンエントリ(外部キー嫌い)
 
Where狙いのキー、order by狙いのキー
Where狙いのキー、order by狙いのキーWhere狙いのキー、order by狙いのキー
Where狙いのキー、order by狙いのキー
 
Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方Javaのログ出力: 道具と考え方
Javaのログ出力: 道具と考え方
 
Java ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsugJava ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsug
 
PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~
PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~
PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~
 
Rails A/B testing by split gem
Rails A/B testing by split gemRails A/B testing by split gem
Rails A/B testing by split gem
 
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
OpenAPI 3.0でmicroserviceのAPI定義を試みてハマった話
 
Keycloakの最近のトピック
Keycloakの最近のトピックKeycloakの最近のトピック
Keycloakの最近のトピック
 
DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!DBスキーマもバージョン管理したい!
DBスキーマもバージョン管理したい!
 
分散トレーシングAWS:X-Rayとの上手い付き合い方
分散トレーシングAWS:X-Rayとの上手い付き合い方分散トレーシングAWS:X-Rayとの上手い付き合い方
分散トレーシングAWS:X-Rayとの上手い付き合い方
 
Laravel の paginate は一体何をやっているのか
Laravel の paginate は一体何をやっているのかLaravel の paginate は一体何をやっているのか
Laravel の paginate は一体何をやっているのか
 
データベース設計徹底指南
データベース設計徹底指南データベース設計徹底指南
データベース設計徹底指南
 
文字コードに起因する脆弱性とその対策(増補版)
文字コードに起因する脆弱性とその対策(増補版)文字コードに起因する脆弱性とその対策(増補版)
文字コードに起因する脆弱性とその対策(増補版)
 
MongoDB Oplog入門
MongoDB Oplog入門MongoDB Oplog入門
MongoDB Oplog入門
 
オブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメオブジェクト指向エクササイズのススメ
オブジェクト指向エクササイズのススメ
 

Viewers also liked

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
 

Viewers also liked (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
 

Similar to 削除フラグのはなし

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
 

Similar to 削除フラグのはなし (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_
 

Recently uploaded

Service-introduction-materials-misorae-leadership
Service-introduction-materials-misorae-leadershipService-introduction-materials-misorae-leadership
Service-introduction-materials-misorae-leadershipYasuyoshi Minehisa
 
Long asia「地方の空き家活用の新戦略」空き家とDX一緒に考えると、すべてうまくいく
Long asia「地方の空き家活用の新戦略」空き家とDX一緒に考えると、すべてうまくいくLong asia「地方の空き家活用の新戦略」空き家とDX一緒に考えると、すべてうまくいく
Long asia「地方の空き家活用の新戦略」空き家とDX一緒に考えると、すべてうまくいくlong asia
 
企業規模で選ぶ、フライクサービス | 中小企業向け 業務フロー診断 × 改善提案
企業規模で選ぶ、フライクサービス | 中小企業向け 業務フロー診断 × 改善提案企業規模で選ぶ、フライクサービス | 中小企業向け 業務フロー診断 × 改善提案
企業規模で選ぶ、フライクサービス | 中小企業向け 業務フロー診断 × 改善提案Flyke1
 
LINEコンサルティング事例資料 | 北海道イノベーション&インキュベーション株式会社
LINEコンサルティング事例資料 | 北海道イノベーション&インキュベーション株式会社LINEコンサルティング事例資料 | 北海道イノベーション&インキュベーション株式会社
LINEコンサルティング事例資料 | 北海道イノベーション&インキュベーション株式会社taka k
 
エンSXセールス_2024051700000000000000000000000
エンSXセールス_2024051700000000000000000000000エンSXセールス_2024051700000000000000000000000
エンSXセールス_2024051700000000000000000000000marikok
 
chouhou_obuse_reiwa6nen_5gatugou_5gatu20nitihakkou
chouhou_obuse_reiwa6nen_5gatugou_5gatu20nitihakkouchouhou_obuse_reiwa6nen_5gatugou_5gatu20nitihakkou
chouhou_obuse_reiwa6nen_5gatugou_5gatu20nitihakkoussuser31dbd1
 
2024年4月度 安全の取り組み - 2024-042024-04コピー.pdf
2024年4月度 安全の取り組み - 2024-042024-04コピー.pdf2024年4月度 安全の取り組み - 2024-042024-04コピー.pdf
2024年4月度 安全の取り組み - 2024-042024-04コピー.pdfyosibaba1
 
地域観光新発見事業説明会資料(観光庁/地域観光新発見事業事務局/令和6年5月23日)
地域観光新発見事業説明会資料(観光庁/地域観光新発見事業事務局/令和6年5月23日)地域観光新発見事業説明会資料(観光庁/地域観光新発見事業事務局/令和6年5月23日)
地域観光新発見事業説明会資料(観光庁/地域観光新発見事業事務局/令和6年5月23日)kankocho
 
デザイナーが挑んだ新規事業開発の失敗談〜しくじりナレッジ編〜_Algomatic 國光俊樹
デザイナーが挑んだ新規事業開発の失敗談〜しくじりナレッジ編〜_Algomatic 國光俊樹デザイナーが挑んだ新規事業開発の失敗談〜しくじりナレッジ編〜_Algomatic 國光俊樹
デザイナーが挑んだ新規事業開発の失敗談〜しくじりナレッジ編〜_Algomatic 國光俊樹Toshiki Kunimitsu
 
ITツールで選ぶフライクサービス | Box 2Box初期設定・サーバー移行支援サービス
ITツールで選ぶフライクサービス | Box 2Box初期設定・サーバー移行支援サービスITツールで選ぶフライクサービス | Box 2Box初期設定・サーバー移行支援サービス
ITツールで選ぶフライクサービス | Box 2Box初期設定・サーバー移行支援サービスFlyke1
 
エンSXセールスアナリティクス_202405171000000000000000
エンSXセールスアナリティクス_202405171000000000000000エンSXセールスアナリティクス_202405171000000000000000
エンSXセールスアナリティクス_202405171000000000000000marikok
 
From Generative AI to Cooperative AI: 協働AIのもたらす社会、2030年への課題と展望
From Generative AI to Cooperative AI: 協働AIのもたらす社会、2030年への課題と展望From Generative AI to Cooperative AI: 協働AIのもたらす社会、2030年への課題と展望
From Generative AI to Cooperative AI: 協働AIのもたらす社会、2030年への課題と展望Osaka University
 
企業規模で選ぶフライクサービス | 大企業向け 部署横断+全体最適化システムコンサルティング
企業規模で選ぶフライクサービス | 大企業向け 部署横断+全体最適化システムコンサルティング企業規模で選ぶフライクサービス | 大企業向け 部署横断+全体最適化システムコンサルティング
企業規模で選ぶフライクサービス | 大企業向け 部署横断+全体最適化システムコンサルティングFlyke1
 
企業規模で選ぶフライクサービス | 中堅企業向け 業務フロー改善×システム導入コンサルティング
企業規模で選ぶフライクサービス | 中堅企業向け 業務フロー改善×システム導入コンサルティング企業規模で選ぶフライクサービス | 中堅企業向け 業務フロー改善×システム導入コンサルティング
企業規模で選ぶフライクサービス | 中堅企業向け 業務フロー改善×システム導入コンサルティングFlyke1
 

Recently uploaded (14)

Service-introduction-materials-misorae-leadership
Service-introduction-materials-misorae-leadershipService-introduction-materials-misorae-leadership
Service-introduction-materials-misorae-leadership
 
Long asia「地方の空き家活用の新戦略」空き家とDX一緒に考えると、すべてうまくいく
Long asia「地方の空き家活用の新戦略」空き家とDX一緒に考えると、すべてうまくいくLong asia「地方の空き家活用の新戦略」空き家とDX一緒に考えると、すべてうまくいく
Long asia「地方の空き家活用の新戦略」空き家とDX一緒に考えると、すべてうまくいく
 
企業規模で選ぶ、フライクサービス | 中小企業向け 業務フロー診断 × 改善提案
企業規模で選ぶ、フライクサービス | 中小企業向け 業務フロー診断 × 改善提案企業規模で選ぶ、フライクサービス | 中小企業向け 業務フロー診断 × 改善提案
企業規模で選ぶ、フライクサービス | 中小企業向け 業務フロー診断 × 改善提案
 
LINEコンサルティング事例資料 | 北海道イノベーション&インキュベーション株式会社
LINEコンサルティング事例資料 | 北海道イノベーション&インキュベーション株式会社LINEコンサルティング事例資料 | 北海道イノベーション&インキュベーション株式会社
LINEコンサルティング事例資料 | 北海道イノベーション&インキュベーション株式会社
 
エンSXセールス_2024051700000000000000000000000
エンSXセールス_2024051700000000000000000000000エンSXセールス_2024051700000000000000000000000
エンSXセールス_2024051700000000000000000000000
 
chouhou_obuse_reiwa6nen_5gatugou_5gatu20nitihakkou
chouhou_obuse_reiwa6nen_5gatugou_5gatu20nitihakkouchouhou_obuse_reiwa6nen_5gatugou_5gatu20nitihakkou
chouhou_obuse_reiwa6nen_5gatugou_5gatu20nitihakkou
 
2024年4月度 安全の取り組み - 2024-042024-04コピー.pdf
2024年4月度 安全の取り組み - 2024-042024-04コピー.pdf2024年4月度 安全の取り組み - 2024-042024-04コピー.pdf
2024年4月度 安全の取り組み - 2024-042024-04コピー.pdf
 
地域観光新発見事業説明会資料(観光庁/地域観光新発見事業事務局/令和6年5月23日)
地域観光新発見事業説明会資料(観光庁/地域観光新発見事業事務局/令和6年5月23日)地域観光新発見事業説明会資料(観光庁/地域観光新発見事業事務局/令和6年5月23日)
地域観光新発見事業説明会資料(観光庁/地域観光新発見事業事務局/令和6年5月23日)
 
デザイナーが挑んだ新規事業開発の失敗談〜しくじりナレッジ編〜_Algomatic 國光俊樹
デザイナーが挑んだ新規事業開発の失敗談〜しくじりナレッジ編〜_Algomatic 國光俊樹デザイナーが挑んだ新規事業開発の失敗談〜しくじりナレッジ編〜_Algomatic 國光俊樹
デザイナーが挑んだ新規事業開発の失敗談〜しくじりナレッジ編〜_Algomatic 國光俊樹
 
ITツールで選ぶフライクサービス | Box 2Box初期設定・サーバー移行支援サービス
ITツールで選ぶフライクサービス | Box 2Box初期設定・サーバー移行支援サービスITツールで選ぶフライクサービス | Box 2Box初期設定・サーバー移行支援サービス
ITツールで選ぶフライクサービス | Box 2Box初期設定・サーバー移行支援サービス
 
エンSXセールスアナリティクス_202405171000000000000000
エンSXセールスアナリティクス_202405171000000000000000エンSXセールスアナリティクス_202405171000000000000000
エンSXセールスアナリティクス_202405171000000000000000
 
From Generative AI to Cooperative AI: 協働AIのもたらす社会、2030年への課題と展望
From Generative AI to Cooperative AI: 協働AIのもたらす社会、2030年への課題と展望From Generative AI to Cooperative AI: 協働AIのもたらす社会、2030年への課題と展望
From Generative AI to Cooperative AI: 協働AIのもたらす社会、2030年への課題と展望
 
企業規模で選ぶフライクサービス | 大企業向け 部署横断+全体最適化システムコンサルティング
企業規模で選ぶフライクサービス | 大企業向け 部署横断+全体最適化システムコンサルティング企業規模で選ぶフライクサービス | 大企業向け 部署横断+全体最適化システムコンサルティング
企業規模で選ぶフライクサービス | 大企業向け 部署横断+全体最適化システムコンサルティング
 
企業規模で選ぶフライクサービス | 中堅企業向け 業務フロー改善×システム導入コンサルティング
企業規模で選ぶフライクサービス | 中堅企業向け 業務フロー改善×システム導入コンサルティング企業規模で選ぶフライクサービス | 中堅企業向け 業務フロー改善×システム導入コンサルティング
企業規模で選ぶフライクサービス | 中堅企業向け 業務フロー改善×システム導入コンサルティング
 

削除フラグのはなし

  • 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();