我需要使用cfloop
来插入记录。
客户填写了一张表格。他们从下拉列表中添加项目,然后在文本框中输入数量。通常,数量仅在 1 到 5 之间。
我需要运行一个循环来一次插入一个记录,每个记录都有一个唯一的项目 ID,每个记录的数量为 1。
例如,如果他们添加数量为 4 的特定项目 5,我需要在表中插入 4 条记录,每条记录的数量为 1。我真正想要的不仅仅是这里的答案,是我如何在不必问的情况下做到这一点的思考过程。
那是...一种奇怪的记录方式,但没关系。
我将假设表单字段的名称是项目和数量。我还假设您使用的是SQL或MySQL。两者的代码应几乎相同。
以下是操作页面上的代码可能如下所示:
<cfloop from="1" to="#FORM.QUANTITY#" index="i">
<cfquery name="insertOrder" datasource="DSN">
INSERT INTO TABLENAME
(
ITEMCOLUMN,
QTYCOLUMN
)
VALUES
(
<cfqueryparam cfsqltype="cf_sql_varchar" value="#FORM.ITEM#">,
1
)
</cfquery>
</cfloop>
我添加了一个cfqueryparam
标记来声明数据类型并帮助防止 SQL 注入。我不知道您的数据类型实际上是什么,但您绝对应该考虑将其用于从 FORM 或 URL 范围获取内容的任何查询。
你使用的是哪种版本的 SQL?与其建立数据库连接并为每个项目插入一次,不如执行以下操作:
<<<< sanitize FORM inputs >>>>
<cfquery name="insertRecords" datasource="#APPLICATION.DSN#">
INSERT INTO <TheTable> ( ItemID, Qty, <OtherDetails> )
VALUES
<cfloop from="1" to="#sanitizedFORMQuantity# index="i">
(
<cfqueryparam cfsqltype="cf_sql_integer" value="#sanitizedItemID#">
, 1
, <cfqueryparam cfsqltype="cf_sql_varchar" value="#sanitizedOtherDetails#">
)
<cfif index NEQ sanitizedFORMQuantity>,</cfif>
</cfloop>
</cfquery>
这使您可以构建查询并执行单个 INSERT,只需与数据库建立一种连接。即使只有 5 个项目,也会快得多。
笔记:
始终清理表单输入(以及来自任何 来源不是您(。queryparam 主要处理 SQLi,但可以 允许其他漏洞通过。
检查您的 cfsqltype 是否与 数据库中列的数据类型。知道哪些有效 一起防止不必要的后台数据转换。 https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-tags/tags-p-q/cfqueryparam.html
尽量减少需要连接到 数据库。特别是如果您的应用程序和数据库驻留在 不同的服务器(他们应该(。
对肖恩的出色回答进行了非常小的改动
<cfquery name="insertRecords" datasource="#APPLICATION.DSN#">
DECLARE @OtherDetails varchar(80) = <cfqueryparam cfsqltype="cf_sql_varchar" value="#sanitizedOtherDetails#">
INSERT INTO <TheTable> ( ItemID, Qty, <OtherDetails> )
VALUES
<cfloop from="1" to="#sanitizedFORMQuantity# index="i">
(
<cfqueryparam cfsqltype="cf_sql_smallint" value="#sanitizedItemID#">
, 1
, @otherDetails
)
<cfif index NEQ sanitizedFORMQuantity>,</cfif>
</cfloop>
</cfquery>
- 这将创建更少的临时变量
- 如果你真的要创建超过少量的变量,那么你在方法中有一个真正的问题。