ColdFusion:如何在一个插入中插入带有静态外键的列表?

时间:2013-10-25 13:48:44

标签: sql sql-server coldfusion

我有一个像这个东西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中不能有一个逗号,我不知道如何在cfloop中说“当前的迭代次数”。如果我将列表转换为查询,那么我可以执行currentRow,但是我想知道在完成所有操作之前是否有更简单的方法来实现这一点。

另外,我正在使用CF 8和sql server '08编辑:抱歉,我实际上正在使用2000.

4 个答案:

答案 0 :(得分:4)

更新:

最终真正的问题是,只有SQL Server 2008+支持使用单个VALUES子句插入多组值的功能,并且OP使用2000.所以他们使用{{3相反。


(扩展自评论)

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

回到你的问题,只需切换到from/to循环,然后使用getToken(list, index)之类的列表函数来获取各个元素(请参阅select / union all approach)或使用数组。显然你也应该先验证列表是不是空的。我个人的偏好是数组。没有经过测试,但是这样的事情:

    <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="..."> 
              )

答案 1 :(得分: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。我已经猜到了这个列的类型。

答案 2 :(得分: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>

我在这里找到了这个解决方案:How do I insert multiple rows WITHOUT repeating the "INSERT INTO dbo.Blah" part of the statement?

答案 3 :(得分:0)

这个答案与Matt类似,但不使用条件逻辑。

<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变量没有改变并且被设置在其他地方。