假设一个系统,其中People
可以访问Buildings
,而在建筑物中,则可以访问某些Rooms
。
访问权限是根据关联的Permissions
表定义的;对于具有完全访问权限的人员,则是完全访问权限。
db表的定义如下:
buildings (id INT)
rooms (id INT, building_id INT)
people (id INT, has_full_access BIT)
building_permissions (building_id INT, person_id INT)
room_permissions (room_id INT, person_id INT)
当前,我具有表值函数,这些函数会根据人员的ID以及他们是否具有完全访问权限来返回带有建筑物和房间的授权ID的表。
CREATE FUNCTION fn_get_authorised_buildings (@person_id INT, @has_full_access BIT)
RETURNS TABLE AS
RETURN
(
SELECT b.id
FROM buildings b
WHERE @has_full_access = 1
UNION
SELECT b.id
FROM buildings b
INNER JOIN building_permissions bp ON bp.building_id = b.id
WHERE bp.person_id = @person_id
);
CREATE FUNCTION fn_get_authorised_rooms (@person_id INT, @has_full_access BIT)
RETURNS TABLE AS
RETURN
(
SELECT r.id
FROM rooms r
WHERE @has_full_access = 1
UNION
SELECT r.id
FROM rooms r
INNER JOIN room_permissions rp ON rp.room_id = r.id
WHERE rp.person_id = @person_id
);
每当涉及建筑物和房间时,我需要遍历整个系统,我需要根据人员的权限过滤这些表。如果该人具有完全访问权限,则必须包括所有行,否则仅包括他们有权访问的行。
我的查询(简体)看起来像这样:
DECLARE @person_id INT = 123
DECLARE @has_full_access BIT = 1
DECLARE @authorised_buildings TABLE (id INT)
INSERT INTO @authorised_buildings SELECT id FROM fn_get_authorised_buildings(@person_id , @has_full_access)
DECLARE @authorised_rooms TABLE (id INT)
INSERT INTO @authorised_rooms SELECT id FROM fn_get_authorised_rooms(@person_id, @has_full_access)
--Example A
SELECT *
FROM buildings b
INNER JOIN rooms r ON r.building_id = b.id
WHERE 1 = 1
AND b.id IN (SELECT id FROM @authorised_buildings)
AND r.id IN (SELECT id FROM @authorised_rooms)
--Example B
SELECT *
FROM floors f -- or other tables that are related to rooms
INNER JOIN rooms r ON r.floor_id = f.id
WHERE 1 = 1
AND r.id IN (SELECT id FROM @authorised_rooms)
有更好的方法吗?
编辑: Here摆弄了摆设
答案 0 :(得分:0)
您可以创建一个包含所有逻辑的视图,
CREATE VIEW bulding_rooms_per_person AS
SELECT p.id AS person_id, b.id as building_id, r.id AS room_id
FROM people p
LEFT JOIN building_permissions bp ON bp.person_id = p.id
LEFT JOIN room_permissions rp ON rp.person_id = p.id
INNER JOIN buildings b ON b.id = bp.building_id OR p.has_full_access = 1
INNER JOIN rooms r ON r.building_id = b.id AND (r.id = rp.room_id OR p.has_full_access = 1)
然后对其进行查询:
SELECT * from bulding_rooms_per_person WHERE person_id = @person_id