web-dev-qa-db-ja.com

ストレージプロジャジャの結果を一時テーブルに挿入する

どのようにSELECT * INTO [temp table] FROM [stored procedure]をするのですか? FROM [Table]ではなく[temp table]を定義せずに?

SelectBusinessLineからtmpBusLineまでのすべてのデータは正常に機能します。

select *
into tmpBusLine
from BusinessLine

私は同じことを試みていますが、データを返すstored procedureを使うことは全く同じではありません。

select *
into tmpBusLine
from
exec getBusinessLineHistory '16 Mar 2009'

出力メッセージ:

メッセージ156、レベル15、状態1、行2キーワード 'exec'の近くに誤った構文があります。

出力ストアドプロシージャと同じ構造を持つ一時テーブルを作成するいくつかの例を読みましたが、これは問題なく動作しますが、列を指定しないのがいいでしょう。

1456
Ferdeen

これには _ openrowset _ を使用できます。見てください。アドホック分散クエリを有効にするためのsp_configureコードも含まれています(まだ有効になっていない場合)。

CREATE PROC getBusinessLineHistory
AS
BEGIN
    SELECT * FROM sys.databases
END
GO

sp_configure 'Show Advanced Options', 1
GO
RECONFIGURE
GO
sp_configure 'Ad Hoc Distributed Queries', 1
GO
RECONFIGURE
GO

SELECT * INTO #MyTempTable FROM OPENROWSET('SQLNCLI', 'Server=(local)\SQL2008;Trusted_Connection=yes;',
     'EXEC getBusinessLineHistory')

SELECT * FROM #MyTempTable
666
Aaron Alton

最初に一時テーブルを宣言せずにそれを実行したい場合は、 ストアドプロシージャ ではなくユーザー定義関数を作成し、そのユーザー定義関数にテーブルを返させることができます。あるいは、ストアドプロシージャを使用したい場合は、次のようにしてください。

CREATE TABLE #tmpBus
(
   COL1 INT,
   COL2 INT
)

INSERT INTO #tmpBus
Exec SpGetRecords 'Params'
560
Gavin

SQL Server 2005では、INSERT INTO ... EXECを使用してストアドプロシージャの結果をテーブルに挿入できます。 MSDNのINSERTドキュメント から(実際にはSQL Server 2000用):

--INSERT...EXECUTE procedure example
INSERT author_sales EXECUTE get_author_sales
277
Matt Hamilton

これはあなたの質問を少し修正したものに対する答えです。ユーザ定義関数に対するストアドプロシージャの使用を中止できる場合は、インラインテーブル値のユーザ定義関数を使用できます。これは基本的には結果セットとしてテーブルを返すストアドプロシージャです(パラメータを取ります)。したがって、INTOステートメントを使用してうまく配置できます。

これと/その他のユーザ定義関数についてのよい 簡単な記事 があります。それでもストアドプロシージャが必要な場合は、インラインテーブル値のユーザー定義関数をストアドプロシージャでラップすることができます。ストアード・プロシージャーは、インライン表値ユーザー定義関数からselect *を呼び出すときにパラメーターを渡すだけです。

たとえば、特定の地域の顧客のリストを取得するためのインラインテーブル値ユーザー定義関数があります。

CREATE FUNCTION CustomersByRegion 
(  
    @RegionID int  
)
RETURNS TABLE 
AS
RETURN 
  SELECT *
  FROM customers
  WHERE RegionID = @RegionID
GO

その後、この関数を呼び出して、結果がそのようなものであることを確認できます。

SELECT * FROM CustomersbyRegion(1)

またはSELECT INTOを実行するには:

SELECT * INTO CustList FROM CustomersbyRegion(1)

それでもストアドプロシージャが必要な場合は、関数を次のようにラップします。

CREATE PROCEDURE uspCustomersByRegion 
(  
    @regionID int  
)
AS
BEGIN
     SELECT * FROM CustomersbyRegion(@regionID);
END
GO

