3

一見単純なリクエストがあります。この基準に従って、データベース内のすべてのストアドプロシージャをスクリプト化する必要があります。

  1. 次のようにprocが存在する場合、スクリプトにはドロップを含める必要があります...

    IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[myproc]') AND type in (N'P', N'PC'))
    
  2. スクリプトにsp_executesqlを含めることはできないため、このようなものはありません...

    EXEC dbo.sp_executesql @statement = '....'
    
  3. ストアドプロシージャごとに個別のスクリプトファイルが必要です。したがって、[ストアドプロシージャ名].sqlになります

組み込みのSQL生成スクリプトを試してみると、別のファイルのオブジェクトをスクリプト化するためのチェックボックスを介して別のファイルのprocを取得でき、ifexistsドロップも取得できます。ただし、不要なsp_executesqlを使用します。

だから私はSMOを少し試してみて、同様の問題を見つけました...

A.残念ながら、以下はdropステートメントのみをスクリプト化したものです。それをクリエイトと組み合わせる方法はありません。したがって、個別のファイルを取得でき、sp_executesqlは取得できませんが、上記の#1がまだ欠落しています。

    Scripter scripter = new Scripter();
    scripter.Options.ScriptDrops = true;

B.次に、次のオプションは、sp_executesqlを使用するように出力を変更します

    scripter.Options.IncludeIfNotExists = true;

C.最後に、テキストを手動で追加できます。TextHeaderに正常に設定されています。ただし、scripter.Script()は例外 "{" Script failed forStoredProcedure'dbo.myproc'をスローします。"}

    storedProcedure.TextHeader = string.Format("IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'{0}') AND type in (N'P', N'PC')) \r\nDROP PROCEDURE {0} \r\nGO\r\n{1}", storedProcedure.Name, storedProcedure.TextHeader);
    scripter.Options.FileName = Path.Combine(storedProceduresPath, storedProcedure.Name + ".sql");
    scripter.Script(new Urn[] { storedProcedure.Urn });  //Exception! - Script failed for StoredProcedure

これがそんなに奇妙なことだとは想像できないので、人々がこれをどのように達成しているのだろうか?sql --tasks --generateスクリプトを使用して個別のファイルを作成する必要がある場合は悲しいです。その後、不要な「EXEC dbo.sp_executesql @statement =N'」をクリアするアプリが続きます。

4

1 に答える 1

2

次のコードサンプルはPowerShellに含まれていますが、SMOを使用しているため、簡単にc#に変換できます。

Scripterは少し遅いと感じたので、私は少し変わった方法を使用していますが、これは私にとって何百回も機能しました。

$spはデータベース内のストアドプロシージャであり、すべてのSPをforeachingします。

foreach($sp in $db.StoredProcedures)

スクリプトドロップ:String.Formatを使用するだけです:)

$sbHead.AppendLine( [string]::Format(@"
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[{0}].[{1}]') AND type in (N'P', N'PC'))
GO
"@, $sp.Schema, $sp.Name))

スクリプト本体

$sbBody.AppendLine( [string]::Format(@"
print 'creating "{1}"...'
--   *  *  *  *  #{0}:{1}; CreateDate:{2}, DateLastModified:{3}   *  *  *  *
GO
{4}
{5}
GO
"@, $cnt, $sp.Name, $sp.CreateDate, $sp.DateLastModified, $sp.TextHeader, $sp.TextBody))

これにより、いくつかの追加情報が出力されます。

  • print 'creating "{1}"...'一度は作品が数分間ぶら下がっていたので、そこに入れてください。現在のSP名を知っていると、問題の原因がわかります。リンクサーバーへの接続がダウンしていました...
  • SPの作成と最終更新日ですが、実際には必要ありません。

この方法ではスクリプトの依存関係が考慮されていないため、コンソールに「現在のSPxyはSPdsaに依存していますが、とにかく作成しています」などの警告メッセージが表示されます。ただし、これらの依存関係を解決しないため、実行速度は速くなります。いつも私のために働いていました...

完全なスクリプトと出力例をGitHubにアップロードしました:SqlScriptExport.ps1

これはいくつかの追加のことを行います:

  • 指定されたプレフィックスで始まるSPのみをスクリプト化します(プレフィックスが空の場合はすべて)
  • スクリプトビューも同様に、プレフィックスの同じフィルタリング。
于 2012-07-08T10:20:58.510 に答える