2012-10-14 48 views
0

我昨天遇到了一些事情,花了我一段時間才弄清楚。在這段代碼中,服務器在正在更新的表中沒有記錄時掛起,並且不會給出超時錯誤或任何錯誤。使用第二個表中的記錄,代碼可以正常工作。當表格爲空時更新記錄 - CF掛起

<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問題,因爲運行在蟾蜍更新查詢確實在沒有記錄人們所期望的是什麼 - 什麼都沒有。

我先運行一個查詢得到的記錄數第二個表,只有運行更新查詢,如果記錄數大於0

這是使用Oracle 10,CF 9.02修好了與修補程序。

注意:select查詢返回2K/20K記錄; 更新和插入查詢都在第二個表中存在現有記錄時正確運行; 刪除更新查詢允許插入查詢運行,而不管第二個表中是否有記錄。

編輯:我要去探索移動更新和插入查詢循環如下建議。儘管如此,我仍然不認爲原始問題(爲什麼服務器掛在第二個表中沒有記錄的情況下)尚未得到解答。

+0

_「隨着表中的記錄,該代碼工作正常。」 _ - 不,沒有關係。你錯過了cfloop查詢屬性的結尾報價。 如果沒有記錄,查詢循環將不會執行它的主體,所以必須比這裏顯示的更多。 –

+0

這只是我輸入的內容來證明問題。實際的代碼是正確的 - 正如我所提到的,當表中有記錄時,它運行良好。此外,select查詢返回2K和20K之間的記錄,具體取決於int傳遞的參數。 – earachefl

+0

提供_actual_代碼(僅對_only_敏感/重複信息進行過濾/剪切)總能讓事情變得更簡單和更清晰...... –

回答

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> 
+0

那麼,我正在運行循環的原因是,我還在更新後執行插入查詢,每次都必須在循環中發生。即使有20K記錄,20K更新和20K插入也會在不到一分鐘的時間內完成。這意味着一個管理功能,其中較早的記錄被更新(基本上變爲非活動狀態)並且新記錄被同時插入,並且通常由管理員每年僅運行一次。我會研究你對更新聲明的建議 - 這聽起來像是一種可能性。 – earachefl

+0

我更新了我的答案,以更好地適合您的問題。您也可以執行INSERT/SELECT語句,因此無論返回多少記錄,您都只運行2個查詢。 –

+0

您也可以運行合併,以便插入或更新,因爲目標表是相同的。 – iivel

1

至於這是爲什麼掛,是有史以來被對數據庫所做的一個電話還是它正在評估第二查詢時[我猜你指的是第二個表是空單]懸。我似乎記得像這樣的問題,我只能使用你注意到的相同方法解決,但是 - 第二個cfquery不是必須的,因爲你可以使用子選擇並在select上進行更新。如果更新中的條件是從第一個查詢生成的,則可能會創建笛卡爾積,導致運行時間過長(這取決於您的超時設置實際上不會超時)。

我對整個查詢感興趣,因爲替代方法是刪除循環的必要性並讓數據庫執行數據庫的操作。 Oracle允許基於選擇更新所以你必須:

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)。維基百科鏈接實際上對於如何構造語法非常清楚。

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