私はこれが望ましい結果を得るための最も「ハックの少ない」方法だと思います。それらは追加の複雑さなしで使用されるように意図されていたのでそれは既存の機能を使用します。ストアドプロシージャでインラインテーブル値ユーザー定義関数をネストすることで、2つの方法で機能にアクセスできます。プラス!実際のSQLコードのメンテナンスポイントは1つだけです。

OPENROWSETの使用が提案されていますが、これはOPENROWSET関数が(Books Onlineから)使用されることを意図したものではありません。

OLE DBデータソースからリモートデータにアクセスするために必要なすべての接続情報を含みます。この方法は、リンクサーバーのテーブルにアクセスする代わりの方法で、OLE DBを使用してリモートデータに接続してアクセスする一時的なアドホック方法です。 OLE DBデータソースへのより頻繁な参照については、代わりにリンクサーバーを使用してください。

OPENROWSETを使用すると、仕事は完了しますが、ローカル接続を開いてデータを整列化するための追加のオーバーヘッドが発生します。セキュリティリスクをもたらすアドホッククエリの許可が必要であり、したがって望ましくない可能性があるため、これはすべての場合に選択肢とは限りません。また、OPENROWSETアプローチでは、複数の結果セットを返すストアドプロシージャを使用できなくなります。単一のストアドプロシージャで複数のインラインテーブル値ユーザー定義関数をラップすると、これを実現できます。

182
Christian Loris
EXEC sp_serveroption 'YOURSERVERNAME', 'DATA ACCESS', TRUE

SELECT  *
INTO    #tmpTable
FROM    OPENQUERY(YOURSERVERNAME, 'EXEC db.schema.sproc 1')
117
Quassnoi

最も簡単な解決策:

CREATE TABLE #temp (...);

INSERT INTO #temp
EXEC [sproc];

スキーマがわからない場合は、次の操作を実行できます。 この方法には深刻なセキュリティリスクがあることに注意してください。

SELECT * 
INTO #temp
FROM OPENROWSET('SQLNCLI', 
                'Server=localhost;Trusted_Connection=yes;', 
                'EXEC [db].[schema].[sproc]')
113
Tigerjz32

ストアドプロシージャが多数の列を返し、結果を保持するために一時テーブルを手動で "作成"したくない場合は、ストアドプロシージャに入って "into"句を最後のselect文を実行し、where句に1 = 0を追加します。

ストアドプロシージャを1回実行して戻り、追加したSQLコードを削除します。これで、ストアドプロシージャの結果に一致する空のテーブルができました。一時テーブル用に「create as as create」テーブルを作成することも、単にそのテーブルに直接挿入することもできます。

95
dotjoe
declare @temp table
(
    name varchar(255),
    field varchar(255),
    filename varchar(255),
    filegroup varchar(255),
    size varchar(255),
    maxsize varchar(255),
    growth varchar(255),
    usage varchar(255)
);
INSERT @temp  Exec sp_helpfile;
select * from @temp;
62
nitin

ストアドプロシージャの結果テーブルが複雑すぎて "create table"ステートメントを手動で入力できず、OPENQUERY OR OPENROWSETを使用できない場合は、sp_helpを使用して列のリストを生成しあなたのためのデータ型。列のリストを取得したら、それはニーズに合わせてフォーマットすることだけです。

ステップ1:出力クエリに "into #temp"を追加します(例: "select [...]から#temp from [...]"まで)。

最も簡単な方法はprocの出力クエリを直接編集することです。保存したプロシージャを変更できない場合は、その内容を新しいクエリウィンドウにコピーして、そこでクエリを変更できます。

ステップ2:一時テーブルに対してsp_helpを実行します。 (例: "exec tempdb..sp_help #temp")

一時テーブルを作成したら、一時テーブルに対してsp_helpを実行して、varcharフィールドのサイズを含む列とデータ型のリストを取得します。

ステップ3:データ列と型をcreate tableステートメントにコピーする

Sp_helpの出力を "create table"ステートメントにフォーマットするために使用するExcelシートがあります。気の利いたものは必要ありません。単にコピーしてSQLエディタに貼り付けてください。列名、サイズ、および型を使用して、ストアドプロシージャの結果をINSERTするために使用できる "Create table #x [...]"または "declare @x table [...]"ステートメントを作成します。

