0

昨天我遇到了一些事情,我花了一段时间才弄清楚。在此代码中,当正在更新的表中不存在任何记录时,服务器会挂起,并且不会给出超时错误或任何错误。使用第二个表中的记录,代码可以正常工作。

<cfquery name="getSomething">
    SELECT one, two
    FROM some_table
    WHERE conditions = 'my conditions'
</cfquery>
<cfloop query="getSomething">
    <cfquery name="updateSomethingElse">
        UPDATE other_table
        SET three = 'my value'
        WHERE four = #getSomething.one#
        AND five = #getSomething.two#
    </cfquery>
    <!--- always run an insert --->
    <cfquery name="insertSomething">
        INSERT INTO other_table
        (columns)
        VALUES
        (values)
    </cfquery>
</cfloop>

我认为这是一个 CF 问题,因为在 Toad 中运行更新查询会在没有记录时完成人们所期望的 - 什么都没有。

我通过首先运行查询以获取第二个表中的记录计数来修复它,并且仅在记录计数大于 0 时才运行更新查询。

这是使用带有修补程序的 Oracle 10、CF 9.02。

注:select查询返回2K/20K记录之间;当第二个表中有现有记录时,更新和插入查询都可以正确运行;删除更新查询允许插入查询运行,而不管第二个表中是否有记录。

编辑:我将探索将更新和插入查询移出循环,如下所示。我仍然认为最初的问题(为什么服务器在第二个表中没有记录的情况下挂起)尚未得到回答。

4

2 回答 2

2

如果没有返回记录,服务器将不会挂在 UPDATE 上,因为它永远不会到达 UPDATE 语句。我建议在没有返回记录时删除您的 UPDATE 查询并在循环中仅输出“记录”。服务器应该仍然挂起,所以你可以排除你的 UPDATE 是问题

但是,为什么不添加记录检查呢?

<cfquery name="getSomething">
SELECT one, two
FROM some_table
WHERE conditions = 'my conditions'
</cfquery>

<cfloop query="getSomething">
 <cfif getSomething.RecordCount>
  <cfquery name="updateSomethingElse">
  UPDATE other_table
  SET three = 'my value'
  WHERE conditions = 'other conditions'
  </cfquery>
 </cfif>
 <cfquery>
 INSERT
 </cfquery>
</cfloop>

我还建议使用将两个表连接在一起的 UPDATE 语句。如果您使用 12,000 次更新来访问您的数据库,这可能需要至少十分钟,而运行下面的代码将花费更少的时间。

<cfquery name="updateSomethingElse">
UPDATE other_table
SET three = 'my value'
FROM some_table, other_table
WHERE some_table.id = other_table.id
AND some_table.conditions = 'my conditions'
AND other_table.conditions = 'other conditions'
</cfquery>
<cfquery name="getSomething">
INSERT INTO other_table (one, two)
SELECT one, two
FROM some_table
WHERE conditions = 'my conditions'
</cfquery>
于 2012-10-14T16:36:28.480 回答
1

至于为什么挂起,是对数据库进行调用还是在评估第二个查询时挂起[我猜你的意思是第二个表是空的]。我似乎记得像这样的问题,我只能使用您注意到的相同方法来解决,但是 - 第二个 cfquery 并不是绝对必要的,因为您可以使用子选择并在选择时更新。如果您在更新中的条件是从第一个查询生成的,则可能会创建一个笛卡尔积,从而导致运行时间过长的查询(取决于您的超时设置实际上不会超时)。

我会对完整查询感兴趣,因为另一种方法是消除循环的必要性,让数据库做数据库所做的事情。Oracle 允许基于 select 进行更新,因此您将拥有:

UPDATE other_table OT
SET OT.three = ( SELECT one 
                 FROM some_table ST
                 INNER JOIN OT
                      ON OT.whatever = ST.stuff
                 WHERE conditions = 'conditions')
WHERE other_conditions = 'other conditions'

鉴于您已明确声明您需要能够从初始表中进行选择,然后进行更新或删除,因此您可以使用合并命令,合并的操作实际上是插入或更新(有时称为 upsert)。Wikipedia 链接实际上非常清楚如何构建语法。

http://en.wikipedia.org/wiki/Merge_(SQL )

于 2012-10-14T16:48:24.880 回答