0

こんにちは、次の SQL を実行しようとしています。この SQL は、名前に「Pull」が含まれるすべてのデータベースを反復処理することにより、SourceDestination という名前のテーブル名を引き出します。

しかし、'+@db_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 '+@table_name+'=name from '+@db_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 '+@db_name+'.sys.tables where name = ''SourceDestinations'' ', N'@tbl_name varchar(50) OUTPUT', @tbl_name=@table_name OUTPUT
--exec(@sql)o
print @table_name
FETCH NEXT FROM db_names INTO @db_name
    end

    close db_names
    deallocate db_names
4

2 に答える 2

2

sp_executesql呼び出しとは別のステップとしてコマンド文字列を作成する必要があります。

set @sql = N'select @tbl_name=name from '+@db_name+'.sys.tables where name = ''SourceDestinations'' '
execute sp_executesql @sql, N'@tbl_name varchar(50) OUTPUT', @tbl_name=@table_name OUTPUT

EDIT 変数は、2 回目の繰り返しで設定されていない可能性があります。
追加してみる

SET @table_name = NULL

print @table_name
于 2012-04-15T10:11:30.860 に答える
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;

ただし、実際のテーブルが存在する場所を特定したら、これをさらに使用したいと思うでしょう。エドは絶対に正しいです。実行中に文字列を連結して sp_executesql に渡すことはできません。事前にビルドする必要があります。これはすべてのストアド プロシージャ コールに当てはまります。たとえば、次のようには言えません。

EXEC sp_who2 'act' + 'ive';

それは次と同じはずですが:

EXEC sp_who2 'active';

@sql変数を宣言したため (ただし、使用したことはありません)、少なくともある程度は既にわかっているようです。

コードを次のように変更します。

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. デフォルトのカーソル オプションを使用しないでください。この場合、おそらく大したことではありませんが、それは悪い習慣です。このブログ投稿で、パフォーマンスへの影響の 1 つのケースを強調しています。
  2. varchar(50)データベース/テーブル名には使用しないでください。これらは、識別子の規則nvarchar(128)に従う必要があります。
  3. また、スキーマもチェックする必要があります。SourceDestinations誰かが自分のデフォルト スキーマでうっかり作成した場合、複数のヒットが発生する可能性があります。
  4. 文字@sql列は、おそらく 100 文字より長くする必要があります。MAX255 や 1024 などで十分な文字数になるかどうかを考えて、パフォーマンスの違いに価値がないため、私は通常、これらのケースで使用します。
于 2012-04-15T20:54:05.350 に答える