diff --git "a/data/2.PostgreSQL\344\270\255\351\230\266/1.\345\237\272\346\234\254\347\273\223\346\236\204/5. \350\247\246\345\217\221\345\231\250/audit.json" "b/data/2.PostgreSQL\344\270\255\351\230\266/1.\345\237\272\346\234\254\347\273\223\346\236\204/5. \350\247\246\345\217\221\345\231\250/audit.json" new file mode 100644 index 0000000000000000000000000000000000000000..4413ed29628c409db2ec8936eecb07b9fa8847f3 --- /dev/null +++ "b/data/2.PostgreSQL\344\270\255\351\230\266/1.\345\237\272\346\234\254\347\273\223\346\236\204/5. \350\247\246\345\217\221\345\231\250/audit.json" @@ -0,0 +1,7 @@ +{ + "type": "code_options", + "author": "ccat", + "source": "audit.md", + "notebook_enable": false, + "exercise_id": "47ab9b38b16d48ca9a4abd637dfe39b3" +} \ No newline at end of file diff --git "a/data/2.PostgreSQL\344\270\255\351\230\266/1.\345\237\272\346\234\254\347\273\223\346\236\204/5. \350\247\246\345\217\221\345\231\250/audit.md" "b/data/2.PostgreSQL\344\270\255\351\230\266/1.\345\237\272\346\234\254\347\273\223\346\236\204/5. \350\247\246\345\217\221\345\231\250/audit.md" new file mode 100644 index 0000000000000000000000000000000000000000..178a9c61ae67a1829c204608d13a246a30e68d79 --- /dev/null +++ "b/data/2.PostgreSQL\344\270\255\351\230\266/1.\345\237\272\346\234\254\347\273\223\346\236\204/5. \350\247\246\345\217\221\345\231\250/audit.md" @@ -0,0 +1,103 @@ +# 交易审计 + +Orders 表 + +```postgresql +create table orders +( + id serial primary key, + item_id int, + amount int, + unit_price money, + total money, + description text, + ts timestamp default now() +); +``` + +记录了未完成的订单。审计部门现在需要记录其变更——新增或删除,该表不会发生update——即将修改都记录到 orders_log 表 + +```postgresql +create table orders_log +( + log_id serial primary key, + id int, + item_id int, + amount int, + unit_price money, + total money, + description text, + ts timestamp, + direction varchar(16), + log_at timestamp default now() +); +``` + +那么应该如何做? + +## 答案 + +```postgresql + +create or replace function log_order_in() returns trigger as $$ +begin + insert into orders_log(id, item_id, amount, unit_price, total, description, ts, direction) + values(NEW.id, NEW.item_id, NEW.amount, NEW.unit_price, NEW.total, NEW.description, NEW.ts, 'in'); + return NEW; +end +$$ language plpgsql; + +create or replace function log_order_out() returns trigger as $$ +begin + insert into orders_log(id, item_id, amount, unit_price, total, description, ts, direction) + values(OLD.id, OLD.item_id, OLD.amount, OLD.unit_price, OLD.total, OLD.description, OLD.ts, 'out'); + return OLD; +end +$$ language plpgsql; + +create trigger in_orders after insert on orders + for each row execute function log_order_in(); + +create trigger out_orders after delete on orders + for each row execute function log_order_out(); +``` + +## 选项 + +### A + +```postgresql +create trigger in_orders after insert on orders + for each row insert into orders_log(id, item_id, amount, unit_price, total, description, ts, direction) + values(NEW.id, NEW.item_id, NEW.amount, NEW.unit_price, NEW.total, NEW.description, NEW.ts, 'in'); + +``` + +### B + +```postgresql + +create trigger out_orders after delete on orders + for each row insert into orders_log(id, item_id, amount, unit_price, total, description, ts, direction) + values(OLD.id, OLD.item_id, OLD.amount, OLD.unit_price, OLD.total, OLD.description, OLD.ts, 'out'); +``` + + +### C + +```postgresql +create trigger in_orders after insert on orders + for each row insert into orders_log(id, item_id, amount, unit_price, total, description, ts, direction) + values(NEW.id, NEW.item_id, NEW.amount, NEW.unit_price, NEW.total, NEW.description, NEW.ts, 'in'); + after delete on orders + for each row insert into orders_log(id, item_id, amount, unit_price, total, description, ts, direction) + values(OLD.id, OLD.item_id, OLD.amount, OLD.unit_price, OLD.total, OLD.description, OLD.ts, 'out'); +``` + +### D + +```postgresql +create trigger in_orders after insert, after delete on orders + for each row insert into orders_log(id, item_id, amount, unit_price, total, description, ts, direction) + values(NEW.id, NEW.item_id, NEW.amount, NEW.unit_price, NEW.total, NEW.description, NEW.ts, 'in'); +``` \ No newline at end of file diff --git "a/data/2.PostgreSQL\344\270\255\351\230\266/1.\345\237\272\346\234\254\347\273\223\346\236\204/5. \350\247\246\345\217\221\345\231\250/config.json" "b/data/2.PostgreSQL\344\270\255\351\230\266/1.\345\237\272\346\234\254\347\273\223\346\236\204/5. \350\247\246\345\217\221\345\231\250/config.json" index 1fac93164b565f064e830f7c4de7b94152ebefa5..8fc4866d4c2b870450cf78e7abdfa310e4bc1632 100644 --- "a/data/2.PostgreSQL\344\270\255\351\230\266/1.\345\237\272\346\234\254\347\273\223\346\236\204/5. \350\247\246\345\217\221\345\231\250/config.json" +++ "b/data/2.PostgreSQL\344\270\255\351\230\266/1.\345\237\272\346\234\254\347\273\223\346\236\204/5. \350\247\246\345\217\221\345\231\250/config.json" @@ -6,7 +6,8 @@ ], "children": [], "export": [ - "trigger.json" + "trigger.json", + "audit.json" ], "keywords_must": [ "trigger", diff --git a/data/tree.json b/data/tree.json index ca3a945712e2c640efa4cd1eef62d3cdcb2eb881..d360e548d70cf0241162a321509bdaf333e3823c 100644 --- a/data/tree.json +++ b/data/tree.json @@ -29,7 +29,8 @@ "relational", "rdbms" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -46,12 +47,14 @@ "服务器", "客户端" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } } ], "keywords_must": [], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -70,7 +73,8 @@ "keywords_must": [ "安装" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -85,7 +89,8 @@ "keywords_must": [ "登录" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -101,12 +106,14 @@ "基本用法", "入门" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } } ], "keywords_must": [], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -126,7 +133,8 @@ "keywords_must": [ "psql" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -141,7 +149,8 @@ "语法", "SQL" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -161,17 +170,20 @@ "update", "delete" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } } ], "keywords_must": [], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } } ], "keywords_must": [], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -196,7 +208,8 @@ "表", "table" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -211,7 +224,8 @@ "函数", "function" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -236,7 +250,8 @@ "权限", "privilege" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -255,7 +270,8 @@ "constraints", "index" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -270,7 +286,8 @@ "trigger", "触发器" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -286,12 +303,14 @@ "数据库扩展", "extension" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } } ], "keywords_must": [], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -312,7 +331,8 @@ "分组", "聚合" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -327,7 +347,8 @@ "join", "连接查询" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -342,7 +363,8 @@ "子查询", "subquery" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -359,7 +381,8 @@ "limit", "offset" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -374,7 +397,8 @@ "keywords_must": [ "cte" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -388,7 +412,8 @@ "keywords_must": [ "过程化" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -405,17 +430,20 @@ "授权", "ddl" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } } ], "keywords_must": [], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } } ], "keywords_must": [], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -441,7 +469,8 @@ "keywords_must": [ "standby" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -458,7 +487,8 @@ "流式复制", "流复制" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -473,12 +503,14 @@ "外部数据连接", "fdw" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } } ], "keywords_must": [], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -498,7 +530,8 @@ "gis", "几何" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -513,7 +546,8 @@ "json", "jsonb" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -535,7 +569,8 @@ ], "" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -550,12 +585,14 @@ "视图", "view" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } } ], "keywords_must": [], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -577,7 +614,8 @@ "递归查询", "recursive" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -593,7 +631,8 @@ "function", "window" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -610,7 +649,8 @@ "交叉透视表", "pivot" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -626,7 +666,8 @@ "conflict", "冲突" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -641,7 +682,8 @@ "事务", "transaction" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -660,12 +702,14 @@ "performance", "优化" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } } ], "keywords_must": [], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } }, { @@ -683,21 +727,25 @@ "keywords_must": [ "数据库问答" ], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } } ], "keywords_must": [], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } } ], "keywords_must": [], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } } ], "keywords_must": [], - "keywords_forbid": [] + "keywords_forbid": [], + "group": 0 } } \ No newline at end of file