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

标签 mysql sql coldfusion

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

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

一级 2级 3级 4类

第 1 类是序列中的第一个类,需要才能继续第 2 类,等等...

我已经成功地允许用户创建上述类(class),但是编辑它们是个窍门。在我的编辑界面中,序列显示在 CFSELECT 列表框中。用户可以在列表上执行 4 个操作:上移、下移、删除和添加。这使用户能够完全操纵列表。

问题:

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

每门类(class)都存储在一个名为 moodle_programs 的表中。它的唯一标识符是自动递增的 mpID 列。

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

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

  • mrID - 自动递增
  • mpID - 类(class) ID
  • mcID - 类 ID
  • 活跃 - 是/否
  • predecessor - 序列中的第一行设置为0,其余为上一行的mrID

moodle_relationships 中的一行代表序列中的一个类。

这意味着我的算法基本上需要考虑以下几点:

如果当前类(class)列表 = 该类(class)的当前行数 然后用正确的值覆盖 mcID 否则如果当前类(class)列表<该类(class)的当前行数 然后覆盖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,然后当数据库中的项目被修改时 count += 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>

从我所看到的情况来看,它是有效的,除了一个流氓错误,在更新表格并返回编辑类(class)之后,有时我注意到一个类已更改为另一个类,更具体地说,一个类已经存在于序列中创建一个副本。

我认为这与我在主循环中的比较运算符有关,虽然我看不到它在哪里,但对行的考虑是重叠的。

有什么想法吗?

最佳答案

有很多方法可以做到这一点。一种方法是删除所有现有记录并输入一个新记录集。

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

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

关于mysql - 根据有序列表中的更改修改数据库表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15215922/

相关文章:

SQL创建语句接近自动增量的语法不正确

coldfusion - 列表 DeleteValue - 删除列表的一部分

php - Fusebox 框架的 future

java - 尝试通过JDBC在MySQL中存储SecretKey、加密密码

mysql - SQL:达到 unix 时间时如何删除一行?

mysql - 错误 1396 (HY000) : Operation CREATE USER failed for 'username' @'localhost' IDENTIFIED BY 'mypassword' ;

java - 为什么我的 JUnit 测试用例在作为测试套件和单独的 Junit 文件运行时表现出不同的输出

sql - 在DateTime字段中的两个日期之间进行选择-SQL Server

mysql - 查找时间值已被使用并将其乘以 SQL 中跨表的数量

ColdFusion 的 Duplicate 函数不会复制查询的元数据