2011-06-29 14 views
0
DECLARE tableList CURSOR FOR  
    SELECT t.name 
    FROM sys.tables t 
     INNER JOIN sys.columns c 
     ON t.object_id = c.object_id 
    WHERE 
      t.name NOT LIKE 'z%' 
     AND t.name NOT LIKE '%delete%' 
     AND t.name <> 'tblUsers' 
     AND t.name <> 'tblUserLogins' 
     AND t.name <> 'searchR' 
     AND t.name <> 'tblUserPortfolio' 
     AND t.name <> 'alerts_User' 
     AND c.name LIKE 'userid' 
     OR c.name LIKE 'user_id' 
    ORDER BY name 
OPEN tableList 
FETCH NEXT FROM tableList 
INTO @tablename 

上記はカーソルを作成するためのクエリです。実行するには高価である可能性が高いと思われる多くの操作を使用しています(LIKENOT LIKE)。カーソルを使用してこのクエリを最適化する方法は?

私は、あまりにも多くのLIKE/NOT LIKEを使用せずにクエリを構築し、より最適なものにするためのよりよいアプローチがあるかどうかを尋ねています。

ありがとうございました。

EDIT:

ここにカーソルを使用しての意図が一致するすべてのテーブルには、私たちはその後、動的にレコードを削除/更新/挿入することができLoop Throughにあります。

私は使用しているデータベースに150を超えるテーブルがあります。だから、SQL Serverは汚い仕事をするかもしれないと思っていました。

+3

実際の問題は、ここでは 'CURSOR'であってクエリではないと思われます。また、それらは高価です。特にsys.tablesとsys.columnsで行のボリュームが狂って大きくならない –

+0

最後の2つの条件( 'OR'と組み合わせたもの)はおそらく括弧で囲まれていなければなりません。そうでなければ、最後の2つの条件。 –

答えて

5

は私がなります

1)NOT INの代わりに、複数の使用により、(IMO)SQLを読みやすく "...とt.name <> ..."
2)c.nameを変更しましたIN句単一のが好きあなたが完全に一致をしたいように見えるよう、

LIKE
SELECT t.name 
FROM sys.tables t 
    INNER JOIN sys.columns c ON t.object_id = c.object_id 
WHERE t.name NOT LIKE 'z%' AND t.name NOT LIKE '%delete%' 
    AND t.name NOT IN ('tblUsers','tblUserLogins','searchR','tblUserPortfolio','alerts_User') 
    AND c.name IN ('userid','user_id') 
ORDER BY name 

を必要としないこと。これは、実際には異なるTBHの性能面の多くを作るそうではありませんが、私はそれをより読みやすくなり考えます/ maintainable。

しかし、私が提起する主なポイントは、実際にはカーソルがまったく必要かどうかということです。セットベースのアプローチに賛成であることは間違いありません。しかし、代替案を提案するためにカーソルで何をしているのかを知る必要があります。

編集:あなたは動的SQLを生成し、(あなたは、それぞれが同じ構造を持つ各テーブルに同じ行を挿入したいと仮定すると、単純な例)一度にそれを実行この種のアプローチを試みることができる 。これが本当にあなたの正確なシナリオに合っているかどうか(あるいはそれが実際に価値のある違いを作り出すかどうか)を知ることは難しいですが、このテクニックを知っていると便利です。

DECLARE @nSQL NVARCHAR(MAX) 
SELECT @nSQL = COALESCE(@nSQL, '') + 
'INSERT ' + QUOTENAME(t.name) + '([SomeCol]) VALUES (@ValueToInsert);' + CHAR(10) 
FROM sys.tables t 
    INNER JOIN sys.columns c ON.... 
...{rest of current SELECT) 

-- comment out PRINT, and uncomment EXECUTE statement to actually run the SQL 
PRINT @nSQL 
-- EXECUTE sp_executesql @nSQL, N'@ValueToInsert VARCHAR(10)', 'NewValue' 
+0

+1良いアドバイスで良い答え。 –

+0

+1カーソルを削除するための良いアドバイスです。しかし、読みやすさは相対的です。あなたの変更は、それがほぼ同じ長さになっているので、それ以上の読み込みができません。類似した長さの問合せに対する可読性はインデントによって達成されます。私はOPのクエリをより読みやすくするために再フォーマットしました。それは可能性のある欠陥も示しています(これは一つの 'x IN(...) 'で修正しました)。 –

+0

私は質問を更新しました。ここでカーソルを使用してください。もう一度見ていただきありがとうございます。 – woodykiddy

関連する問題