如果我有一个包含任意数量变量的表单,那么在coldfusion中有一个好方法可以消除为插入或更新查询再次输入变量名称的需要。 例如,在下面,我必须输入变量名strPersonName 3次,不能以某种方式输入一次吗?:
<form> <input name="strPersonName" >... etc... </form>
......提交后......
<cfquery >
Insert into sometable (strPersonName) VALUES ('#FORM.strPersonName#')
</cfquery>
答案 0 :(得分:1)
Control + C和Control + V是你的朋友。
严肃地说,听起来你正试图为cfloop设计一个方法来为你完成大部分工作。从理论上来说这听起来很精彩,但在实践中它会变得一团糟,正如我所展示的那样,而且它可能会导致错误或打开你的代码而导致恶作剧。
例如,如果我有表格..
FirstName - Text Box
LastName - Text Box
State - Select box, 50 states.
我可以在提交时执行此操作。
<cfquery>
<cfset icount = 0>
<cfset istring = "">
Insert into Persons(<cfloop list="#form.fieldnames#" index="i"><cfset icount = icount + 1>
<cfif not listfindnocase("comma,delimited,list,of,fields,you,dont,want,to,insert",i)>
<cfset istring = istring & "," & i>
</cfif>
</cfloop><cfset istring = ReReplace(istring,"(^,|,$)","","ALL")>#istring#)
<cfset icount = 0>
Values(<cfloop list="#istring#" index="ix"><cfset icount = icount + 1>#form[ix]#<cfif icount neq listlen(istring)>,</cfif>)
</cfquery>
我可能会列出&#34; btnGo&#34; (如果这是我的提交按钮的名称)在逗号,分隔符,列表中...&#39;我在上面提到过。
这只是建立了基本的查询(或关闭,我没有测试)。但是有很多问题......这是一个烂摊子,它是垃圾阅读。您必须考虑在字符串末尾添加逗号。您还必须考虑不同的数据类型,因此您几乎不需要具有相应键名的结构,因此您可以将值标识为int或字符串(用于&#39;“&#39;目的)。
有些情况下,循环使用字段名称的子集会有其使用,但它不会单独跳过编码时间。
此外,您似乎没有使用<cfqueryparam>
。你需要。 CFQueryParam是您对sql注入的主要防御,并提供内置验证方式。它不会让你的目标变得更容易,所以不要去寻找它。
主要集中在使事情变得更容易的问题是它很少。你最终不得不支撑和捅它,它通常不值得。如果您需要我的建议:深呼吸,在办公桌前吃午餐,然后编写代码:)
现在,这并不意味着没有多少非常棒的工具可以帮助完成任务并加快速度。事实上,这是UDF和自定义标签的很大一部分目的。
并不是说我从未使用cf来生成cf代码或查询,但我将该代码复制到源代码中并且没有离开cf尝试汇编sql语句在生产中达到这种程度。
<cfoutput><Cfset form.fieldnames = "test,this,thing"><Cfset form.fieldnames = "test,this,thing"> <pre> <cfquery>
<cfset icount = 0>
<cfset istring = "">
Insert into Persons(<cfloop list="#form.fieldnames#" index="i"><cfset icount = icount + 1>
<cfif not listfindnocase("comma,delimited,list,of,fields,you,dont,want,to,insert",i)>
<cfset istring = istring & "," & i>
</cfif><cfset istring = ReReplace(istring,"(^,|,$)","","ALL")>
</cfloop>#istring#)
<cfset icount = 0>
Values(<cfloop list="#istring#" index="ix"><cfset icount = icount + 1><cfqueryparam cfsqltype="XXXXXXXX" value="##form.#ix###"><cfif icount neq listlen(istring)>,</cfif></cfloop>)
</cfquery></pre></cfoutput>
生成代码并将其复制到源代码后,您希望将每次出现的XXXXXXXX替换为实际的sql类型。阅读cfqueryparam
了解类型(如cf_sql_integer和cf_sql_varchar)。
但同样,有一种情况是编写代码以生成sql插件块是最明智的路径,但它更精确,就像循环遍历子集字段名列表一样。
例如,如果我有一个名为Classrooms的表,它们看起来像这样
Teacher | Student1 | Student2 | Student3 | ...StudentN... | Student10
我有一个表格,管理员可以通过勾选学生删除的班级来删除课程中的学生,我可能会安排类似
的内容update students set
<cfloop list="#form.delstudents#" index="s">
Student#val(s)# = '',
</cfloop>
Teacher = <cfqueryparam...>
(我知道上面的例子作为一个关系数据库会好得多,我只是为了一个例子而挠头。)
答案 1 :(得分:0)
我自己不会这样做,但这种方法可能有用。在您的表单页面上:
fields = "field1,field2,etc";
labels = "label1,label2,etc;
datatypes = "cf_sql_varchar,cf_sql_date,etc";
<cfform>
<cfloop from = "1" to = "#listlen(fields)#" index = "i">
<cfinput
name = "#ListGetAt(fields, i)#"
label = "#ListGetAt(labels, i)#">
</cfloop>
two hidden tags go here where you pass the fields and datatypes variables.
在您的操作页面上:
insert into yourtable
(#form.fields#)
values
(
<cfloop from = "1" to = "#Listlen(form.fields)#" index = "i">
<cfqueryparam
cfsqltype="#ListGetAt(form.datatypes, i)#"
value = "#form[ListGetAt(form.fields, i)]#">
故意遗漏是在必要时插入逗号。你可以搞清楚。
</cfloop>
)
请注意,此代码未经测试,可能存在语法错误。