这实际上是从here继续。
说老师想要更新学生的技能。过程如下:
E.g:
+------+------------------------+
Draw | <checkbox checked >
+------+------------------------+
Read | <checkbox>
+------+------------------------+
Dance | <checkbox checked >
+------+------------------------+
所以这就是问题;
如何使用一个ID更新多个提交? (将提交值与数据库中的提交值进行比较)
如果表studentkill中不存在技能,我该如何添加(INSERT INTO)?
表技能
+---------+------------+
| skillid | skillname |
+---------+------------+
| 1 | draw |
+---------+------------+
| 2 | read |
+---------+------------+
| 3 | dance |
+---------+------------+
表studentkill
+----------+----------|
|studentid | skillid |
+----------+----------+
| 001 | 1 |
| 001 | 2 |
| 002 | 1 |
| 002 | 2 |
| 002 | 3 |
+----------+----------+
答案 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 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>
注意:请务必将这两个查询包装在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提供了一个很好的答案,但另一种方法可能是将“选定”选项显示为链接而不是复选框。该链接将提示您确认删除该选项并刷新页面。
然后你的复选框处理只会添加新记录(这听起来像你已经在做)。这有助于防止人们意外地检查错误的方框并删除该技能。