【发布时间】:2018-01-25 03:49:01
【问题描述】:
假设我有一张员工表(员工),其中有数千条记录。我需要根据您的登录限制您可以看到的员工以实现可重用性我创建了一个函数fn_HasEmployeeAccess(t_userid int, t_employee_id INT),它将返回 true/false 以确定您是否有权访问该员工。
这个函数看起来像这样(尽管它会进行其他检查,例如,您无法访问自己的个人资料,您无法访问与您共享职位的其他员工等):
FUNCTION fn_HasEmployeeAccess(t_userid INT, t_employee_id INT)
DECLARE isAdmin BOOL;
DECLARE isDirector BOOL;
DECLARE empStatus INT;
SELECT admin, director INTO isAdmin, isDirector FROM users
WHERE users.userid=t_userid;
/*select the status of this user if it is in your dept
if employee is not in your department - status will be null
which will fail the checks below and return 0*/
SELECT employee.status INTO empStatus FROM employee
INNER JOIN users ON employee.department = users.department
WHERE employee.employeeID=t_employee_id;
IF empStatus IN (1,2) AND isAdmin THEN
RETURN 1;
ELSE IF empStatus=2 AND userIsDirector THEN
RETURN 1;
ELSE
return 0;
END IF;
END FUNCTION
现在所有这些都有效并且很棒,除非您有大量数据并且需要使用多个连接进行查询,然后根据此函数的结果在该过滤器之上进行查询 - 性能会下降很多,我相信我理解 - 该函数正在为员工表中的每一行运行。
例如:
SELECT * FROM employee e
INNER JOIN employee_attachments a ON e.employeeID = a.employeeID
WHERE fn_HasEmployeeAccess(12345, e.employeeID)=1
如何防止我认为由于函数使用而导致的全表扫描?他们是这种模式的替代品吗?
该功能用于过滤应用程序中几乎所有地方(仪表板、视图、报告)等,如果我想调整对员工的访问权限,我目前只需要调整该功能。有人建议我只内联所有这些逻辑,但每次我们添加状态或想要更改访问逻辑时,这将需要涉足系统以更改与员工有关的每个查询、每个报告、每个部分。
另外 - 我听说函数可以利用索引,但前提是函数是确定性的。这样的函数会是确定性的吗?给定相同的employeeID 和userID,它应该返回相同的结果……除非用户从管理员更改为主管……否则该函数将返回不同的结果。这个函数是确定性的还是非确定性的?
感谢任何见解
【问题讨论】:
-
status在哪个表中?使用JOIN时,请限定所有列名。 -
抱歉 - 状态在员工表中,表示这是否是已终止员工、在职员工等(employee.status)- 已更新
标签: mysql database-design database-optimization