昨天我遇到了一些让我花了一些时间才弄明白的事情。在此代码中,当正在更新的表中不存在任何记录时服务器挂起,并且不会给出超时错误或任何错误。使用第二个表中的记录,代码工作正常。
<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记录; 当第二个表中存在现有记录时,更新和插入查询都能正确运行; 删除更新查询允许插入查询运行,无论第二个表中是否有记录。
编辑:我将探讨如下所示,将更新和插入查询移出循环。我仍然不认为原来的问题(为什么服务器在第二个表中没有记录的情况下挂起)的问题尚未得到解答。
答案 0 :(得分:2)
如果没有返回记录,服务器将不会挂起UPDATE,因为它永远不会到达UPDATE语句。我建议删除你的UPDATE查询,并在没有返回记录时在循环中输出'record'。服务器应该仍然挂起,因此您可以排除您的更新是问题
但是,为什么不添加记录检查?
<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>
答案 1 :(得分:1)
至于为什么这是挂起的,是对数据库进行的调用,还是在评估第二个查询时挂起[我猜你的意思是第二个表是空表]。我似乎记得这样一个问题,我只能用你注意到的相同方法来解决,但是 - 第二个cfquery并不是绝对必要的,因为你可以使用subselects并在select上更新。如果更新中的条件是从第一个查询生成的,则可能会创建一个笛卡尔积,从而导致查询过长(取决于您的超时设置实际上不会超时)。
我对完整查询感兴趣,因为另一种方法是删除循环的必要性并让数据库执行数据库所做的事情。 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)。维基百科链接实际上非常清楚如何构造语法。