Coldfusion:如何使用一个ID更新多个记录

时间:2012-12-27 10:37:51

标签: sql-server coldfusion

这实际上是从here继续。

说老师想要更新学生的技能。过程如下:

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

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

    所以这就是问题;

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

    2. 如果表studentkill中不存在技能,我该如何添加(INSERT INTO)?

    3. 表技能

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

      表studentkill

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

4 个答案:

答案 0 :(得分:4)

更新:

事实证明StudentSkill包含其他列(超出StudentID和SkillID)。对于那种情况,Steve Bryant's answer是更好的选择。


一种常见的方法是先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 JOININSERT技能。其他任何事情都被认为没有改变。

   <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>

注意:请务必将这两个查询包装在cftransaction中,以便将它们视为一个单元。

答案 1 :(得分:2)

我同意Leigh的回答。我只想添加(并且这个添加内容太长而无法发表评论)以下内容:

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

2)我建议使用“WHERE NOT EXISTS”而不是OUTER JOIN来确保学生技能表中不存在记录。 OUTER JOIN可能会表现得更好一点,但在这种情况下,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中将确保发生一系列改变或根本不发生。

答案 2 :(得分:0)

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

请参阅此答案:Passing a Table Valued parameter to a stored procedure

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

答案 3 :(得分:0)

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

然后你的复选框处理只会添加新记录(这听起来像你已经在做)。这有助于防止人们意外地检查错误的方框并删除该技能。