2012-04-15 13 views
0

こんにちは私は、名前が 'プル'を持つすべてのデータベースを反復処理することにより、SourceDestinationという名前のテーブル名を引き出す次のSQLを実行しようとしています。sp_executesqlの構文エラー

しかし、プラス記号「[email protected]_name+」.sys.tablesの近くにエラーが表示されています。私は両側でN ''を試しましたが、うまく動作しないようです。

このエラーが発生します。 メッセージレベル102、レベル15、状態1、行20 '+'の近くの構文が正しくありません。

私が間違っている場所を知る必要があります。助けてくれてありがとう。

declare db_names cursor for 
select name 
from master.sys.databases 
where name like 'Pull_%' 

declare @db_name varchar(50) 
declare @table_name varchar(50) 
declare @sql nvarchar(100) 
DECLARE @ParmDefinition NVARCHAR(500); 
open db_names 

fetch next from db_names into @db_name 

while @@FETCH_STATUS = 0 
begin 
print @db_name 

    -- set @sql = 'select '[email protected]_name+'=name from '[email protected]_name+'.sys.tables' 
    -- set @sql = N'select @table_name=name from @db_name.sys.tables where name = ''SourceDestinations'' ' 
execute sp_executesql N'select @tbl_name=name from '[email protected]_name+'.sys.tables where name = ''SourceDestinations'' ', N'@tbl_name varchar(50) OUTPUT', @[email protected]_name OUTPUT 
--exec(@sql)o 
print @table_name 
FETCH NEXT FROM db_names INTO @db_name 
    end 

    close db_names 
    deallocate db_names 

答えて

2

あなたはsp_executesqlコールから別々のステップとしてコマンド文字列を構築する必要があります:

set @sql = N'select @tbl_name=name from '[email protected]_name+'.sys.tables where name = ''SourceDestinations'' ' 
execute sp_executesql @sql, N'@tbl_name varchar(50) OUTPUT', @[email protected]_name OUTPUT 

EDIT 変数が2回目の反復で設定されてすることはできません。あなたは、テーブルが入っているデータベースの名前を印刷されてやりたいすべては、あなたのスクリプトがずっと簡単になることができれば(私はポイントを見に失敗

SET @table_name = NULL 

print @table_name 
+0

ありがとうございました!現在、構文エラーは発生していません。しかしもう一つ問題があります。カーソルは2つのDB名を返しますが、sys.tablesのクエリは返された最初のDB名に対してのみ機能します。 2番目のDB名については、前のDB自体の結果が返されます。私はデバッグを追加し、@ db_name変数が各反復ごとに各DBの名前を保持するが、両方のDB名の結果が同じになることを示しています。 – JunaidKirkire

+0

@JunaidKirkire - ( 'SourceDestinations'テーブルが両方のデータベースにあると仮定して)書かれたクエリでは、両方のクエリで同じ結果が得られます。質問を編集して、現在のクエリと達成しようとしていることの詳細な説明を更新してください。 –

+0

テーブルSourceDestinationsは、2番目のDBに存在しません。それでもdb_nameの2番目の値が表示されます。 sys.tablesでクエリを実行する前に、 'use' + db_nameを実行しました。それを念頭において、テーブル 'SourceDestinations'が返されます。 私はdb_nameに2番目のDBの名前があることを確認するために、デバッグモードでクエリを実行しました。 私が達成しようとしているのは、名前に「プル」を持ち、特定のテーブルをクエリするすべてのデータベースを反復処理することです。 しかし、最初のデータベースだけが照会されているようです。 – JunaidKirkire

0

後に追加すること
てみてくださいテーブル名を取得し、それを毎回印刷する - それはSourceDestinations以外の何をすることができる):

DECLARE @sql NVARCHAR(MAX); 
SET @sql = N''; 

SELECT @sql = @sql + 'IF EXISTS (SELECT 1 FROM ' + QUOTENAME(name) 
    + '.sys.tables WHERE name = ''SourceDestinations'') 
    PRINT ''' + name + ''';' 
FROM sys.databases 
WHERE name LIKE 'PULL_%'; 

EXEC sp_executesql @sql; 

私はあなたがMOをやってみたいことをいえ疑います?実際のテーブルがどこに住んでいるかを決めると、これでもう一度やり直してください。エドは絶対に正しいです。実行する際に文字列を連結してsp_executesqlに渡すことはできません。事前に構築する必要があります。これは、すべてのストアドプロシージャコールに当てはまります。あなたが言うことができません。

EXEC sp_who2 'act' + 'ive'; 

それは同じものであるべきにもかかわらずとして:あなたは@sql変数を宣言しているため、少なくともある程度は、すでにこれを知っているように見える

EXEC sp_who2 'active'; 

(あなたはそれを使うことはありませんが)。デフォルトのカーソルオプションを使用しないでください

  1. DECLARE d CURSOR 
        LOCAL STATIC FORWARD_ONLY READ_ONLY 
        FOR SELECT name FROM sys.databases 
        WHERE name LIKE 'Pull_%'; 
    
    DECLARE 
        @db_name NVARCHAR(128), 
        @sql  NVARCHAR(MAX); 
    
    OPEN d; 
    
    FETCH NEXT FROM d INTO @db_name; 
    
    WHILE @@FETCH_STATUS = 0 
    BEGIN 
        PRINT @db_name; 
    
        SET @sql = N'IF EXISTS (SELECT 1 FROM ' + QUOTENAME(@db_name) 
        + '.sys.tables WHERE name = ''SourceDestinations'') 
         PRINT ''' + @db_name + ''';' 
    
        EXEC sp_executesql @sql; 
    
        FETCH NEXT FROM d INTO @db_name; 
    END 
    
    CLOSE d; 
    DEALLOCATE d; 
    

    キーポイントのカップル:

    は私がするようにコードを変更します。この場合は多分大したことではありませんが、入るのは悪い習慣です。私はこのブログ記事の中でパフォーマンスの影響の1つのケースを強調します:http://sqlblog.com/blogs/aaron_bertrand/archive/2011/03/08/t-sql-tuesday-16-this-is-not-the-aggregate-you-re-looking-for.aspx

  2. データベース/テーブル名にはvarchar(50)を使用しないでください。識別子の規則(this doc is from 2000、ただしsimilar docs exist for newer versions)に従って、これらはnvarchar(128)である必要があります。
  3. また、スキーマも確認する必要があります。誰かが自分自身のデフォルトスキーマで誤って作成した場合は、SourceDestinationsに対して複数のヒットを得ることがあります。
  4. @sqlの文字列は100文字を超える必要があります。私は通常、このような場合にはMAXを使用します。これは、パフォーマンスの違いが、255または1024などが十分な文字であるかどうか疑問に思うほど価値がないためです。