我有下表称为“经理”:
Store | Person
ABC Ms. Elara
XYZ Mr. Saros
DEF Ms. Orion
我正在学习PostgreSQL中的触发器,并且正在尝试为上表编写一个触发器,以检查并禁止在Manager表中插入或更新Person成为任何一家商店的经理。
我的方法是在触发器函数中,从Manager表中选择元组,其中Person等于要尝试插入的元组中的Person。如果Manager表中的元组与要插入的新元组中的Person相等,那么将不插入该行。
我不确定如何在触发函数中从Manager中选择“人”等于要插入的“人”的所有元组。任何见解都会受到赞赏。
答案 0 :(得分:3)
您还可以使用唯一索引:
CREATE UNIQUE INDEX Manager_IDX ON Manager (person);
如果您尝试将一个人的名字更新为已经存在的名字,这也将起作用。这样做还有一个好处,就是可以快速地通过人名查询表格。
您确实说过想了解触发器,一种开始的方法可能是在管理器上有一个触发器(实际上是3个插入,更新和删除触发器),该触发器会自动保留更改的历史记录(即审核记录) )放在另一个表中(例如manager_audit)。审核表的定义与Manager表的定义相同,但是至少有一个额外的列(例如操作码)来跟踪操作的内容。例如I代表插入,D代表删除,U代表更新。您还可以有一个时间戳记来记录操作发生的时间以及其他字段(例如,进行更改的用户ID等)。
说了这么多,不管它有什么价值,对名称之类的东西实施唯一性可能都不是最好的主意。 “史密斯先生”很可能是恰好在一家大公司工作的两个不同的人的名字。
您可能要考虑的另一个因素是性能。如果使用基于选择的方法来确保非索引列/列的唯一性,则需要对表进行“全行扫描”以执行该测试。无论您如何实现(例如触发器,函数,过程或其他任何东西),这都是正确的。
换一种说法,假设您有100位经理,并且您想插入一个新经理。基于选择的检查将要求您扫描整个表(即100行)以查看名称是否已存在。随着表的增长,扫描也将增长。随着时间的流逝,您将遇到“性能下降”的现象。当表达到数百万或数十亿行时,您的“单记录插入”实际上将需要数十亿个I / O。
索引不能那样工作。索引本质上是反向子表,其中您指定的列(例如manager.person)是“键”。这样,无论其中有多少条记录,只需一个I / O即可执行必要的检查。
免责声明(对于纯粹主义者),我将I / O定义为逻辑“记录级别” I / O,而不是物理磁盘I / O或任何其他类型的I / O。因此,读取一条记录= 1 I / O,写入一条记录= 1 I / O。
答案 1 :(得分:0)
为什么需要为此触发? U可以编写一个postgres函数,以在插入之前检查特定人的存在。
这样的事情,
Create function check_person_exists(par_person_id int)
Declare var_exists_flag int;
Begin
var_exists_flag =0;p
Select 1 from table where person_id = par_person_id into var_exists_flag;
If var_exists_flag = 0
Then
Insert into ....
Else
Raise notice ' the records already exists';
Return;
End
PS:上面的代码将有语法问题。