ステップ4:新しく作成したテーブルに挿入する

これで、このスレッドで説明されている他のソリューションと似たクエリができます。

DECLARE @t TABLE 
(
   --these columns were copied from sp_help
   COL1 INT,
   COL2 INT   
)

INSERT INTO @t 
Exec spMyProc 

この手法は、一時テーブル(#temp)をテーブル変数(@temp)に変換するためにも使用できます。これはcreate tableステートメントを自分で書くことよりも多くのステップになるかもしれませんが、大規模プロセスでのタイプミスやデータ型の不一致などの手動エラーを防ぎます。タイプミスをデバッグすることは、最初にクエリを書くよりも時間がかかることがあります。

44
FistOfFury

ストアドプロシージャはデータを取得するだけなのか、それとも変更するだけなのか。検索専用として使用する場合は、ストアドプロシージャを関数に変換し、宣言することなく次のように共通テーブル式(CTE)を使用できます。

with temp as (
    select * from dbo.fnFunctionName(10, 20)
)
select col1, col2 from temp

ただし、CTEから取得する必要があるものはすべて1つのステートメントでのみ使用してください。 with temp as ...を実行して、数行のSQLの後に使用することはできません。より複雑な照会のために、1つのステートメントに複数のCTEを含めることができます。

例えば、

with temp1020 as (
    select id from dbo.fnFunctionName(10, 20)
),
temp2030 as (
    select id from dbo.fnFunctionName(20, 30)
)
select * from temp1020 
where id not in (select id from temp2030)
44
Rashmi Pandit

Quassnoiはほとんどの方法で私をそこに置きましたが、一つ欠けていました:

****ストアドプロシージャでパラメータを使用する必要がありました。****

そして、OPENQUERYはこれが起こることを許可していません:

そのため、システムを動作させる方法を見つけました。また、テーブル定義をそれほど厳格にせず、別のストアドプロシージャ内で再定義する必要もありません(もちろん、壊れる可能性があります)。

はい。NO RESULT SETが同じ数のフィールドを返し、良好なデータを持つデータセットと同じ位置)。

テーブルが作成されたら、execストアドプロシージャを1日中一時テーブルに使用できます。


(上記のように)注意するには、データアクセスを有効にする必要があります。

EXEC sp_serveroption 'MYSERVERNAME', 'DATA ACCESS', TRUE

コード:

declare @locCompanyId varchar(8)
declare @locDateOne datetime
declare @locDateTwo datetime

set @locDateOne = '2/11/2010'
set @locDateTwo = getdate()

--Build temporary table (based on bogus variable values)
--because we just want the table definition and
--since openquery does not allow variable definitions...
--I am going to use bogus variables to get the table defintion.

select * into #tempCoAttendanceRpt20100211
FROM OPENQUERY(DBASESERVER,
  'EXEC DATABASE.dbo.Proc_MyStoredProc 1,"2/1/2010","2/15/2010 3:00 pm"')

set @locCompanyId = '7753231'

insert into #tempCoAttendanceRpt20100211
EXEC DATABASE.dbo.Proc_MyStoredProc @locCompanyId,@locDateOne,@locDateTwo

set @locCompanyId = '9872231'

insert into #tempCoAttendanceRpt20100211
EXEC DATABASE.dbo.Proc_MyStoredProc @locCompanyId,@locDateOne,@locDateTwo

select * from #tempCoAttendanceRpt20100211
drop table #tempCoAttendanceRpt20100211

元々提供されていた情報をありがとう...はい、最後に、データを使用するときにこれらすべての偽の(厳密な)テーブル定義を作成する必要はありません別のストアドプロシージャまたはデータベース、およびyesパラメーターも使用できます。

検索参照タグ:

  • 一時テーブルへのSQL 2005ストアドプロシージャ

  • ストアドプロシージャと変数2005を使用したopenquery

  • 変数を使用したopenquery

  • 一時テーブルにストアドプロシージャを実行する

更新:これは一時テーブルでは機能しないため、手動で一時テーブルを作成する必要がありました。

