2016-04-05 6 views
2

私は、私が見つけたさまざまな方法を使用して、ストアドプロシージャの出力を一時テーブルまたはテーブル変数に保存しようとしています。ストアドプロシージャからの広範な結果セットを一時テーブルまたはテーブル変数に挿入する方法はありますか?

私は一時テーブルを宣言してからやって試してみた:ストアドプロシージャが結果セットで約550の列を持っているので、私は、問題に実行しているよ

INSERT INTO #temptable EXEC storedprocedurename 

。最大行サイズが8060バイトを超えているため、ワイドテーブルを作成できません。

残念ながら、ストアドプロシージャを編集する機能はありませんが、実際には約200個のカラムにアクセスする必要があります。サイズの問題を回避するために、テーブル変数または一時テーブルにそれらを貼り付けたり、テーブルの結果全体を固定したりしているのですか?

私はOPENROWSETも調べましたが、使用しているSQLサーバーではADHOCクエリを有効にすることはできません。私が知っている唯一のことは、ストアドプロシージャのクローンを作成し、私が必要としないカラムの1/2を取り除くことですが、ソースストアドプロシージャはこれまでどおり変更されており、私はそれについてはわかりません。

+0

550カラムあなたが戻ってくる200の列で何をしていますか? - おそらく、SQLの外側とアプリケーション層で、より小さなサブセットの列を選択できる優れたソリューションがありますか? –

+0

私は同意します。しかし、私が与えられた要求/タスクは、これらの200の列を報告のために利用可能にすることです。私は同じストアドプロシージャを使用するCrystalレポートの実行の結果としてより多くの研究が必要な場合に追加の詳細をクエリするために使用できるレポートテーブルを構築するために、データベースの多くの行に対してストアドプロシージャを実行しています。 もっと良い方法があると私は同意しますが、尋ねることに基づいて私は自分ができることには限界があります。 – sallou

答えて

0

制限の数の列が終了に達するまで、テンポラリテーブルに送信されるデータにカーソルを使用できます。これがパフォーマンスに影響を与える可能性があります。

1

INSERT ... EXECステートメントにいくつかの列だけを挿入する方法が見つかりません。これは、テンポラリテーブルには550列すべてが含まれている必要があります。しかし、返されたすべてのデータをそれらの列に挿入しないようにすることができます。

最初のオプション。 INSTEAD OFトリガー。私は1つを使用していないので、それが一時テーブルで動作するかどうかはわかりません。それは通常のテーブルで動作するはずです。主なアイデア - トリガーでINSERTの操作を傍受し、8060バイトの制限を超え、必要としない長い値をNULLsで置き換えます。

2番目のオプション。それらの長いvarcharカラムの場合は、CREATEのtempテーブルステートメントにvarchar(1)と定義する必要はありません。主なアイデア - 最後の行が8060バイト未満になることを願って、1文字にする必要がない長いvarchar値を切り捨てます。この方法を試すと、次のエラーメッセージが表示されます。String or binary data would be truncated.このエラーメッセージを表示しないようにして、サーバーでデータを切り捨てるようにします。SET ansi_warnings OFF

1

OPENQUERYを試しましたか?私はそれがOPENROWSETと同じ要件を持っているとは思わない。あなたは "ループバック"リンクサーバーを作成し、それをOPENQUERYの呼び出しで使用します。ただし、OPENQUERYにはいくつかの制限がありますが、動的SQLまたはそれ以外の何もかも内部的に使用されるsp_describe_first_result_setという制限がありません。その後

EXEC sp_addlinkedserver 
    @server = N'Loopback', 
    @srvproduct = N'', 
    @provider = N'SQLNCLI', 
    @datasrc = N'<your server name>'; 

してみてください:

SELECT * FROM OPENQUERY(Loopback, N'EXEC sp_who2'); -- this gets an error 

SELECT * FROM OPENQUERY(Loopback, N'EXEC sp_who'); -- this works 

