[英]Update table by all records from second table
早晨,
我有两张桌子。 第一个表 (SecurityRules) 是一个安全规则列表:
ID srRight srRole
1 4 NULL
2 2 32
第二个表(项目)是项目列表:
ProjId prRight prRole
1 0 NULL
2 0 32
3 0 NULL
我需要使用 SecurityRules 中的所有记录更新项目列表,并根据两个表中的 Role 更新prRight
列。 Right
值是按位组织的。 我使用以下 SQL 更新查询来执行此操作:
Update Projects
-- Perform binary sum
Set prRight = prRight | srRight
From SecurityRules
Where (srRole is Null) --Always apply srRight if srRole is not defined
OR (srRole is Not Null And srRole=prRole) --Apply right if both roles are equal
预期的结果是:
ProjId prRight prRole
1 4 NULL
2 6 32
3 4 NULL
但我得到:
ProjId prRight prRole
1 4 NULL
2 4 32
3 4 NULL
看起来更新仅由 SecurityRules 表的第一条记录完成。 我需要将 SecurityRules 表中的所有记录应用到 Project 表的所有记录中。 如果我创建一个简单的循环并手动循环来自 SecurityRules 的所有记录,它工作正常,但是如果您必须将 10 个安全规则与 2000 个项目进行比较,则性能非常差...
有什么建议吗?
阿诺
此答案基于此答案中用于生成值的按位 OR 的代码。 它使用 CTE 为每个权限值生成一个位掩码,然后通过对每个权限值中存在的不同位掩码求和来生成整体按位或。 然后使用最后一个 CTE 的输出来更新Projects
表:
WITH Bits AS (
SELECT 1 AS BitMask
UNION ALL
SELECT 2 * BitMask FROM Bits
WHERE BitMask < 65536
),
NewRights AS (
SELECT ProjId, SUM(DISTINCT BitMask) AS NewRight
FROM Projects p
JOIN SecurityRules s ON s.srRole IS NULL OR s.srRole = p.prRole
JOIN Bits b ON b.BitMask & s.srRight > 0
GROUP BY ProjID
)
UPDATE p
SET p.prRight = n.NewRight
FROM Projects p
JOIN NewRights n ON n.ProjId = p.ProjId
结果Projects
表:
ProjId prRight prRole
1 4 null
2 6 32
3 4 null
如果我理解正确,您在srRole
列上有一个直接匹配,然后是一个适用于每个人的默认规则。
最简单的方法(在这种情况下)是在update
使用join
:
update p
Set prRight = p.prRight | srn.srRight | coalesce(sr.srRight, 0)
From Projects p join
SecurityRules srn
on srRole is null left join
SecurityRules sr
on sr.srRole = p.prRole;
这是一个 db<>fiddle。
假设没有默认规则,您可能会更安全。 那个prRight
可能是NULL
:
update p
Set prRight = coalesce(p.prRight, 0) | coalesce(srn.srRight, 0) | coalesce(sr.srRight, 0)
From Projects p left join
SecurityRules srn
on srRole is null left join
SecurityRules sr
on sr.srRole = p.prRole;
也就是说,我建议您考虑修改您的数据模型。 比特摆弄在编程语言中很有趣。 但是,它通常不是数据库中的最佳方法。 而是使用联结表,除非您的应用程序确实需要位开关。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.