这个问题一直困扰着我一个多星期,我迫切需要一个解决方案。
我一直在为基于ColdFusion的CMS系统构建一个模块,它允许用户构建一个包含一系列类的课程。序列顺序代表先决条件,例如:
第1类 2级 3级 第4类
第1类是序列中的第一个类,是进入第2类等所需的......
我已成功允许用户创建所述课程,但编辑它们就是诀窍。在我的编辑界面中,序列在CFSELECT列表框中表示。用户可以在列表上执行4个操作:上移,下移,删除和添加。这使用户能够完全操作列表。
问题:
我们的数据库真的很旧,事实上我们的整个CMS系统都是在99年制造的,所以处理的是一个相当过时且设计不佳的数据集。序列存储如下:
每个课程都存储在一个名为moodle_programs的表中。它的唯一标识符是列mpID,它是一个自动增量。
序列中的每个类都存储在一个名为moodle_course的表中,其唯一标识符是mcID,这是一个自动增量。
我们将关系存储在名为moodle_relationships的查找表中,该表具有以下结构:
moodle_relationships中的一行代表序列中的一个类。
这意味着我的算法基本上需要考虑以下内容:
如果当前班级列表=该班级的当前行数 然后用正确的值覆盖mcID 否则,如果当前的班级列表是<该课程的当前行数 然后覆盖mcID直到到达序列的末尾,并将所有剩余的行设置为active ='N'
这是通过这个算法完成的:
//comma deliminated list of mcIds before edit
<CFSET preclasses = listToArray(#PREsectionOrder#, ",")>
// number of classes
<CFSET numpreClasses = ArrayLen(#preclasses#)>
//comma deliminated list of mcIds after edit
<CFSET classes = listToArray(#sectionOrder#, ",")>
//number of classes
<CFSET numClasses = ArrayLen(#classes#)>
<!--- Modify moodle_relationships --->
<CFQUERY NAME="Course_seq" DATASOURCE="#CMS_SD#">
SELECT *
FROM moodle_relationships
WHERE mpID = #URL.id#
</CFQUERY>
<CFSET row = 0>
<CFLOOP QUERY="Course_seq">
<CFSET row = #Course_seq.CurrentRow#>
<CFQUERY NAME="relation" DATASOURCE="#CMS_SD#">
SELECT *
FROM moodle_relationships
WHERE mrID=#Course_seq.mrID#
</CFQUERY>
<CFIF #row# LTE #numClasses#>
<!--Change Classes-->
<CFQUERY NAME="change" DATASOURCE="#CMS_SD#">
UPDATE moodle_relationships
SET mcID='#classes[row]#', active='Y'
WHERE mrID=#relation.mrID#
</CFQUERY>
<CFELSEIF (#row# GT #numClasses#) AND (#row# LTE #numpreClasses#)>
<!--Set to N-->
<CFQUERY NAME="set" DATASOURCE="#CMS_SD#">
UPDATE moodle_relationships
SET active='N'
WHERE mrID=#relation.mrID#
</CFQUERY>
</CFIF>
</CFLOOP>
现在我遇到的问题是当前的类序列超过了前一个序列中的行数。我需要以某种方式注意何时发生这种情况,并为剩余的行执行INSERT语句。
例如:
原始序列 - 1级,2级,3级 新序列 - 1级,2级,3级,4级
由于我的循环只会迭代三次,所以从不考虑第四个索引。
我该如何解决这个问题?
修改
我设法通过创建CFSET count = 0来修复此问题,然后在数据库中修改项目时计数+ = 1。之后我创建了这段代码片段。
<CFIF #count# LT #numClasses#>
<CFLOOP FROM="#count#" TO="#numClasses#" INDEX="i">
<CFQUERY NAME="mrID" DATASOURCE="#CMS_SD#">
SELECT MAX(mrID) AS MAXmrID
FROM moodle_relationships
WHERE mpID = #URL.id#
</CFQUERY>
<CFSET ID = #mrID.MAXmrID# - 1>
<CFQUERY NAME="new" DATASOURCE="#CMS_SD#">
INSERT INTO moodle_relationships (mpID, mcID, active, predecessor)
VALUES ('#URL.id#', '#classes[i]#', 'Y', '#ID#')
</CFQUERY>
</CFLOOP>
它可以从我看到的除了流氓bug之外起作用,在更新表并返回编辑课程之后,有时我注意到一个类已经被更改为另一个类,更具体地说是已经存在于序列中的类创建副本。
我认为它与我在主循环中的比较运算符有关,其中对行的考虑是重叠的,尽管我无法看到它在哪里。
有什么想法吗?
答案 0 :(得分:1)
有很多方法可以做到这一点。一种方法是删除所有现有记录并输入新的记录。
<cfscript>
/* Count the number of classes before the edit */
preclasses = listToArray(PREsectionOrder, ",");
numpreClasses = ArrayLen(preclasses);
/* Count the number of classes after edit */
classes = listToArray(sectionOrder, ",");
numClasses = ArrayLen(classes);
</cfscript>
<!--- Making sure we have a 'numeric' URL id --->
<CFPARAM name="URL.id" default="0" type="numeric" />
<CFSET courseId = URL.id />
<!--- Only continue if the courseId is not the default 0--->
<CFIF courseId neq 0>
<!--- Delete the existing course and its combination classes --->
<!--- Query checks for a specific course and class id --->
<CFQUERY NAME="Course_seq" DATASOURCE="#CMS_SD#">
DELETE
FROM moodle_relationships
WHERE mpID = <cfqueryparam cfsqltype="cf_sql_numeric" value="#courseId#" />
AND mcID IN (<cfqueryparam cfsqltype="cf_sql_numeric" value="#PREsectionOrder#" list="true" separator=","/>)
</CFQUERY>
<!--- Create and Set the predecessor value to default 0--->
<cfset predecessorValue = 0 />
<!--- Loop over the array of new classId and Insert them--->
<CFLOOP array="#classes#" index="newClass">
<CFQUERY NAME="insertingNewCourse" DATASOURCE="#CMS_SD#">
INSERT INTO moodle_relationships
(mpID, mcID, active, predecessor)
VALUES (
<cfqueryparam cfsqltype="cf_sql_numeric" value="#courseId#" />,
<cfqueryparam cfsqltype="cf_sql_numeric" value="#newClass#" />,
<cfqueryparam cfsqltype="cf_sql_varchar" value="Y" />,
<cfqueryparam cfsqltype="cf_sql_numeric" value="#predecessorValue#" />
)
</CFQUERY>
<!--- The first one goes as zero. the next one shall be the just inserted classId --->
<cfset predecessorValue = newClass />
</CFLOOP>
</CFIF>
注意:因为涉及删除,请确保在测试数据库上运行此代码。