バマー通知:これは一時テーブルでは動作しません、 http://www.sommarskog.se/share_data.html#OPENQUERY

参照:次に、LOCALSERVERを定義します。例ではキーワードのように見えますが、実際には名前にすぎません。これがあなたのやり方です:

sp_addlinkedserver @server = 'LOCALSERVER',  @srvproduct = '',
                   @provider = 'SQLOLEDB', @datasrc = @@servername

リンクサーバーを作成するには、権限ALTER ANY SERVERを持っているか、固定サーバーロールsysadminまたはsetupadminのメンバーである必要があります。

OPENQUERYは、SQL Serverへの新しい接続を開きます。これにはいくつかの意味があります。

OPENQUERYで呼び出すプロシージャは、現在の接続で作成された一時テーブルを参照できません。

新しい接続には独自のデフォルトデータベース(sp_addlinkedserverで定義され、デフォルトはmaster)があるため、すべてのオブジェクト指定にデータベース名を含める必要があります。

オープントランザクションがあり、OPENQUERYを呼び出すときにロックを保持している場合、呼び出されたプロシージャはロックしたものにアクセスできません。つまり、注意しないと自分をブロックしてしまいます。

接続は無料ではないため、パフォーマンスが低下します。

OPENROWSETが問題を引き起こしている場合、2012年以降は別の方法があります。ここで説明したように、sys.dm_exec_describe_first_result_set_for_objectを使用します。 列名とストアドプロシージャの型を取得しますか?

まず、このストアドプロシージャを作成して、一時的なSQLを生成します。

CREATE PROCEDURE dbo.usp_GetStoredProcTableDefinition(
    @ProcedureName  nvarchar(128),
    @TableName      nvarchar(128),
    @SQL            nvarchar(max) OUTPUT
)
AS
SET @SQL = 'CREATE TABLE ' + @tableName + ' ('

SELECT @SQL = @SQL + '['+name +'] '+ system_type_name +''  + ','
        FROM sys.dm_exec_describe_first_result_set_for_object
        (
          OBJECT_ID(@ProcedureName), 
          NULL
        );

--Remove trailing comma
SET @SQL = SUBSTRING(@SQL,0,LEN(@SQL))    
SET @SQL =  @SQL +')'

プロシージャを使用するには、次の方法で呼び出します。

DECLARE     @SQL    NVARCHAR(MAX)

exec dbo.usp_GetStoredProcTableDefinition
    @ProcedureName='dbo.usp_YourProcedure',
    @TableName='##YourGlobalTempTable',@SQL = @SQL OUTPUT

INSERT INTO ##YourGlobalTempTable
EXEC    [dbo].usp_YourProcedure

select * from ##YourGlobalTempTable

グローバル一時テーブルを使用していることに注意してください。これは、EXECを使用して動的SQLを実行すると独自のセッションが作成されるため、通常の一時テーブルは後続のコードの範囲外になるためです。グローバル一時テーブルに問題がある場合、canは通常の一時テーブルを使用できますが、後続のSQLは動的である必要があります。 EXECステートメントによって。

27
StuartQ

このストアドプロシージャは仕事をします:

CREATE PROCEDURE [dbo].[ExecIntoTable]
(
    @tableName          NVARCHAR(256),
    @storedProcWithParameters   NVARCHAR(MAX)
)
AS
BEGIN
    DECLARE @driver         VARCHAR(10)
    DECLARE @connectionString   NVARCHAR(600)
    DECLARE @sql            NVARCHAR(MAX)
    DECLARE @rowsetSql      NVARCHAR(MAX)

    SET @driver = '''SQLNCLI'''

    SET @connectionString = 
        '''server=' + 
            CAST(SERVERPROPERTY('ServerName') AS NVARCHAR(256)) + 
            COALESCE('\' + CAST(SERVERPROPERTY('InstanceName') AS NVARCHAR(256)), '') + 
        ';trusted_connection=yes'''

    SET @rowsetSql = '''EXEC ' + REPLACE(@storedProcWithParameters, '''', '''''') + ''''

    SET @sql = '
SELECT
    *
INTO 
    ' + @tableName + ' 
