2009-02-25 8 views
6

OK、それはできますが、私はかなり頻繁に行いますが、なぜT-SQLではループを行うのが難しいのですか?私は、クエリの結果セットを解析し、ループなしでは実行できないことをやりたいのですが、私のループを設定して実行するコードは> 20行です。T-SQLでループを実行するのがなぜ難しいのですか

他の人も同様の意見を持っていると思いますが、どうしてループを実行する簡単な方法がないのですか?

脇に:私たちは最終的にSQL2008でUPSERT(別名MERGE)を手に入れたので、おそらくすべての希望は失われません。

答えて

22

SQLは、セットベース、declarative languageです。手続き型またはimperative languageではありません。 T-SQLは、この2つにまたがるよう試みますが、基本的にセットベースのパラダイムで構築されています。

+0

これは正しい方法ですか? – AnthonyWJones

+0

おっと!あなたは正しいです、私は間違った順序で私のリンクを貼り付けました:)ありがとう –

1

SQLはSetベースの言語なので、 sqlの機能は、特定の特性に基づいて、より大きなグループのデータ内の小さなグループを見つけることにあります。この作業を処理するために、ループはほとんど不要です。明らかに、いくつかの状況を処理する便宜のために追加されていますが、言語の意図された使用はこの機能を無関係にします。

2

T-SQLは、命令型言語ではありません。宣言的になるように設計されています。その宣言的性質により、オプトマイザは様々なタスクをスライスしてパラレルなどで実行し、他の方法では最も効率的な順序で処理を実行できます。

-2

私はDBの専門家ではありませんが、データベーストランザクションの原子的性質は、トランザクションが完了するか、まったく発生しないため、ループを達成するのが難しいと考えています。状態を維持することは厄介なことです!

Wikipedia Article on Atomicity

0

SQLは、SETベースのシステムではなく、手続き(ループ)です。一般的には、SQLでループを使用するのは悪い習慣とみなされます。なぜなら、それらのセットに基づく同等のものと比較してパフォーマンスが低いからです。

WHILE、カーソルも使用することができ、最も一般的なループ構造ですが、自分の問題が

... WHILEの例(あなたがそれを必要としないかもしれないが、他の人がかもしれないが(割り当て解除/クローズし忘れる)は)

DECLARE @iterator INT 
SET @iterator = 0 

WHILE @iterator < 20 
BEGIN 
    SELECT * FROM table WHERE rowKey = @iterator 
/*do stuff*/ 
    @iterator = @iterator + 1 
END 

本当の問題は、「それはあなたが単にセットベースの方法で行うことができないことをやろうとしていることは何ですか?」されます

10
私はクエリ結果セットを通して解析し、単純にループ

なしの大部分を行うことができない何かをしたいと思います理由のトンと考えることができ

代わりにセットベースの操作でそれを行う方法を示すか、データベースではなくクライアントコードでそれを行うべき理由を説明することができます。 SQLでループを実行する必要性はまれです。

+1

私は彼らがクライアントコードで行う必要があることに同意します。しかし、何百万ものレコードを処理しているときには、それが適切な「場所」ではないとしても、データベース内ですべての処理を高速化するのは100倍(1000倍)です。 –

+1

1つの例:データベース内のすべての「フィッテインメント」をループし、1つのテーブルに挿入し、そのフィレットの値に基づいて別のテーブルを更新するストアドプロシージャを実行します。値を計算するテーブルは定期的に変更されるため、これを定期的に実行する必要があります。クライアントコード= 1日、SQL = 1時間。 –

+1

> "クライアントコードで実行する必要があることに同意しますが、" ...それはその一部です。もう1つは、リファクタリングを基にして設定されるものです。 "fitment"の例では、ストアドプロシージャを書き換えてテーブル全体を操作できるはずです。 –

1

ほとんどすべてが基づいて設定行うことができ、なぜ20行番号テーブルに

を使用してみては?これはあなたが必要とするものです。

select *,identity(int, 1,1) as Someid into #temp 
from sysobjects 

declare @id int, @MaxId int 
select @id = 1,@MaxId = max(Someid) from #temp 

while @id < @MaxId 
begin 
-- do your stuff here 
print @id 
set @id [email protected] + 1 
end 
1

これはループで何をしたいかによって異なります。whileループを使用することは全く難しいことではありません。とにかく避けるべきカーソルを、使用している場合、それが唯一面倒になり

declare @i int 
set @i = 20 
while @i>0 begin 
... do some stuff 
set @i = @i-1 
end 

1

ループベースのアプローチではなく、ほとんどの作業を行うためにユーザー定義関数を使用することをお勧めします。これは、設定されたSQL言語の意図を保持します。

+0

私はこれが好きです。私は調査するつもりです。 –

関連する問題