【问题标题】:Saving large form to multiple tables, normalization and dynamic queries将大型表单保存到多个表、规范化和动态查询
【发布时间】:2014-02-12 09:24:21
【问题描述】:

去年我发布了一个问题here,关于提交 50 字段的表单,以及执行此操作的最佳方法。该解决方案仍在使用中,并且运行良好。但是,为了构建这些动态查询,我最终会重复很多<cfif>,我想知道是否有更好的方法来处理这个问题。虽然代码最终变得“混乱”,但数据库当然因此非常干净,并且写入次数也保持在最低限度,但是是否有 更好的 方法来执行以下操作?

<cfif StructKeyExists(arguments.form,"data1") or StructKeyExists(arguments.form,"data2") or StructKeyExists(arguments.form,"data3")>
  <cfquery>
    insert into table1 (
      <cfif StructKeyExists(arguments.form,"data1")>data1,</cfif>
      <cfif StructKeyExists(arguments.form,"data2")>data2,</cfif>
      <cfif StructKeyExists(arguments.form,"data3")>data3,</cfif>
      userid
    )
    values (
      <cfif StructKeyExists(arguments.form,"data1")><cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.form.data1#" maxlength="30">,</cfif>
      <cfif StructKeyExists(arguments.form,"data2")><cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.form.data2#" maxlength="10">,</cfif>
      <cfif StructKeyExists(arguments.form,"data3")><cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.form.data3#" maxlength="25">,</cfif>
      <cfqueryparam cfsqltype="cf_sql_smallint" value="#arguments.form.userid#" maxlength="5">
    )
    on duplicate key update 
      <cfif StructKeyExists(arguments.form,"data1")>data1=values(data1),</cfif>
      <cfif StructKeyExists(arguments.form,"data2")>data2=values(data2),</cfif>
      <cfif StructKeyExists(arguments.form,"data3")>data3=values(data3),</cfif>
      userid=values(userid)
  </cfquery>
</cfif>

出于某种原因,这种“感觉”是错误的。例如,宁愿有更多的写入,将每个值分成自己的更新,这样会不会更聪明,就像这样:

<cfif StructKeyExists(arguments.form,"data1")>
  <cfquery>
    insert into table1 (data1,userid)
    values (<cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.form.data1#" maxlength="30">,<cfqueryparam cfsqltype="cf_sql_smallint" value="#arguments.form.userid#" maxlength="5">)
    on duplicate key update data1=values(data1),userid=values(userid)
  </cfquery>
</cfif>

等等。

或者有没有更好的方法来做到这一点,我完全忽略了?!

【问题讨论】:

    标签: jquery mysql ajax coldfusion coldfusion-10


    【解决方案1】:

    如果您知道您有多达 50 个字段,并且它们的名称都是一致的 (data1 ... dataN),那么我只需要一个循环。比如:

    <cfloop index="i" from="1" to="50">
        <cfif StructKeyExists(arguments.form, "data#i#")>
            <cfquery>
                insert into table1 (data#i#,userid)
                values (<cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.form['data' & i]#" maxlength="30">,<cfqueryparam cfsqltype="cf_sql_smallint" value="#arguments.form.userid#" maxlength="5">)
                on duplicate key update data#i#=values(data#i#),userid=values(userid)
            </cfquery>
        </cfif>
    </cfloop>
    

    【讨论】:

    • 对不起,我应该更清楚,但它并不完全一致。我重写了问题的命名,但它更像 arguments.form.departure_date / arguments.form.staffid / arguments.form.otherinfo 等。我可以遍历我假设的 arguments.form,但值进入不同的表( Staffid 在表 2 中,otherinfo 在表 3 中等等),并且没有自动方法知道哪个值在哪个表中。
    • “没有自动知道的方式” - 所以使用手动方式;每个表的一个数组,其中包含它可以接收的可能字段,并循环遍历这些字段。
    • 好的,所以我遍历arguments.form,然后使用一堆数组将更新的字段与其正确的表匹配,这些数组包括每个表的字段以及cfqueryparam的sql类型和maxlength,然后执行每次更改一次插入/更新?这肯定会使代码保持整洁!因此,就我最初的问题而言,在一次写入可能包含多个值的情况下,我也会得到一堆单一写入?感谢所有的建议;在这里肯定学到很多东西!
    • 刚刚有了另一个想法 - 您可以在参数上添加额外的属性并使用 getMetadata 来识别是什么 - 相同的基本想法,只是可能更整洁一点,而不是创建单独的数组/结构方式。
    • 每次更改不要进行一次更新(查询)!最好将其合并到一个查询中。
    【解决方案2】:

    是的,无论如何,我认为有更好的方法。

    首先,不是检查所有 50 个字段是否存在,而是检查表单是否已提交。完成此操作后,唯一可能不存在的字段是复选框和单选按钮。

    接下来,在获取 cfquery 标记之前执行所有条件逻辑。除了复选框和单选按钮,您不是在检查值是否存在,而是在检查有效性。如果需要表单字段,请确保它不是空字符串。还要确保数字和日期字段的数据类型正确。

    在此阶段,您可能希望设置一些变量以用于 cfqueryparam 的 null 属性。例如,如果您有一个可选的数字字段并且用户没有填写它,您将需要一个等于 true 的变量,以便数据库接收一个空值。空字符串仅适用于文本字段。

    另外请记住,数据的质量比代码的外观更重要。虽然可读的代码很重要,但您不会在 10 行或更少的代码中处理 50 个表单字段。

    【讨论】:

    • 我肯定早在代码的这个阶段之前就已经检查过表单是否已提交,必填字段是否存在等。关键是我不想最终将空行写入表,因为这基本上破坏了正常化的点(那么每人可能有一排)。在动态插入/更新查询的构建中,我认为事情必须能够得到改进,至少在易读性和可扩展性方面是明智的。
    • “如果需要表单字段,请确保它不是空字符串。” - 空字符串和没有值是两个不同的东西。
    • 如果表单已提交,早在代码的这个阶段之前就已经检查过,必填字段在那里 对,但我认为想法是将验证(服务器端)与查询逻辑,以便在您运行 SQL 时,您已经消除了“空行”的可能性。然后查询代码只插入给定的任何内容,因为该数据已经过验证。诚然,有时您可以同时做到这两点,但根据您最初的问题,我不确定您的表结构是否适合这种情况。
    • 我正在使用“structkeyExists”来检查是否必须运行该特定查询或查询中的该特定行。验证已经在早些时候进行了,但这只是关于构建动态 sql 查询,提交到大约 10 个不同的表,具体取决于编辑的内容。
    【解决方案3】:

    我认为你这样做的方式很好。

    我不会将您的插入/更新分解为每个数据字段的单独查询。当提交大量字段时,这将导致更多开销。想象一下,所有 50 个表单字段都已提交,50 个查询,哎呀。

    如果您需要处理 NULL 值,以下是在您的语法中执行此操作的示例:

    <cfif structKeyExists(arguments.form, "data1"><cfqueryparam value="#arguments.form.data1#" null="#(NOT len(arguments.form.data1))#" cfsqltype="cf_sql_integer">,</cfif>
    

    【讨论】:

    • 我认为您是对的,因为这归结为关于可能提交多少字段的决定。从我所看到的情况来看,它似乎主要是 2、3、4 个字段,可能证明每个数据字段设置更新一个查询是合理的,前提是可以像 Peter 建议的那样自动完成。如果没有,我将保持原样,因为如果同时更新大量字段,当前的解决方案会更好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-21
    • 1970-01-01
    • 1970-01-01
    • 2015-06-11
    • 2017-03-07
    相关资源
    最近更新 更多