2017-08-15 6 views
0

masterデータベースに接続している特定のデータベース(データベースのグループではない)からテーブルのリストをロードする際に、特有の問題が発生します。現在、私のクエリはサーバー上のすべてのデータベースを読み込み、RAISERRORを経由してクライアントに情報を返すデータベースをループします。このループが実行されていると、照会が完了すると、後で送信するために現在のデータベースのすべてのテーブルをロードするためにネストされたループが必要です(SELECT)。私が実行している問題は、これがC#コード内で単一のクエリとして実行されることです。理想的には、すべてをSQLでロードして、処理のためにクライアントに返したいと思います。例:SQL:特定のデータベースから別のテーブルに接続するとき

WHILE (@dbLoop < @dbCount) BEGIN 
    -- Do cool things and send details back to client. 
    SET @dbName = (SELECT _name FROM dbTemp WHERE _id = @dbLoop); 
    -- USE [@dbName] 
    -- Get a count of the tables from info schema on the newly specified database. 
    WHILE (@tableLoop < @tableCount) BEGIN 
      -- USE [@dbName] 
      -- Do super cool things and load tables from info schema. 
      SET @tableLoop += 1; 
    END 

    SET @dbLoop += 1; 
END 

-- Return the list of tables from all databases to the client for use with SQLDataAdapter. 
SELECT * FROM tableTemp; 

このトピックはかなり単純です。 SqlConnectionオブジェクトの接続を変更せずに、指定したデータベースのテーブルにアクセスする方法が必要です(C#コードのループを各データベースで同じクエリを処理する必要はありません)。 C#側。すべてをSQLにロードしてアプリケーションに返す方が効率的です。これで提供できるヘルプは素晴らしいでしょう!

おかげで、 ジェイミー

+1

? –

+0

これについて考えてみると、マイクロソフトが提供するもの以外にストアドプロシージャを使用するのではなく、セキュリティ上のリスクがあると言われました。また、カーソルクエリを使用しない理由を誰かが尋ねる場合でも、私たちのDBAはカーソルクエリを許可しません。 – lxxtacoxxl

+1

@lxxtacoxxl - 実際は逆です - SPははるかに安全です。 – Hogan

答えて

0

これで1日を過ごした後、私は最終的に解決策を思いつきました。すべてのデータベースをテーブル変数にロードしてから、それらのデータベースをループして、その詳細をクライアントに送り返します。 RAISERRORを介してデータベースの詳細自体がクライアントに送信された後、sp_executesqlを使用して、現在のデータベースで新しいサブクエリを実行し、プライマリの最後で処理するテーブルのリストを取得します。以下の例は、この問題を今後経験する他の人たちのためのこのプロセスの基本的な構造を示しています。

ご協力いただきありがとうございます。あなたがストアドプロシージャを書いていないのはなぜ

-Jamie

DECLARE @LoopCounter INT = 1, @DatabaseCount INT = 0; 
DECLARE @SQL NVARCHAR(MAX), @dbName NVARCHAR(MAX); 
DECLARE @Databases TABLE (_id INT, _name NVARCHAR(MAX)); 
DECLARE @Tables TABLE (_name NVARCHAR(MAX), _type NVARCHAR(15)); 

INSERT INTO @Databases 
SELECT ROW_NUMBER() OVER(ORDER BY name) AS id, name 
FROM sys.databases 
WHERE name NOT IN ('master', 'tempdb', 'msdb', 'model'); 

SET @DatabaseCount = (SELECT COUNT(*) FROM @Databases); 

WHILE (@LoopCounter <= @DatabaseCount) BEGIN 
    SET @dbName = (SELECT _name FROM @Databases WHERE _id = @LoopCounter); 
    SET @SQL NVARCHAR(MAX) = 'SELECT TABLE_NAME, TABLE_TYPE 
          FROM [' + @dbName + '].INFORMATION_SCHEMA.TABLES'; 
     INSERT INTO @Tables EXEC sp_executesql @SQL; 
    SET @LoopCounter += 1; 
END 
1

すべてのテーブルには、あなただけのことに対してクエリを実行すると、あなたが見てみたいスキーマのリストに参加することができるメタデータです。

SELECT tab.name 
FROM sys.tables AS tab 
JOIN sys.schemas AS sch on tab.schema_id = sch.schema_id 
JOIN dbTemp temp on sch.name = temp.[_name] 

これは、結果セットとして返されるテーブルのリストを返します。それが実行された後

+0

これは結果を返しませんでした。最後のJOINをwhere句に変更して、スキーマ名を特定のデータベース名(実際には2つ)と比較しました。 – lxxtacoxxl

+0

最後の結合を取り出して結果にsch.nameを追加すると、必要としたくないすべてのスキーマ名がわかります。 – Hogan

0

声明USE [@dbName]は通常GO文によって(有効になります。

USE [@dbName] 
GO 

上記の2行は、新しいデータベースの使用を開始するだろう。あなたはあなたのSQLの途中でこれを使用することはできませんまたはあなたが使用することができますSP。

もう一つの選択肢は、あなたのテーブルを照会するために、すなわち、dbname..tablename構文をドット表記を使用することです。

double dot notation post

+0

'@dbName'という名前のデータベースが見つかりませんでした。これは、ダブルドットとシングルドット表記と同じです。 – lxxtacoxxl

関連する問題