0

昨日、理解するのに時間がかかったものに出くわしました。このコードでは、更新中のテーブルにレコードが存在しない場合にサーバーがハングし、タイムアウト エラーやそれに関するエラーは発生しません。2 番目のテーブルのレコードを使用すると、コードは正常に機能します。

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

Toad で更新クエリを実行すると、レコードがない場合に期待されることを実行するため、これは CF の問題であると考えています。

最初にクエリを実行して 2 番目のテーブルのレコード数を取得し、レコード数が 0 より大きい場合にのみ更新クエリを実行することで修正しました。

これは、ホットフィックスを適用した Oracle 10、CF 9.02 を使用しています。

注: select クエリは 2K/20K レコードの間で返されます。2 番目のテーブルに既存のレコードがある場合、更新クエリと挿入クエリの両方が正しく実行されます。更新クエリを削除すると、2 番目のテーブルにレコードがあるかどうかに関係なく、挿入クエリを実行できます。

編集: 以下で提案されているように、更新クエリと挿入クエリの両方をループから移動することを検討します。ただし、元の質問 (2 番目のテーブルにレコードがない状況でサーバーがハングする理由) はまだ回答されていないと思います。

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>

2 つのテーブルを結合する UPDATE ステートメントを使用することもお勧めします。12,000 件の更新でデータベースをヒットしている場合、以下のコードを実行すると、おそらく少なくとも 10 分かかります。

<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

これがハングしている理由については、データベースに対して呼び出しが行われているのか、それとも 2 番目のクエリが評価されているときにハングしているのか [2 番目のテーブルが空のテーブルであることを意味していると思います]。このような問題を覚えているようですが、あなたが指摘したのと同じ方法を使用してのみ解決できました.2番目の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'

最初のテーブルから選択してから更新または削除する機能が必要であるという明確なステートメントを考えると、マージコマンドを利用できるようになり、マージのアクションは事実上挿入または更新になります (アップサートと呼ばれることもあります)。ウィキペディアのリンクは、実際には構文を構造化する方法について非常に明確です。

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

于 2012-10-14T16:48:24.880 に答える