2014-02-12 50 views
1

去年,我发布了一个问题here关于提交一个50字段的表单,以及最好的方法来做到这一点。该解决方案仍在使用中,运行良好。然而,为了构建这些动态查询,我最终得到了很多重复的<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> 

还是有更好的方式来做到这一点,我完全可以俯瞰?!

回答

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

对不起,我本来应该更清晰,但它不是很*是*一致。我重写了这个问题的命名,但它更像arguments.form.departure_date/arguments.form.staffid/arguments.form.otherinfo等。我可以循环arguments.form我假设,但值进入不同的表( staffid进入表2,其他信息进入表3等),并且没有自动的方式知道哪个值在哪个表中。 – sckd

+2

_“有没有自动的方式知道”_ - 所以使用手动方式;每个表都有一个数组,它可以接收可能的字段,并循环这些数据。 –

+0

好吧,我循环遍历arguments.form,然后使用一堆包含每个表的字段以及cfqueryparam的sql类型和maxlength的数组来匹配更新的字段,然后对每个更改执行一次插入/更新?这肯定会让代码更加干净!因此,就我原来的问题而言,在一次写入可能包含多个值的情况下,最终还会产生大量单写操作?感谢所有的建议;绝对在这里学习很多! – sckd

0

是的,还有一种更好的方法来做到这一点,无论如何,我认为。

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

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

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

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

+1

我确定已经在代码的这个阶段之前检查了很久,如果表单被提交,必填字段等。关键是我不想最终写入空行到表中,因为这基本上破坏了规范化的点(可能每个人都有一行)。这是在构建动态插入/更新查询的过程中,我认为事情必须能够得到改进,至少可读性和可扩展性是明智的。 – sckd

+0

_“如果需要表单字段,请确保它不是空字符串。”_ - 空字符串和没有值是两个不同的东西。 –

+0

*如果表单已提交,已经在代码的这个阶段之前检查了很长时间,所需的字段在那里*正确,但我认为想法是将验证(服务器端)与查询逻辑分开,以便当您运行SQL,你已经消除了“空行”的可能性。然后,查询代码只是插入任何给定的数据,因为该数据已经过验证。当然,有时你可以干净地同时做两个 - 但根据你原来的问题,我不确定你的表结构是否适合这种情况。 – Leigh

0

我觉得你这样做的方式很好。

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

如果需要处理空值,这里有办法把你的语法内做到这一点的例子:

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

我认为你是对的,这可以归结为可能提交多少字段的决定。从我所看到的情况来看,它似乎主要是2,3,4个字段,如果可以像Peter建议的那样自动完成,那么可能需要更新每个数据字段设置的一个查询。如果没有,我会保持原样,因为如果许多字段一次更新,当前的解决方案会更好。 – sckd