sql - 存储用户帐户权限的最佳方式?

标签 sql session permissions coldfusion cfloop

我有与我的应用程序中的每个帐户相关联的权限记录。每个账户根据账户类型可以有一个或多个权限记录。这是示例:

<cfquery name="qryUserPerm" datasource="#Application.dsn#">
    SELECT AccessType, AccessLevel, State, City, Building
    FROM Permissions
    WHERE AccountID = <cfqueryparam cfsqltype="cf_sql_integer" value="#trim(session.AccountID)#">
</cfquery>

上面的查询将为其中一个帐户生成这样的数据:

RecID   AccountID   AccessType  AccessLevel State     City    Building
70      285A637D82B9    F            B        NY    New York    8010
71      285A637D82B9    F            B        NY    New York    5412
73      285A637D82B9    F            B        NY    New York    6103
74      285A637D82B9    F            B        NY    New York    3106

正如您在上面看到的,该帐户分配了 4 条记录。访问类型可以是完全 F 或仅查看 V。访问级别可以是州“S”、城市“C”或建筑物“B”。用户当时只能分配给他们一个访问级别,因此例如没有用户可以分配城市和州级别的情况。我的问题是,针对特定访问级别组织查询数据的最佳方式是什么?在这种情况下,我必须合并列表或数组中的 4 条记录。 State 级别只能分配一个权限记录,City 和 Building 可以有多个记录。这是我所拥有的示例:

<cfset local.permissionType = "">
<cfset local.permissionLevel = "">
<cfset local.permissionList = "">

<cfloop query="qryUserPerm">
    <cfif qryUserPerm.AccessLevel EQ "S">
         <cfset local.permissionType = qryUserPerm.AccessType>
         <cfset local.permissionLevel = qryUserPerm.AccessLevel>
         <cfset local.permissionList = listAppend(permissionList, "", ",")>
    <cfelseif qryUserPerm.AccessLevel EQ "C">
         <cfset local.permissionType = qryUserPerm.AccessType>
         <cfset local.permissionLevel = qryUserPerm.AccessLevel>
         <cfset local.permissionList = listAppend(permissionList, qryUserPerm.City, ",")>
    <cfelseif qryUserPerm.AccessLevel EQ "B">
         <cfset local.permissionType = qryUserPerm.AccessType>
         <cfset local.permissionLevel = qryUserPerm.AccessLevel>
         <cfset local.permissionList = listAppend(permissionList, qryUserPerm.Building, ",")>
    <cfelse>
         <cfset local.permissionType = "">
         <cfset local.permissionLevel = "">
         <cfset local.permissionList = listAppend(permissionList, "", ",")>
    </cfif>
</cfloop>

permissionTypepermissionLevel 保留在循环中似乎是多余的,但我目前不知道更好的方法来避免这种情况。如果我必须比较权限列表,这也会使过程变得非常困难。我将不得不运行相同的过程并构建列表,以便在当前登录的用户更改其权限的情况下将其与 Session.premissionList 进行比较。有没有办法将这些记录与 SQL 合并?或者这种方法是更好的选择?

最佳答案

这可以在 SQL 本身中完成,这可能比在代码中操作数据的性能更高。

数据的一个问题是 StateCityBuilding 列需要逆透视然后变成逗号 -分隔列表。

由于您使用的是 SQL 2008,因此您可以访问所需的功能。

查询是:http://sqlfiddle.com/#!18/0f4f7/1

; WITH cte AS (
  SELECT
      AccountID, AccessType, AccessLevel
      , CASE AccessLevel
          WHEN 'S' THEN State
          WHEN 'C' THEN City
          WHEN 'B' THEN Building
        END AS Permissions
  FROM Permissions
  WHERE AccountID = 
    <cfqueryparam cfsqltype="cf_sql_integer" value="#session.AccountID#"> 
    /* Dynamic variable here */
)
SELECT DISTINCT AccountID, AccessType, AccessLevel
  , CASE 
      WHEN AccessLevel = 'S' THEN Permissions 
      ELSE LEFT(ca.pl, COALESCE(LEN(ca.pl),0)-1)
    END AS PermissionList
FROM cte
CROSS APPLY (
  SELECT p.Permissions + ', '
  FROM cte p
  WHERE p.AccountID = cte.AccountID
    AND p.AccessType = cte.AccessType
    AND p.AccessLevel = cte.AccessLevel
  FOR XML PATH('')
) ca (pl)     ;

我从 CTE 开始,根据 AccessLevel 构建 Permissions 的“unpivoted”列表。如果这可以放在 SQL View 中,您可以在此处省略 WHERE 语句,并在调用 View 时调用它。如果您可以将 View 放入数据库中,我会更喜欢 View 。

获得 CTE 后,我只需选择基本列(AccountIDAccessTypeAccessLevel,然后我CROSS APPLY Permissions 的逗号分隔列表。我使用 FOR XML PATH('') 构建该逗号分隔列表。

如果能够将其转换为 View ,那将是一个简单的

<cfquery name="qryUserPerm" datasource="#Application.dsn#">
    SELECT AccessType, AccessLevel, PermissionList
    FROM myPermissionsView
    WHERE AccountID = <cfqueryparam cfsqltype="cf_sql_integer" value="#trim(session.AccountID)#">
</cfquery>

如果没有,您将不得不尝试在 cfquery 标记内运行上述完整查询。

这应该会给你一个像这样的数据集:

| AccessType | AccessLevel |         PermissionList |
|------------|-------------|------------------------|
|          F |           B | 8010, 5412, 6103, 3106 |

您只需处理一个结果,无需循环。

============================================= =======================

如果您想走代码内路线,我仍然建议您尝试使用 cfscript 构建结构。但是,如果您可以拥有多个 AccessLevel,您的结果可能不是您认为的那样。您必须仔细检查您的数据。

  local.permissionType = q2.AccessType ;
  local.permissionLevel = q2.AccessLevel ;

  switch( q2.AccessLevel ) {
    case "S" :  local.permissionList = q2.State ;
      break ;
    case "C" :  local.permissionList = ListRemoveDuplicates(ValueList(q2.City)) ;
      break ;
    case "B" :  local.permissionList = ListRemoveDuplicates(ValueList(q2.Building)) ;
      break ;
  }

https://trycf.com/gist/e811ec86f0d5a52fd9ce703f897cb5aa/acf2016?theme=monokai

关于sql - 存储用户帐户权限的最佳方式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51527787/

相关文章:

sql - 使用 Rails 和 SQL 在数据库中保存多条温度曲线(同时测量)的最佳方法是什么

sql - 从集合类型插入表 oracle 12c - ORA-00902 : invalid datatype

node.js - 如何检查redis中是否已存在 session ID

ios - 使用 ACAccount for Facebook iOS 7 获取电子邮件

java - Liferay 只显示有子项的页面

sql - 如何将表中的数据添加到 PostgreSQL 中的最大对象查询

SQL如何用单个查询替换同一个表的单个字段中的多个字符

php - 消息 : ini_set(): A session is active. 您此时无法更改 session 模块的 ini 设置

javascript - 浏览器刷新 - 丢失服务堆栈身份验证 session 数据

java - Android Studio 权限拒绝