2

我有一个带有多个复选框的动态表单,在提交时我想只使用更改状态的复选框值CFSTOREDPROC在另一个表单中运行。cfloop

到目前为止,下面是一个我正在尝试测试的粗略概念,但我确信我创建数组的方式会有问题。如果有人可以就可能的解决方案提供反馈,我将不胜感激。

HTML/CF 表格:

<form action="self.cfm" method="post" name="permissions">
 <input type="hidden" name="User_ID" value="<CFOUTPUT>#User_ID#</CFOUTPUT>">
<table>
<CFLOOP QUERY="getNthPermission">
<tr><td>#getNthPermission.Permission_Name#</td><td><input type="checkbox" value="#getNthPermission.Permission_ID#" name="#getNthPermission.Permission_Name#" <CFIF LISTVALUECOUNT(VARIABLES.UserPermission_ID_List,getNthPermission.Permission_ID) NEQ 0>CHECKED</CFIF>></td></tr>
</CFLOOP>
</table>
<input type="submit" name="submit" value="Update">
</form>

冷熔作用:

<CFSET VARIABLES.Permission_ID_List = ValueList(getUserPermission.Permission_ID)>
    <cfset changed_permissions=ArrayNew()>
    <CFLOOP QUERY="getNthPermission">
    //If it was checked when the form was created but was unchecked by the user add it to my array.
    <CFIF LISTVALUECOUNT(VARIABLES.UserPermission_ID_List,getNthPermission.Permission_ID) NEQ 0  AND !IsDefined(FORM.#getNthPermission.Permission_Name#)>
    <cfset changed_permissions[getNthPermission.Permission_ID]>
    <CFELSEIF LISTVALUECOUNT(VARIABLES.UserPermission_ID_List,getNthPermission.Permission_ID) EQ 0  AND IsDefined(FORM.#getNthPermission.Permission_Name#)>
    //If it wasn't checked when the form was built but was checked by the user add it to my array.
    <cfset changed_permissions[getNthPermission.Permission_ID]>
    </CFIF>
    </CFLOOP>

//现在循环遍历刚刚创建的数组并将存储过程传递给我的值

<CFLOOP from="1" to="#arrayLen(changed_permissions)#" index="i">
    <CFSTOREDPROC DATASOURCE="#MYDB_DSN#" PROCEDURE="Update_UserPermission">
        <CFPROCPARAM DBVARNAME="@PermissionList" VALUE="#changed_permissions[i]#" TYPE="IN" CFSQLTYPE="cf_sql_longvarchar">
        <CFPROCPARAM DBVARNAME="@User_ID" VALUE="#FORM.User_ID#" CFSQLTYPE="cf_sql_integer">
    </CFSTOREDPROC>
</CFLOOP>

更新:

我正在使用我不参与设置的数据库配置,其中包含以下表:

  • 权限表 (permission_name, ID) -权限列表
  • 用户表(用户名,ID)
  • User_Permissions 表(Permissions_ID、User_ID)-包含用户有权访问的每个权限的条目。

因此,当复选框被选中/取消选中时,我要么添加一个新条目,要么删除一个。已经存在的存储过程会执行(或者我希望它会执行)。

4

1 回答 1

3

三张桌子是一个很好的设置。我担心它是一个单一的表或值存储为 csv 列表 {颤抖}。仍然无法很好地可视化您的表单,但是..根据您的描述,听起来使用一些查询而不是循环来执行此操作会更简单。

首先,为复选框提供与“Permission_IDList”相同的名称,因此 id 将作为列表提交。然后将该 ID 列表与以下选项之一一起使用:

选项 1:删除/全部插入

我经常对简单联结表使用的一种方法是首先删除所有现有用户权限。然后使用 INSERT/SELECT插入新权限。使用 INSERT/SELECT 的两大优点是它消除了循环的需要,并且还提供了内置验证。

这是最简单的选项之一,但不如选项 2 精确,因为它每次都会删除所有记录。所以从技术上讲,它可能比许多情况下需要做的工作多一点。尽管除非您处理大量记录,否则差异通常可以忽略不计。这些方面的东西(未经测试):

    --- First remove all existing permissions for User
    DELETE FROM User_Permissions 
    WHERE  User_ID = <cfqueryparam value="#FORM.User_ID#" cfsqltype="cf_sql_integer">

    --- Now re-insert current/new permissions 
    INSERT INTO User_Permissions  ( User_ID, Permissions_ID )
    SELECT  u.ID AS User_ID
            , p.ID AS Permissions_ID
    FROM    UserTable u CROSS JOIN PermissionTable p   
    WHERE   u.ID = <cfqueryparam value="#FORM.User_ID#" cfsqltype="cf_sql_integer">
    AND     p.ID IN 
           (
                <cfqueryparam value="#FORM.Permission_IDList#" cfsqltype="cf_sql_integer" list="true">
           )

选项 2:删除更改/插入添加

另一种选择是使用查询来识别和删除已删除的权限,即未选中的权限。然后使用 INSERT/SELECT 插入已添加的权限。其余保持不变。它比选项 1 稍微复杂一点,但更精确,因为它只删除或添加实际更改的内容。同样,未经测试,但类似这样:

    --- existing id's NOT in the new list were UN-checked
    DELETE FROM User_Permissions 
    WHERE  User_ID = <cfqueryparam value="#FORM.User_ID#" cfsqltype="cf_sql_integer">
    AND    Permissions_ID NOT IN 
           (
                <cfqueryparam value="#FORM.Permission_IDList#" cfsqltype="cf_sql_integer" list="true">
           )


    INSERT INTO UserPermissions ( User_ID, Permissions_ID )
    SELECT u.ID AS User_ID
            , p.ID AS Permissions_ID
    FROM   UserTable u 
                CROSS JOIN PermissionsTable p 
                LEFT JOIN UserPermissions up ON up.User_ID = u.ID AND up.Permissions_ID = p.ID
    --- this user + permission does not already exist
    WHERE  up.Permissions_ID IS NULL        
    AND    u.ID = <cfqueryparam value="#FORM.User_ID#" cfsqltype="cf_sql_integer">
    AND    p.ID IN 
        (
                    <cfqueryparam value="#FORM.Permission_IDList#" cfsqltype="cf_sql_integer" list="true">

        )

注意:确保将两个查询包装在一个事务中,以便将它们视为一个单元,即要么都成功,要么都失败。

于 2016-03-03T02:17:58.187 回答