OPENQUERYがオプションでない場合、これはまだSQLCLRを経由して多くの困難を伴わずに行うことができます。次の2つの主要なオプションがあります。ストアドプロシージャ

  1. SQLCLR:既存のストアドプロシージャは、(すなわち、動的SQL、副作用機能、DMLを行っていることに関連する制限はありませんので、これは容易な方法であるSETステートメントなど)。内部コンテキスト接続を使用することができます(つまり、既に存在する同じセッションに接続し、アセンブリがSAFEとマークされている間に動作します)。ストアドプロシージャを実行し、結果をSqlDataReaderで実行し、各行を元に戻しますSqlContext.Pipe.SendResultsRowを使用して発信者に送信します(つまり、行を戻す)。 SqlDataRecordを使用して結果セット構造を作成し、必要な列のみを作成します。これらの各列をSqlDataReaderから設定すると、SqlDataReaderに決してアクセスされなかった列が多数あることに関係なく処理できます。

  2. SQLCLR表値関数:などこの方法は、実際にあなたがWHERE条件を追加できるように、操作に対してSELECTを発行することができるという利点を持っている、あなたはまだちょうど、SqlCommand/SqlDataReaderを使用しますSQLCLRストアドプロシージャと同様です。ただし、T-SQL関数と同様にいくつかの制限があります。あなたの現在のストアドプロシージャは、T-SQL関数(すなわち、動的SQL、副作用関数、DML、SET文など)を作成するための規則に違反していない場合は

    • することは、あなたは読み取り専用に行うことができますSQLCLR関数からストアドプロシージャを実行して内部コンテキスト接続を使用している(つまり、すでに存在する同じセッションにアタッチします。これはアセンブリがSAFEとマークされている間に機能します)。ただし、行を元に戻すことはできませんが、代わりにメモリに格納する必要があります(T-SQLマルチステートメントTVFでテーブル変数を使用する場合と同様)、プロセスの最後に結果を解放します。
    • 現在のストアドプロシージャがこれらのルールに違反している場合(SET NOCOUNT ON;SETステートメントのように違反になります)、これもできますが、通常の/外部接続を使用する必要がありますコンテキスト接続は機能しません。このオプションは、yield returnを使用して行を戻すことができるという利点がありますが、同じセッションの一部ではないため(ローカル一時表またはCONTEXT_INFOは表示されません)、アセンブリに署名し、そのDLL /アセンブリからmasterにAsymmetric Keyを作成し、そのAsymmetric Keyからログインを作成してから、EXTERNAL_ACCESSとマークする必要があります(ではなくにデータベースをTRUSTWORTHY ONに設定する必要があります)最後にログインするにはEXTERNAL ACCESS ASSEMBLYの許可を与えます)。

そして、あなたがヒットしているSQL ServerがAd Hoc Distributed Queriesを許可しないことを見て、DBAがSQLCLRも起因する「セキュリティ」リスクに有効にすることはできませんと言っていたならば、その後に彼らの注意を向けてください。 SQL Server CentralでSQLCLRについて書いているシリーズ:Stairway to SQLCLR(そのサイトのコンテンツを表示するには無料登録が必要です)。最初の4つの記事では、特にアセンブリがSAFE(前述の3つのオプションのうちの2つを含む)とマークされている場合、いくつかの例を介して、SQLCLRの安全性を示しています。

+0

ありがとうございます。あなたのコメントに基づいて、私はいくつかの調査を行いました.SQLCLRは.NETフレームワークで外部アプリケーションを使用する必要がある機能であり、SQLサーバー自体を使用するだけでは実行できません(SQLサーバーエージェントジョブ)、正しい? – sallou

+0

@sallou SQLCLRはSQL Serverに読み込まれる.NETです( 'sys.assemblies'の内部にあります)。 SQLCLRは、外部ではなくSQL Server内で.NETコード(制限あり)を実行できるフレームワークです。ストアドプロシージャ、関数、型、集計、およびトリガを作成できます。それが何であり、でき、できないのかについての詳細については、私が答えにリンクしている一連の記事をご覧ください。それ以外では、あなたは 'OPENQUERY'を試しましたか? –

関連する問題