繁体   English   中英

通过第二个表中的所有记录更新表

[英]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

dbfiddle 上的演示

如果我理解正确,您在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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM