C# 如果行的值出现在列表中但不在表中,如何插入行;如果行的值不在列表中但在表中,如何删除行?

C# 如果行的值出现在列表中但不在表中,如何插入行;如果行的值不在列表中但在表中,如何删除行?,c#,sql,sql-server,sql-server-2008-r2,relational-database,C#,Sql,Sql Server,Sql Server 2008 R2,Relational Database,最近,我负责清理一个SQLServer2008数据库和网站代码,我很难想出一个优雅的解决方案来解决以下问题。在网站上,有不同角色的用户,每个角色都有若干权限。网站管理员可以启用或禁用给定角色的权限 目前,数据库尚未规范化,表的设置如下: 角色: RoleID | RoleName | Permissions 1 | Admin | 1;2;3;4;5;etc. 2 | User | 4;23;54;etc. 3 | Person | 54;2;3;

最近,我负责清理一个SQLServer2008数据库和网站代码,我很难想出一个优雅的解决方案来解决以下问题。在网站上,有不同角色的用户,每个角色都有若干权限。网站管理员可以启用或禁用给定角色的权限

目前,数据库尚未规范化,表的设置如下:

角色:

RoleID | RoleName | Permissions
  1    | Admin    | 1;2;3;4;5;etc.
  2    | User     | 4;23;54;etc.
  3    | Person   | 54;2;3;45;etc.
RoleID | RoleName 
  1    | Admin    
  2    | User     
  3    | Person  
权限:

PermissionID | PermissionName
    1        | Random Name
    2        | You get the idea
    3        | etc.
PermissionID | PermissionName
    1        | Random Name
    2        | You get the idea
    3        | etc.
rpID | RoleID | PermissionID
 1   |   1    |      1
 2   |   1    |      2
 3   |   1    |      20
 4   |   2    |      5
 5   |   2    |      2
要更新角色权限,它们基本上会遍历codebehind中的每个复选框,生成权限字符串并在单个调用中更新行

我希望按如下方式规范化数据库:

角色:

RoleID | RoleName | Permissions
  1    | Admin    | 1;2;3;4;5;etc.
  2    | User     | 4;23;54;etc.
  3    | Person   | 54;2;3;45;etc.
RoleID | RoleName 
  1    | Admin    
  2    | User     
  3    | Person  
权限:

PermissionID | PermissionName
    1        | Random Name
    2        | You get the idea
    3        | etc.
PermissionID | PermissionName
    1        | Random Name
    2        | You get the idea
    3        | etc.
rpID | RoleID | PermissionID
 1   |   1    |      1
 2   |   1    |      2
 3   |   1    |      20
 4   |   2    |      5
 5   |   2    |      2
角色权限:

PermissionID | PermissionName
    1        | Random Name
    2        | You get the idea
    3        | etc.
PermissionID | PermissionName
    1        | Random Name
    2        | You get the idea
    3        | etc.
rpID | RoleID | PermissionID
 1   |   1    |      1
 2   |   1    |      2
 3   |   1    |      20
 4   |   2    |      5
 5   |   2    |      2
问题是用户可能希望一次更改20-30个权限。我能想到的唯一方法是删除该角色的每个权限,然后逐个添加每个角色权限关系。通常这不会是一个问题,但我们的数据库与代码存储在一个单独的服务器上,因此单独执行30多个命令的网络延迟将是一个杀手。我还知道,在这种情况下,用户应该很少更新角色,但我正在尝试切换整个数据库以进行规范化,因此这个问题可能会发生在更常用的页面上的其他地方

我想知道在一个或两个SQL命令中是否有一种优雅的方法,可以在角色权限关系不存在时将其插入到RolePermissions表中,并删除任何不再存在的RolePermissions。后面的代码是C,所以我可以很容易地生成所需的任何SQL命令字符串。有什么建议吗


如果需要更多信息,我将提供。

如果您使用的是支持表值参数的较新客户端库,则可以使用它们向存储过程发送数据列表

将类型PermissionList创建为表 PermissionID int不为空 ; 去 创建过程更新权限 @罗莱德国际酒店, @许可列表许可列表只读 像 以t作为 选择 * 从…起 角色权限 哪里 RoleId=@RoleId 合并 T 使用 @许可证列表 在…上 t、 PermissionID=s.PermissionID 当源不匹配时 删去 当目标不匹配时 插入roleID,permissionID 值@roleID,s.PermissionID ; 去 如果有更多数据,并且需要在匹配时更新某些内容,还可以添加一个when matched then update子句


如果您使用的是支持表值参数的较新的客户端库,则可以使用它们向存储过程发送数据列表

将类型PermissionList创建为表 PermissionID int不为空 ; 去 创建过程更新权限 @罗莱德国际酒店, @许可列表许可列表只读 像 以t作为 选择 * 从…起 角色权限 哪里 RoleId=@RoleId 合并 T 使用 @许可证列表 在…上 t、 PermissionID=s.PermissionID 当源不匹配时 删去 当目标不匹配时 插入roleID,permissionID 值@roleID,s.PermissionID ; 去 如果有更多数据,并且需要在匹配时更新某些内容,还可以添加一个when matched then update子句


SQLFiddle完美地满足了我的需求。非常感谢。下周我将在我们的数据库中试用,但看起来应该可以。现在最困难的部分将是计算代码的C部分,但是感谢您提供的链接,这应该不会太困难。如果我能对你的答案投赞成票,我会的。谢谢!漂亮的技巧@Laurence在目标表中使用CTE。它必须被劫持+1 SQLFiddle完美地满足了我的需求。非常感谢。下周我将在我们的数据库中试用,但看起来应该可以。现在最困难的部分将是计算代码的C部分,但是感谢您提供的链接,这应该不会太困难。如果我能对你的答案投赞成票,我会的。谢谢!漂亮的技巧@Laurence在目标表中使用CTE。它必须被劫持+1.