0

这其实是从这里继续的。

假设一位老师想要更新学生的技能。过程是这样的:

  1. 选择学生姓名。
  2. 查看学生的个人资料。
  3. 单击更新链接。更新页面显示带有复选框的技能列表。
  4. 教师可以检查或取消检查学生的技能。然后点击提交。

例如:

+------+------------------------+
Draw   |   <checkbox checked > 
+------+------------------------+
Read   |   <checkbox> 
+------+------------------------+
Dance  |   <checkbox checked >
+------+------------------------+

所以这就是问题所在;

  1. 如何使用一个 ID 更新多个提交?(将提交值与数据库中的值进行比较)

  2. 当skillid在studentskill表中不存在时,如何添加(INSERT INTO)?

餐桌技巧

+---------+------------+
| skillid | skillname  |
+---------+------------+
| 1       | draw       |
+---------+------------+
| 2       | read       |
+---------+------------+
| 3       | dance      |
+---------+------------+

表学生技能

+----------+----------|
|studentid | skillid  |
+----------+----------+
| 001      | 1        |
| 001      | 2        |
| 002      | 1        |
| 002      | 2        |
| 002      | 3        |
+----------+----------+
4

4 回答 4

4

更新:

事实证明,它StudentSkill包含额外的列(除了 StudentID 和 SkillID)。史蒂夫布莱恩特的回答是这种情况的更好选择。


一种常见的方法是DELETE首先针对所选学生的所有现有技能。然后INSERT是新技能。优点:它比第二种方法更简单一些缺点:每次都删除,即使没有任何更改。

   <!--- change cfsqltypes if needed --->
   <cfquery ...>
      DELETE FROM StudentSkill
      WHERE  studentID = <cfqueryparam value="#form.studentId#" cfsqltype="cf_sql_integer">
   </cfquery>

   <cfquery ...>
        INSERT INTO studenSkill ( studenId, skillId )
        SELECT <cfqueryparam value="#form.studentId#" cfsqltype="cf_sql_integer">
               , skillId
        FROM   skill
        WHERE  skillId IN 
               (
               <cfqueryparam value="#form.skillId#" cfsqltype="cf_sql_integer" list="true">
               )
   </cfquery>



另一种方法是DELETE仅使用未检查/删除的技能。然后使用新添加的 OUTER JOIN技能INSERT。其他任何内容都被视为未更改。

   <cfquery ...>
      DELETE FROM StudentSkill
      WHERE  studentID = <cfqueryparam value="#form.studentId#" cfsqltype="cf_sql_integer">
      <cfif listLen(form.skillId)>
        AND  skillId NOT IN 
             (
               <cfqueryparam value="#form.skillId#" cfsqltype="cf_sql_integer" list="true">
             )
      </cfif>
   </cfquery>

   <cfquery ...>
      INSERT INTO StudentSkill ( studenId, skillId )
      SELECT <cfqueryparam value="#form.studentId#" cfsqltype="cf_sql_integer">
               , s.skillId
      FROM   Skill s LEFT JOIN StudentSkill stu 
                 ON   s.skillID = stu.skillID
                 AND  stu.studentID = <cfqueryparam value="#form.studentId#" cfsqltype="cf_sql_integer">
      WHERE  s.skillId IN 
               (
               <cfqueryparam value="#form.skillId#" cfsqltype="cf_sql_integer" list="true">
               )
      AND    stu.skillID IS NULL
   </cfquery>

注意:确保将两个查询包装在 a 中cftransaction,以便将它们视为一个单元。

于 2012-12-27T12:54:25.857 回答
2

我同意李的回答。我只想添加(这个添加对于评论来说太长了)以下内容:

1)避免删除所有记录然后重新添加它们。有一天,您可能会决定要在该表中添加额外的数据,如果您删除所有技能,则只要运行此代码,您就会丢失它。正确添加 WHERE 子句很容易,因此您不妨这样做。

2) 我建议使用“WHERE NOT EXISTS”而不是 OUTER JOIN 来确保学生技能表中不存在记录。OUTER JOIN 可能会表现得更好一些,但 WHERE NOT EXISTS 在这种情况下应该表现得足够好并且会更清晰。

毕竟,您说“当skillid 在studentskill 表中不存在时”和“WHERE NOT EXISTS”读起来很像。

 <cftransaction>
   <cfquery ...>
      DELETE
      FROM StudentSkill
       WHERE  studentID = <cfqueryparam value="#form.studentId#" cfsqltype="cf_sql_integer">
       <cfif listLen(form.skillId)>
         AND  skillId NOT IN (<cfqueryparam value="#form.skillId#" cfsqltype="cf_sql_integer" list="true">)
       </cfif>
    </cfquery>

    <cfquery ...>
       INSERT INTO StudentSkill ( studentId, skillId )
       SELECT <cfqueryparam value="#form.studentId#" cfsqltype="cf_sql_integer">
                , skillId
       FROM   Skill
       WHERE  skillId IN (<cfqueryparam value="#form.skillId#" cfsqltype="cf_sql_integer" list="true">)
       AND    NOT EXISTS
                (
                    SELECT  1
                    FROM     StudentSkill
                    WHERE   studentID = <cfqueryparam value="#form.studentId#" cfsqltype="cf_sql_integer">
                        AND skillID = Skill.skillID
                )
    </cfquery>
  </cftransaction>

如前所述,将整个事物包装在 cftransaction 中将确保整个更改集发生或根本不发生。

于 2012-12-28T12:29:56.030 回答
0

SQL Server 2008 支持表值参数,但我不知道 ColdFusion 是否支持。

请参阅此答案:将表值参数传递给存储过程

在那个答案中有一个如何将列表作为 XML 传递给存储过程的链接。在存储过程中,您可以将 XML 列表加载到临时表中,并通过加入临时表来插入和删除记录。

于 2012-12-27T10:56:15.117 回答
0

@leigh 提供了一个很好的答案,但另一种方法可能是将您的“选定”选项显示为链接而不是复选框。该链接将提示您确认删除该选项并刷新页面。

然后您的复选框处理将仅用于添加新记录(听起来您已经在做)。这将有助于防止人们意外选中错误的框并删除技能。

于 2012-12-27T15:37:24.957 回答