FROM
    OPENROWSET(' + @driver + ',' + @connectionString + ',' + @rowsetSql + ')'

    EXEC (@sql)
END
GO

これは少しやり直したものです。 ストアドプロシージャの結果をtable に​​挿入して、実際に動作するようにします。

一時テーブルで機能させたい場合は、##GLOBALテーブルを使用して、後で削除する必要があります。

20
briantyler

あなたがSQL 2012以上を持っているのに十分幸運なら、あなたはdm_exec_describe_first_result_set_for_objectを使うことができます

Gotqnが提供するSQLを編集したところです。ありがとうございました。

これにより、プロシージャ名と同じ名前のグローバル一時表が作成されます。一時テーブルは後で必要に応じて使用できます。再実行する前に削除するのを忘れないでください。

    declare @procname nvarchar(255) = 'myProcedure',
            @sql nvarchar(max) 

    set @sql = 'create table ##' + @procname + ' ('
    begin
            select      @sql = @sql + '[' + r.name + '] ' +  r.system_type_name + ','
            from        sys.procedures AS p
            cross apply sys.dm_exec_describe_first_result_set_for_object(p.object_id, 0) AS r
            where       p.name = @procname

            set @sql = substring(@sql,1,len(@sql)-1) + ')'
            execute (@sql)
            execute('insert ##' + @procname + ' exec ' + @procname)
    end
17
Sandeep Gaadhe
  1. 以下のスキーマとデータでテーブルを作成しています。
  2. ストアドプロシージャを作成します。
  3. これで、自分のプロシージャの結果が何であるかがわかったので、次のクエリを実行しています。

    CREATE TABLE [dbo].[tblTestingTree](
        [Id] [int] IDENTITY(1,1) NOT NULL,
        [ParentId] [int] NULL,
        [IsLeft] [bit] NULL,
        [IsRight] [bit] NULL,
    CONSTRAINT [PK_tblTestingTree] PRIMARY KEY CLUSTERED
    (
        [Id] ASC
    ) WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY]
    GO
    SET IDENTITY_INSERT [dbo].[tblTestingTree] ON
    INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (1, NULL, NULL, NULL)
    INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (2, 1, 1, NULL)
    INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (3, 1, NULL, 1)
    INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (4, 2, 1, NULL)
    INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (5, 2, NULL, 1)
    INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (6, 3, 1, NULL)
    INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (7, 3, NULL, 1)
    INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (8, 4, 1, NULL)
    INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (9, 4, NULL, 1)
    INSERT [dbo].[tblTestingTree] ([Id], [ParentId], [IsLeft], [IsRight]) VALUES (10, 5, 1, NULL)
    
    SET IDENTITY_INSERT [dbo].[tblTestingTree] OFF
    

    VALUES(10、5、1、NULL)SET IDENTITY_INSERT [dbo]。[tblTestingTree]オン

    create procedure GetDate
    as
    begin
        select Id,ParentId from tblTestingTree
    end
    
    create table tbltemp
    (
        id int,
        ParentId int
    )
    insert into tbltemp
    exec GetDate
    
    select * from tbltemp;
    
15
Devansh

