根据有序列表中的更改修改数据库表

时间:2013-03-05 04:38:26

标签: mysql sql coldfusion

这个问题一直困扰着我一个多星期,我迫切需要一个解决方案。

我一直在为基于ColdFusion的CMS系统构建一个模块,它允许用户构建一个包含一系列类的课程。序列顺序代表先决条件,例如:

第1类 2级 3级 第4类

第1类是序列中的第一个类,是进入第2类等所需的......

我已成功允许用户创建所述课程,但编辑它们就是诀窍。在我的编辑界面中,序列在CFSELECT列表框中表示。用户可以在列表上执行4个操作:上移,下移,删除和添加。这使用户能够完全操作列表。

问题:

我们的数据库真的很旧,事实上我们的整个CMS系统都是在99年制造的,所以处理的是一个相当过时且设计不佳的数据集。序列存储如下:

每个课程都存储在一个名为moodle_programs的表中。它的唯一标识符是列mpID,它是一个自动增量。

序列中的每个类都存储在一个名为moodle_course的表中,其唯一标识符是mcID,这是一个自动增量。

我们将关系存储在名为moodle_relationships的查找表中,该表具有以下结构:

  • mrID - 自动增量
  • mpID - 课程ID
  • mcID - 班级ID
  • 有效 - Y / N
  • predecessor - 序列中的第一行设置为0,其余行设置为上一行的mrID

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之外起作用,在更新表并返回编辑课程之后,有时我注意到一个类已经被更改为另一个类,更具体地说是已经存在于序列中的类创建副本。

我认为它与我在主循环中的比较运算符有关,其中对行的考虑是重叠的,尽管我无法看到它在哪里。

有什么想法吗?

1 个答案:

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

注意因为涉及删除,请确保在测试数据库上运行此代码。