2

我有一个像这样的东西1,东西2,东西3的列表。我想将它们插入到具有相同外键的查找表中。所以理想情况下它看起来像这样:

<cfquery datasource="#ds#" result="insert_things">
    INSERT INTO lkp_things (foreign_key, thing) VALUES
    (1, thing1), (1, thing2), (1, thing3)
</cfquery>

似乎完成此操作的唯一方法是将列表转换为查询,但我想知道,有没有更简单的方法?

这是我尝试过的:

<cfquery datasource="#ds#" result="insert_things">
    INSERT INTO lkp_things (foreign_key, thing) VALUES
    <cfloop list="#things#" index="thing">
        (#id#,#thing#)<cfif ?????? NEQ len(#things#)>,</cfif>
    </cfloop>
</cfquery>

我听说你不能在 cfquery 中执行 cfloop,但我什至不确定这是不是真的,因为我不能在 VALUES 中使用尾随逗号,而且我不知道该怎么说“The当前迭代次数”在 cfloop 中。如果我把列表变成一个查询,那么我可以做 currentRow,但我想知道在我完成所有这些之前是否有更简单的方法来完成这个。

另外,我使用的是 CF 8 和 sql server '08 编辑:对不起,我实际上使用的是 2000。

4

4 回答 4

4

更新:

最终,这里真正的问题是仅在 SQL Server 2008+ 中支持使用单个VALUES子句插入多组值的功能,并且 OP 使用的是 2000。所以他们改用select / union all 方法


(从评论中扩展)

当然,您可以在cfquery. 首先在 CF 服务器上处理所有 cfml 代码。然后将生成的 SQL 字符串发送到数据库执行。只要您的 CF 代码生成有效的 SQL 语句,您就可以做任何您想做的事情:) 是否应该是另一个问题,但这种循环非常好。

回到您的问题,只需切换到from/to循环并使用列表函数(例如getToken(list, index)获取单个元素)(参见Matt 的示例)或使用数组。显然,您还应该首先验证列表不为空。我个人的偏好是数组。未经测试,但类似这样:

    <cfset thingArray = listToArray(things, ",")>

    <cfquery datasource="#ds#" result="insert_things">
       INSERT INTO lkp_things (foreign_key, thing) VALUES
       <cfloop from="1" to="#arrayLen(thingArray)#" index="x">
           <cfif x gt 1>,</cfif>
           ( 
              <!--- Note: Replace cfsqltype="..." with correct type --->
               <cfqueryparam value="#id#" cfsqltype="..."> 
             , <cfqueryparam value="#thingArray[x]#" cfsqltype="..."> 
           )
       </cfloop>
    </cfquery>

话虽如此,您的#thing#清单的来源是什么?如果这些值存在于数据库表中,您可以使用语句直接插入它们SELECT,而不是循环:

       INSERT INTO lkp_things (foreign_key, thing) 
       SELECT <cfqueryparam value="#id#" cfsqltype="...">, thing
       FROM   ThingTable
       WHERE  thing IN 
              (
                <cfqueryparam value="#thingList#" list="true" cfsqltype="..."> 
              )
于 2013-10-25T14:15:25.377 回答
2

我会添加一个计数器并在循环内增加它。此外,您需要使用listLen()而不是len在您的列表中来获取项目数。

<cfquery datasource="#ds#" result="insert_things">
  INSERT INTO lkp_things (foreign_key, thing) VALUES
  <cfset count = 1>
  <cfloop list="#things#" index="thing">
    (
     <cfqueryparam cf_sql_type="cf_sql_integer" value="#id#">,
     <cfqueryparam cf_sql_type="cf_sql_varchar" value="#thing#">
    )<cfif count NEQ listLen(things)>,</cfif>
   <cfset count++>
  </cfloop>
</cfquery>

你应该使用你cfqueryparam所有的价值观。我已经猜到该列是什么类型了。

于 2013-10-25T14:03:59.073 回答
1

我遇到了一个数据库错误

INSERT INTO lkp_things (foreign_key,thing) 
VALUES (1,'thing1'),(1,'thing2')

Leigh 帮助我意识到我实际上使用的是 SQL Server '00,并且该版本不允许这种插入方法。所以,我不得不使用这个:

INSERT INTO lkp_things (foreign_key,thing)
SELECT 1,'thing1'
    UNION ALL
SELECT 1,'thing2'

在 CF 中看起来像这样:

<cfset thingArray = listToArray(form.things,",")>
<cfquery datasource="aliaba_jdbc" name="insert_courses">
    INSERT INTO lkp_Things (id,thing)
    <cfloop from="1" to="#arrayLen(thingArray)#" index="x">
        SELECT <cfqueryparam cfsqltype="CF_SQL_INTEGER" value="#form.id#">,<cfqueryparam cfsqltype="CF_SQL_VARCHAR" value="#thingArray[x]#">
        <cfif x lt arrayLen(thingArray)>UNION ALL</cfif>
    </cfloop>
</cfquery>

我在这里找到了这个解决方案:如何插入多行而不重复语句的“INSERT INTO dbo.Blah”部分?

于 2013-10-25T17:59:42.783 回答
0

这个答案类似于马特的,但不使用条件逻辑。

<cfquery>
insert into lkp_things (foreign_key, thing)
select 0, ''
where 1=2
<cfloop list="#things#" index="thing">
union
select <cfqueryparam cf_sql_type="cf_sql_integer" value="#id#">
, <cfqueryparam cf_sql_type="cf_sql_varchar" value="#thing#">
</cfloop>

我们的两个答案都假设 id 变量没有改变并且被设置在其他地方。

于 2013-10-25T14:16:39.790 回答