ストアドプロシージャの最初のレコードセットを一時テーブルに挿入するには、次のことを知っておく必要があります。

  1. ストアドプロシージャの最初の行セットのみが一時テーブルに挿入できます。
  2. ストアドプロシージャは動的T-SQLステートメントを実行してはいけません(sp_executesql
  3. 最初に一時テーブルの構造を定義する必要があります

上記は制限に見えるかもしれませんが、私たちは完全に理にかなっています - もしあなたがsp_executesqlを使っているなら2回と10回を返すことができます。 1つのT-SQLステートメント内の2つのテーブルで最大(OUTPUT節を使用し、トリガーは使用しない)。

したがって、問題は主にEXEC ... INTO ...ステートメントを実行する前に一時テーブル構造を定義する方法です。

1つ目はOBJECT_IDで動作し、2つ目と3つ目はアドホッククエリでも動作します。 CROSS APPLYを使用して同時に複数のプロシージャー用の一時表定義を作成できるので、spの代わりにDMVを使用することをお勧めします。

SELECT p.name, r.* 
FROM sys.procedures AS p
CROSS APPLY sys.dm_exec_describe_first_result_set_for_object(p.object_id, 0) AS r;

また、system_type_nameフィールドは非常に便利なので注意してください。列の完全な定義を格納します。例えば:

smalldatetime
nvarchar(max)
uniqueidentifier
nvarchar(1000)
real
smalldatetime
decimal(18,2)

ほとんどの場合、テーブル定義を作成するために直接使用できます。

そのため、ほとんどの場合(ストアドプロシージャが特定の条件を満たす場合)、そのような問題を解決するための動的ステートメントを簡単に作成できると思います(一時テーブルを作成し、その中にストアドプロシージャの結果を挿入し、データを使って必要な処理を行います)。 。


動的T-SQLステートメントが実行されたり、一時テーブルがストアード・プロシージャーで使用されたりする場合のように、上記のオブジェクトは ケース 内の最初の結果セット・データを定義できません。

14
gotqn

クエリにパラメータが含まれていない場合はOpenQueryを、それ以外の場合はOpenRowsetを使用してください。

基本的なことは、ストアドプロシージャに従ってスキーマを作成し、そのテーブルに挿入することです。例えば。:

DECLARE @abc TABLE(
                  RequisitionTypeSourceTypeID INT
                , RequisitionTypeID INT
                , RequisitionSourcingTypeID INT
                , AutoDistOverride INT
                , AllowManagerToWithdrawDistributedReq INT
                , ResumeRequired INT
                , WarnSupplierOnDNRReqSubmission  INT
                , MSPApprovalReqd INT
                , EnableMSPSupplierCounterOffer INT
                , RequireVendorToAcceptOffer INT
                , UseCertification INT
                , UseCompetency INT
                , RequireRequisitionTemplate INT
                , CreatedByID INT
                , CreatedDate DATE
                , ModifiedByID INT
                , ModifiedDate DATE
                , UseCandidateScheduledHours INT
                , WeekEndingDayOfWeekID INT
                , AllowAutoEnroll INT
                )
INSERT INTO @abc
EXEC [dbo].[usp_MySp] 726,3
SELECT * FROM @abc
12
ProblemSolver

コード

CREATE TABLE #T1
(
    col1 INT NOT NULL,
    col2 NCHAR(50) NOT NULL,
    col3 TEXT NOT NULL,
    col4 DATETIME NULL,
    col5 NCHAR(50) NULL,
    col6 CHAR(2) NULL,
    col6 NCHAR(100) NULL,
    col7 INT NULL,
    col8 NCHAR(50) NULL,
    col9 DATETIME NULL,
    col10 DATETIME NULL
)

DECLARE @Para1 int
DECLARE @Para2 varchar(32)
DECLARE @Para3 varchar(100)
DECLARE @Para4 varchar(15)
DECLARE @Para5 varchar (12)
DECLARE @Para6 varchar(1)
DECLARE @Para7 varchar(1)


SET @Para1 = 1025
SET @Para2 = N'6as54fsd56f46sd4f65sd'
SET @Para3 = N'XXXX\UserName'
SET @Para4 = N'127.0.0.1'
SET @Para5 = N'XXXXXXX'
SET @Para6 = N'X'
SET @Para7 = N'X'

INSERT INTO #T1
(
    col1,
    col2,
    col3,
    col4,
    col5,
    col6,
    col6,
    col7,
    col8,
    col9,
    col10,
)
EXEC [dbo].[usp_ProcedureName] @Para1, @Para2, @Para3, @Para4, @Para5, @Para6, @Para6

これが役に立つことを願っています。適切な資格を得てください。

10
SoftwareARM

私は配列/データテーブルをストアドプロシージャに渡すを見つけました。これはあなたがあなたの問題を解決する方法について別の考えを与えるかもしれません。

リンクは、ストアドプロシージャに渡すために Image typeパラメータを使用することを提案します。その後、ストアドプロシージャで、イメージは元のデータを含むテーブル変数に変換されます。

一時テーブルでこれを使用できる方法があるかもしれません。

10
kevchadders

私は同じ問題に遭遇しました、そして、これは私が ポールの提案から - 私がしたことです 。ここでの主な部分は、複数のユーザーが同時にストアドプロシージャ/スクリプトを実行しないようにするためにNEWID()を使用することです。これは、グローバル一時表の問題です。

DECLARE @sql varchar(max) = '', 
@tmp_global_table varchar(255) = '##global_tmp_' + CONVERT(varchar(36), NEWID())
SET @sql = @sql + 'select * into [' + @tmp_global_table + '] from YOURTABLE'
EXEC(@sql)

EXEC('SELECT * FROM [' + @tmp_global_table + ']')
9
zhongxiao37

もう1つの方法は、型を作成し、PIPELINEDを使ってオブジェクトを返すことです。ただし、これは列を知ることに限定されています。しかし、それにはできるという利点があります。

SELECT * 
FROM TABLE(CAST(f$my_functions('8028767') AS my_tab_type))
8
pierre

周りを検索した後、特にデータベース管理者でない場合、ストアドプロシージャの結果定義の汎用スキーマを使用して、OPENROWSETまたはOPENQUERYを使用せずに、ストアドプロシージャの一時テーブルを動的に作成する方法を見つけました。

SQLサーバーには、任意のプロシージャの結果セットのスキーマを提供できるbuit-in proc sp_describe_first_result_setがあります。この手順の結果からスキーマテーブルを作成し、すべてのフィールドを手動でNULLABLEに設定しました。

declare @procname varchar(100) = 'PROCEDURENAME' -- your procedure name
declare @param varchar(max) = '''2019-06-06''' -- your parameters 
declare @execstr nvarchar(max) = N'exec ' + @procname
declare @qry nvarchar(max)

-- Schema table to store the result from sp_describe_first_result_set.
create table #d
(is_hidden  bit  NULL, column_ordinal   int  NULL, name sysname NULL, is_nullable   bit  NULL, system_type_id   int  NULL, system_type_name nvarchar(256) NULL,
max_length  smallint  NULL, precision   tinyint  NULL,  scale   tinyint  NULL,  collation_name  sysname NULL, user_type_id  int NULL, user_type_database    sysname NULL,
user_type_schema    sysname NULL,user_type_name sysname NULL,Assembly_qualified_type_name   nvarchar(4000),xml_collection_id    int NULL,xml_collection_database    sysname NULL,
xml_collection_schema   sysname NULL,xml_collection_name    sysname NULL,is_xml_document    bit  NULL,is_case_sensitive bit  NULL,is_fixed_length_clr_type  bit  NULL,
source_server   sysname NULL,source_database    sysname NULL,source_schema  sysname NULL,source_table   sysname NULL,source_column  sysname NULL,is_identity_column bit NULL,
is_part_of_unique_key   bit NULL,is_updateable  bit NULL,is_computed_column bit NULL,is_sparse_column_set   bit NULL,ordinal_in_order_by_list   smallint NULL,
order_by_list_length    smallint NULL,order_by_is_descending    smallint NULL,tds_type_id   int  NULL,tds_length    int  NULL,tds_collation_id  int NULL,
tds_collation_sort_id   tinyint NULL)


-- Get result set definition of your procedure
insert into #d
EXEC sp_describe_first_result_set @exestr, NULL, 0

-- Create a query to generate and populate a global temp table from above results
select 
@qry = 'Create table ##t(' +
stuff(  
    (select ',' + name + ' '+ system_type_name + ' NULL'
    from #d d For XML Path, TYPE)
    .value(N'.[1]', N'nvarchar(max)')
, 1,1,'')
+ ')

insert into ##t 
Exec '+@procname+' ' + @param

Exec sp_executesql @qry

-- Use below global temp table to query the data as you may
select * from ##t

-- **WARNING** Don't forget to drop the global temp table ##t.
--drop table ##t
drop table #d 

Sql Serverバージョンで開発およびテスト済み-Microsoft SQL Server 2016(RTM)-13.0.1601.5(Build 17134 :)

使用しているSQLサーバーのバージョンに合わせてスキーマを調整できます(必要な場合)。

6
vendettamit

渡されているパラメータがわかっていて、sp_configureを作成するためのアクセス権がない場合は、これらのパラメータを使用してストアドプロシージャを編集し、同じ手順を##グローバルテーブルに格納できます。

3
lakshmivisalij

SPが1つのテーブルのみを返す場合、これはSQL Server 2014以降で実行できます。誰かが複数のテーブルでこれを行う方法を見つけた場合、私はそれについて知りたいです。

DECLARE @storeProcname NVARCHAR(MAX) = ''

SET @storeProcname = 'myStoredProc'

DECLARE @strSQL AS VARCHAR(MAX) = 'CREATE TABLE myTableName '

SELECT @strSQL = @strSQL+STUFF((
SELECT ',' +name+' ' + system_type_name 
FROM sys.dm_exec_describe_first_result_set_for_object (OBJECT_ID(@storeProcname),0)
FOR XML PATH('')
),1,1,'(') + ')'

EXEC (@strSQL)

INSERT INTO myTableName
EXEC ('myStoredProc @param1=1, @param2=2')

SELECT * FROM myTableName

DROP TABLE myTableName

これにより、返されたテーブルの定義がシステムテーブルから取得され、それを使用して一時テーブルが作成されます。その後、前述のようにSPからデータを入力できます。

動的SQLでも機能するこのバリアントもあります。

0
Matthew Baker

それは簡単な2ステップのプロセスです: - 一時テーブルを作成します - 一時テーブルに挿入します。

同じことを実行するためのコード:

CREATE TABLE #tempTable (Column1 int, Column2 varchar(max));
INSERT INTO #tempTable 
EXEC [app].[Sproc_name]
@param1 = 1,
@param2 =2;
0
S Krishna

まあ、あなたは一時テーブルを作成する必要がありますが、それは正しいスキーマを持っている必要はありません....私はそれが正しいデータで必要な列を持つように既存の一時テーブルを修正するストアドプロシージャを作成しました型と順序(既存のすべての列を削除し、新しい列を追加する):

GO
create procedure #TempTableForSP(@tableId int, @procedureId int)  
as   
begin  
    declare @tableName varchar(max) =  (select name  
                                        from tempdb.sys.tables 
                                        where object_id = @tableId
                                        );    
    declare @tsql nvarchar(max);    
    declare @tempId nvarchar(max) = newid();      
    set @tsql = '    
    declare @drop nvarchar(max) = (select  ''alter table tempdb.dbo.' + @tableName 
            +  ' drop column ''  + quotename(c.name) + '';''+ char(10)  
                                   from tempdb.sys.columns c   
                                   where c.object_id =  ' + 
                                         cast(@tableId as varchar(max)) + '  
                                   for xml path('''')  
                                  )    
    alter table tempdb.dbo.' + @tableName + ' add ' + QUOTENAME(@tempId) + ' int;
    exec sp_executeSQL @drop;    
    declare @add nvarchar(max) = (    
                                select ''alter table ' + @tableName 
                                      + ' add '' + name 
                                      + '' '' + system_type_name 
                           + case when d.is_nullable=1 then '' null '' else '''' end 
                                      + char(10)   
                              from sys.dm_exec_describe_first_result_set_for_object(' 
                               + cast(@procedureId as varchar(max)) + ', 0) d  
                                order by column_ordinal  
                                for xml path(''''))    

    execute sp_executeSQL  @add;    
    alter table '  + @tableName + ' drop column ' + quotename(@tempId) + '  ';      
    execute sp_executeSQL @tsql;  
end         
GO

create table #exampleTable (pk int);

declare @tableId int = object_Id('tempdb..#exampleTable')
declare @procedureId int = object_id('examplestoredProcedure')

exec #TempTableForSP @tableId, @procedureId;

insert into #exampleTable
exec examplestoredProcedure

sys.dm_exec_describe_first_result_set_for_objectがストアドプロシージャの結果を判断できない場合(たとえば一時テーブルを使用している場合など)、これは機能しません。

0
jmoreno