プロシージャの結果をテーブル形式で取得して、SQLで処理する方法について説明します。 上記のほとんどは、複雑なSQLロジックと膨大な手順を備えたアプリケーションでのみ役立つと思います。 これらの方法が最も効果的だとは言えません。 これは私が仕事で使うものです。 これはすべてMicrosoft SQL Server 2008で機能します。
トピックに精通している人のために、5番目の方法まで投稿をスクロールすることをお勧めします。
データを取得する必要がある手順を次のようにします。
create procedure Proc1 as begin select 1 p1, 'b' p2 end
1方法
最も簡単な方法の1つ。
insert ... exec ...
コンストラクトの使用
if object_id(N'tempdb..
長所と短所:
- 送信されたフィールドは2回リストされ
select
(これらは内部select
、外部テーブル作成、およびinsert
)。 さらに、新しい同様の呼び出しごとにフィールドの列挙が発生します。 (この基準を追加します。多数の編集とプロシージャを呼び出す場所が多いため、出力データを変更するプロセスは非常に時間がかかるためです) - 重大な制限があります-テーブルは1つしか取得できません
- 手順が単純な出力モードで機能するためには、追加の手順は必要ありません。
insert
せずにexec Proc1
を実行するだけです
2方法
以前に作成したテーブルに書き込む。 ここで、プロシージャに挿入を追加する必要があります。
create procedure Proc1 as begin insert
基本的に、プロシージャ内に挿入行をラップします。
if object_id(N'tempdb..
長所と短所:
- 転送されたフィールドは2回リストされ、新しい使用ごとにもう1回転送されます
- プロシージャを単純な出力モードで動作
Proc1
は、 Proc1
から受け取っProc1
テーブルをProc1
する別のプロシージャを記述するか、 Proc1
内でそれらをProc1
出力するかを決定する必要があります。 たとえば、挿入用のテーブルが存在しないという事実に基づいて:
alter procedure Proc1 as begin declare @show bit if object_id(N'tempdb..#t1',N'U') is null begin set @show = 1 create table
私は、永続的なテーブルを介して転送する可能性を考慮していません。 必要に応じて、タスクはこのトピックに関係しません。 そうでない場合は、セッション間のロックと認証に関する不要な問題が発生します。
3方法
実際、これは2番目の方法の改良版です。 サポートを簡素化するには、カスタムテーブルタイプを作成します。 次のようになります。
create type tt1 as table(p1 int, p2 varchar(max)) go create procedure Proc1 as begin insert
長所と短所:
- 送信されるフィールドは2回リストされますが、新しい使用ごとに複雑さは増しません
- 結果の直接出力を整理するには、追加のアクションも必要です。
- インデックスと制限の作成には、次のような小さな困難があります。
select ... into
コンストラクトを使用して作成することはできません
4方法
3番目の方法の複雑さ。制限とインデックスを持つテーブルを作成できます。 前のものとは異なり、Microsoft SQL Server 2005で動作します。
create procedure Proc1 as begin insert
ただし、通常、delmy一時列は使用されず、代わりに1つの最初の列(ここではp1)でテーブルが作成されます。
長所と短所:
- 送信されるフィールドは2回リストされますが、新しい使用ごとに複雑さは増しません
- 結果を直接出力するには、追加の結果も必要です。
- 未知の理由により、
alter table #t1
コンストラクトでロックが発生することがあり、プロセスはProc1
( Proc1_AlterTable
はない!)の並列リクエストが完了することを予期することが予期せずに発見されました。 これが何に関連しているのか誰もが知っているなら、それを共有してください、私は聞いてうれしいです:)
5方法
このメソッドは、事前に作成されたプロシージャを使用します。 これは、実行中のプロシージャに動的SQLクエリを含めることに基づいています。 ただし、非常に使いやすいです。
それを使用するには、手順を次のように処理する必要があります。
1.手順の最初に、次の行を含めます。
if object_id('tempdb..
2.出力を選択するすべてのプロシージャを再実行して、
into #Output5
で始まる一時テーブルを作成します(たとえば、
into #Output5
、
into #Output5
、
into #Output5
に)。 プロシージャが結果セットを作成しない場合、アクションは不要です。
3.手順の最後に、次の行を含めます。
exec util.InclusionEnd
この例では、次を取得します。
create procedure Proc1 as begin if object_id('tempdb..#ttInclusion', 'U') is null create table
起動は次のとおりです。
if object_id('tempdb..
生成されたSQLは常に良いとは限らないため、上記の例は小さな命令に適しています。 大量のコードがある場合は、それを別のプロシージャに削除して動的部分からのみexec呼び出しを実行するか、データを新しい一時テーブルにリロードできます。 後者の場合、当然、別の「余分な」コピーが発生しますが、この段階で結果を事前にグループ化し、さらに処理するために必要なフィールドのみを選択できることがよくあります(たとえば、返されるデータがすべて不要な場合など) )
util.InclusionRun
関数には3つのパラメーターが渡されます。
@sql
呼び出されたプロシージャ内で実行するSQLスクリプト@notShowOutput
-if = 1の場合、 #Output
始まるテーブルの出力をブロックします@replaceableTableName
(default = '#Output'
) @sql
で使用されるテーブルの名前にプレフィックスを設定し、スクリプト内の対応する@sql
#Output*
テーブルに置き換えます。 たとえば、 #Output55
を指定し、2つのテーブル#Output55
および#Output0A
プロシージャで作成されている場合、 @sql
では、 #Output0A
を#InclusionOutput2
として、 #Output0A
を#InclusionOutput2
として#InclusionOutput2
作業は、最初に
Proc1
を実行せずに
Proc1
を実行すると、処理前に出力されるすべてのデータを出力するプロシージャの自然な操作につながるように構成されています。
使用のニュアンス:
- プロシージャでの
return
使用に制限を課します。 その前にutil.InclusionEnd
を実行する必要があります - 起動されたプロシージャから結果を出力するセレクターは、呼び出される前に作成された#出力テーブルよりも早く結果を出力します(出力は
util.InclusionEnd
のみ発生するため、これは論理的util.InclusionEnd
)
長所と短所:
- 渡されたフィールドは一度リストされますが、新しく使用するたびに複雑さは増しません
- 結果を直接出力するためのアクションは不要です。
- 使用のニュアンスを覚えて考慮する必要があります
- 追加の手順により、より多くの命令が実行され、頻繁な呼び出しのパフォーマンスが低下する可能性があります(これは起動時に1秒に1回未満は無視できると思います)
- おそらく、このメソッドに慣れていない従業員のコードの理解が複雑になる可能性があります。プロシージャは2つのexec-callを取得し、すべての
#Output
テーブルが表示されるという非自明性を取得します。 - 外部ツールなしでユニットテストを簡単に整理できます
使用のデモンストレーション:
非表示のテキストコード:
if object_id('dbo.TestInclusion') is not null drop procedure dbo.TestInclusion go create procedure dbo.TestInclusion @i int as begin if object_id('tempdb..#ttInclusion', 'U') is null create table
結果:
----------------------------------------------------------------------------------------------------------------------------------------------------------- 1: TestInclusion. myI : 2 3. 1 : " TestInclusion" myI ----------- 2 3 alt ----------------------- TestInclusion ------------------------------------------------------------------------------------------------------ 2: TestInclusion. testSum : 5 testSum ----------- 5
機能自体:
非表示のテキスト if not exists(select top 1 null from sys.schemas where name = 'util') begin exec ('create schema util') end go alter procedure util.InclusionBegin as begin set nocount on set ansi_warnings off declare @lvl int if object_id('tempdb..#ttInclusionParameters', 'U') is not null begin select @lvl = max(lvl) from
その他の方法
(
OUTPUT
)関数からのパラメーター転送を使用して、その値に基づいてテーブルを復元できます。 たとえば、カーソルまたはXMLを渡すことができます。
このテーマ
に関する記事があります。
このタスクにカーソルを使用するには、最初にカーソルが必要な場合にのみ理由がわかります。 しかし、XMLは有望に見えます。
以下は、非常に興味深いパフォーマンステストの結果です。
このタスクを簡素化するために使用する方法を聞くのは興味深いです:)
UPD 03/31/2014:コメントからのアイデアに関する投稿を修正