2009-03-03 8 views
2

私は非常に新しいSQLです。私は基本的なステートメントをかなり簡単に扱うことができますが、私はまだループを理解していません。ストアドプロシージャ内のsql2000ループ

Foreach(JobHeaderID AS @OldJobHeaderID in dbo.EstimateJobHeader WHERE [email protected]) 
{ 
    INSERT EstimateJobHeader (ServiceID,EstimateID) 
    SELECT ServiceID, @NewEstimateID 
    FROM EstimateJobHeader 
    WHERE [email protected]; 

    SELECT @err = @@error 
    IF @err <> 0 
    BEGIN 
    ROLLBACK TRANSACTION 
    SET @RETURN_VALUE = 4 
    RETURN 4 
    END 

    SET @NewJobHeaderID = CAST(SCOPE_IDENTITY() AS INT) 

    SELECT @err = @@error 
    IF @err <> 0 
    BEGIN 
    ROLLBACK TRANSACTION 
    SET @RETURN_VALUE = 3 
    RETURN 3 
    END 

    INSERT EstimateDetail (JobHeaderID, OtherCols) 
    SELECT (@NewJobHeaderID,OtherCols) 
    FROM EstimateDetail 
    WHERE [email protected] 

    SELECT @err = @@error 
    IF @err <> 0 
    BEGIN 
    ROLLBACK TRANSACTION 
    SET @RETURN_VALUE = 3 
    RETURN 3 
    END 

    INSERT EstimateJobDetail (JobHeaderID, OtherCols) 
    SELECT (@NewJobHeaderID, OtherCols) 
    FROM EstimateJobDetail 
    WHERE [email protected] 

    SELECT @err = @@error 
    IF @err <> 0 
    BEGIN 
    ROLLBACK TRANSACTION 
    SET @RETURN_VALUE = 3 
    RETURN 3 
    END 
} 
+0

私の答えが更新されました:ここに投稿すると、あなたのユーザーページでpingされます。 –

答えて

6

ストアドプロシージャのループを避ける必要があります。

Sqlは、あなたがよく慣れ親しんでいる命令型言語ではなく、宣言型言語です。ループを使ってやりたいことのほとんどは、セットベースの操作として実行するか、クライアントコードで行う必要があります。もちろん、例外はありますが、あなたが思うほど多くはありません。
Why is it so difficult to do a loop in T-SQL


あなたはセットベースの方法を使用してそれを行う方法を尋ねた:

はこれを参照してください。私は最善を尽くしますが、あなたのコードには早い段階でバグがあり、それを正しく読んでいるかどうかを確かめることができません。最初のINSERT文の条件は、FOREACHループの条件と一致します。したがって、ループは1回だけ実行されます(1レコードがそこに返されます)。または、インサートは繰り返しごとに複数の新しいレコードを挿入します(はい、insertステートメントは一度に複数のレコードを追加できます)。複数のレコードが追加されている場合、なぜ最後の挿入によって作成されたIDだけを取得するのですか?

しかし、私はあなたに何かを見せてくれるほど十分に理解していると思います。見積もりの​​コピーを作成しているようです。また、@ NewEstimateIDの値がどこから来るのか説明しません。親テーブルがあればそれもそうですが、それについて知ることは役に立つでしょう。

/* Where'd @NewEstimateID come from? */ 
/* If there are several records in EstimateJobHeader with @OldEstimateID, 
* this will insert one new record for each of them */ 
INSERT EstimateJobHeader (ServiceID,EstimateID) 
    SELECT ServiceID, @NewEstimateID 
    FROM EstimateJobHeader 
    WHERE EstimateID= @OldEstimateID 

/* Copy EstimateDetail records from old estimate to new estimate */ 
INSERT EstimateDetail (JobHeaderID, OtherCols) 
    SELECT (new.JobHeaderID,ed.OtherCols) 
    FROM EstimateJobHeader new 
    INNER JOIN EstimateJobHeader old ON old.EstimateID= @OldEstimateID 
     AND new.EstimateID= @NewEstimateID AND old.ServiceID=new.ServiceID 
    INNER JOIN EstimateDetail ed ON ed.JobHeaderID= old.JobHeaderID 

/* Copy EstimateJobDetail records from old estimate to new estimate */ 
INSERT EstimateJobDetail (JobHeaderID, OtherCols) 
    SELECT (new.JobHeaderID,ed.OtherCols) 
    FROM EstimateJobHeader new 
    INNER JOIN EstimateJobHeader old ON old.EstimateID= @OldEstimateID 
     AND new.EstimateID= @NewEstimateID AND old.ServiceID=new.ServiceID 
    INNER JOIN EstimateJobDetail ejd ON ejd.JobHeaderID= old.JobHeaderID 

上記のコードは、サービスID + EstimateIDがEstimateJobHeaderテーブル内で一意であるという仮定を行います。これが当てはまらない場合は、テーブル内の行を一意に識別する列が何であるかを知る必要があるため、古いレコードと新しいレコードを結合して、関係が1:1であることを確認してください。

最後に、簡潔さのためにエラーチェックが省略されました。

+0

私は達成しようとしているものを投稿しました。セットベースの操作ではどうしたらいいですか? –

5

WHILE文のを見てみましょう:しかし

http://msdn.microsoft.com/en-us/library/aa260676(SQL.80).aspx

は、あなたがやろうとしているものに応じて、おそらくあなたは何を行うには良い、セットベースの方法がありますそれを最初に考慮する必要があります。

+0

私は現在サイトを見ています –

関連する問題