将大表单保存到多个表,规范化和动态查询

时间:2014-02-12 09:24:22

标签: jquery mysql ajax coldfusion coldfusion-10

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

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

等。

或者有更好的方法可以完全忽略这一点吗?!

3 个答案:

答案 0 :(得分:0)

如果你知道你有多达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>

答案 1 :(得分:0)

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

首先,不要检查是否存在所有50个字段,只需检查表单是否已提交。完成后,唯一可能不存在的字段是复选框,也可能是单选按钮。

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

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

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

答案 2 :(得分:0)

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

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

如果您需要处理NULL值,这里有一个在语法中执行此操作的示例:

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