2009-08-26 15 views
0

私はプロジェクト用にColdFusionを使用していますが、ストアドプロシージャを使用する方が高速かもしれないと書かれていますが、私はT-SQLの人ではありません私はそれを比較する方法をよく分かりません。ストアドプロシージャ/ ColdFusionのSelectクエリに基づくテーブルの更新

動的に構築されたcfqueryに基づいてテーブルからいくつかのフィールドを選択する初期クエリを実行しています。私はこのクエリをSQL Serverストアドプロシージャに変換する方法を知っていると思います。

しかし、その直後に、私はそのクエリからすべてのプライマリキーIDを取得し、別のテーブルに対してこれらのIDを持つレコードを「ロック」する別のクエリを実行します。ロックは、このレコードが「チェックアウトされた」ことをシステムに知らせる、第2のテーブル内のビットフィールド(フラグ)である。私はcftransactionの両方のクエリをラップして、1つの単位として実行します。

コード概要:

<cftransaction> 
    <cfquery name="selectQuery"> 
     SELECT id, field2, field3 
     FROM table1 
     WHERE (bunch of conditions here) 
    </cfquery> 

    <cfquery name="updateQuery"> 
     UPDATE table2 
     SET lockField = 1 
     WHERE table2.id IN (#ValueList(selectQuery.id#) 
    </cfquery> 
</cftransaction> 

私はその後、いくつかのデータを出力するためにそれを使用しています私のアプリにselectQueryの結果セットを返します。 cfstoredprocを使用して呼び出すことができる単一のSQL Server 2008ストアドプロシージャで同じことをどのように達成できますか?

また、CFに戻り、DBに戻って別のクエリを呼び出す必要があるため、ネイティブCFウェイ(cfquery)はストアドプロシージャほど効率的ではないと考えています。 1つのストアドプロシージャがDB内のすべての処理を行い、使用するために元のクエリ結果セットを返します。

アイデア?

答えて

0

最初のクエリをサブクエリにして別のステートメントを使用して結果を返すことで、1つのクエリで更新できます。全部が単一のストアドプロシージャのようになります。

CREATE PROCEDURE myUpdate 
     @Variable [datatype], etc... 
    AS 
    BEGIN 
    UPDATE table2 
    SET lockField = 1 
    WHERE table2.id IN (
     SELECT id 
     FROM table1 
     WHERE (bunch of conditions here) 
    ) 
    SELECT id, field2, field3 
    FROM table1 
    WHERE (bunch of conditions here) 
    END 

あなたは、おそらく、いくつかのパラメータを渡す必要があるでしょうが、それは、ストアドプロシージャの基本的な構造です。

<cfstoredproc procedure="myUpdate"> 
    <cfprocparam type="[CF SQL Type]" value="[CF Variable]"> 
    etc... 
    <cfprocresult name="selectQuery" resultSet="1"> 
</cfstoredproc> 

このようなクエリ結果は、以前と同じように使用できます。

+0

いいえ、私はこの回答の健全性チェックが必要です。テーブル1のデータは一定のフラックスにあります...本質的にキューです。これは単一のstoredprocの内部にあるので、本質的に単一のトランザクション権限として実行されていますか?意味、私はテーブル1で2回SELECTを実行しているので、私は両方の時間に同じ結果を得ていることを保証する必要があります。多くのユーザーがこの機能を定期的に使用するため、「ロック」が正しく機能するようにする必要があります。 –

+0

いいえ、単一のトランザクションとして実行されていません。更新プログラムを実行する前にデータを出力する必要がある場合は、別の方法で行う必要があります。私はあなたの質問の全体をロックするものをキャッチしていない。 –

1

あなたの問題は「ここに条件の束」です。これらの条件は常に静的ですか?だからそれはいつもですか?(FOO = @x AND BAR = @y)?それとも条件としてFOOがまったく存在しない場合もありますか?

FOOが常に存在するとは限りませんが、ストアドプロシージャに問題があります。 T-SQLは動的クエリー構築を行うことができません。実際には、SQLをコンパイルし事前に最適化するためのprocのポイントを無効にすることさえ可能です。あなたはもちろんそうすることができますが、proc本体の内部にSQL文字列を作成し、最後に実行するだけで終わります。 cfqueryparamsでCFQueryを使うほうがはるかに優れています。実際にあなたは代わりにこれを行うと考えていますか?

+0

問題は、table2を更新するだけでなく、table1からselect文の結果セットを返す必要があることです。 –

1

更新されたレコードのIDを取得してテーブル変数/一時テーブルに挿入するために、UPDATEステートメントにOUTPUT句を追加できます。その後、結果セットを返すためにtable1に戻ってJOINします。

DECLARE @UpdatedRecords TABLE (ID INT) 

UPDATE t2 
SET  t2.lockField = 1 
OUTPUT Inserted.ID INTO @UpdatedRecords (ID) 
FROM table2 t2 INNER JOIN table1 t1 ON t2.id = t1.id 
WHERE (bunch of conditions for table1 here) 

SELECT t1.id, t1.field2, t1.field3 
FROM table1 t1 INNER JOIN @UpdatedRecords u ON t1.id = u.id 

table1に一定のフラックスである場合、他の値(「フィールド2」と「フィールド3」)はUPDATEが発生したときに、彼らが何であったかであることが保証されていないことに注意してください。しかし、私はあなたの現在の方法もその問題の影響を受けやすいと思います。

0

SPROCは不要です。

UPDATE table2 
SET table2.lockField = 1 
FROM table1 
WHERE table1.id = table2.id 
    AND table1.field2 = <cfqueryparam ....> 
    AND table1.field3 = <cfqueryparam ....> 
+0

ちょうどこれがいくつかの重要な疑問を感じました。 : - / – Shawn

関連する問題