저장 프로 시저의 결과를 임시 테이블에 삽입


1577

어떻게합니까 SELECT * INTO [temp table] FROM [stored procedure]? 아니고 FROM [Table]정의하지 않고 [temp table]?

Select모든 데이터 BusinessLinetmpBusLine작품 벌금.

select *
into tmpBusLine
from BusinessLine

나는 똑같이 노력하고 있지만 stored procedure데이터를 반환 하는 것을 사용하는 것은 완전히 동일하지 않습니다.

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

출력 메시지 :

메시지 156, 수준 15, 상태 1, 줄 2 키워드 'exec'근처의 구문이 잘못되었습니다.

출력 저장 프로 시저와 동일한 구조로 임시 테이블을 만드는 몇 가지 예를 읽었지만 제대로 작동하지만 열을 제공하지 않는 것이 좋습니다.


22
SELECT * INTO [TABLE NAME]을 사용하면 열이 원래 테이블에서 복사되므로 열을 알 수 있습니다. 이것은 저장 프로 시저에 대해 동일한 작업을 수행하려는 경우 원하는 것입니다.
Ferdeen


7
"select * into tmpBusLine"이 영구 테이블을 생성한다는 점을 지적하고 싶을뿐입니다. "select * into #tmpBusLine"을 원할 것입니다. 나는 원래의 포스터가 이미 이것을 발견했다고 확신하지만,이 게시물이 현재 "temp table로 선택"검색에 대한 최고 결과
이므로이

2
이 문제가 해결되었는지는 모르지만 오류가 발생하는 이유는 from 키워드 때문입니다.
Wes Palmer

9
Microsoft는 SELECT * INTO FROM EXEC를 추가해야합니다! 부디!
kjmerf

답변:


704

이를 위해 OPENROWSET 을 사용할 수 있습니다 . 보세요 또한 Ad Hoc Distributed Queries가 활성화되어 있지 않은 경우이를 활성화하기 위해 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

28
이것이 올바른 방법입니다. OPENROWSET은 저장 프로 시저의 결과를 테이블 식으로 처리 할 수있는 유일한 방법입니다.
Rob Farley

37
이것은 테이블에 삽입하는 것이 약간 번거로운 것 같습니다. 할 많은 구성. 또한 시도 할 때 "Msg 7357, 수준 16, 상태 2, 줄 1 개체"EXEC GetPartyAnalysisData 146 "개체를 처리 할 수 ​​없습니다. 연결된 서버"(null) "에 대한 OLE DB 공급자"SQLNCLI "에 개체 중 하나가 있음을 나타냅니다 열이 없거나 현재 사용자에게 해당 개체에 대한 권한이 없습니다. " 그래서 당신은 연결된 서버를 설정해야합니다 ...
Ferdeen

10
연결된 서버는 필요하지 않지만 연결 문자열을 올바르게 가져와야합니다. 또한 데이터베이스 이름과 sp의 소유자를 포함하여 저장 프로 시저의 전체 경로를 지정하십시오.
MartW

18
네! 같은 서버에 대한 참조? 추잡한. 확실히 더 많은 해킹 수동으로 임시 테이블을 생성하는 것보다
팀 아벨

23
나는 이것이 해킹이므로 등이 벽에 닿지 않는 한 피해야 할 것입니다. sp를 함수로 변경하는 것이 더 좋은 각도 일 것입니다. 이모.
greg

623

임시 테이블을 먼저 선언하지 않고 수행하려는 경우 저장 프로 시저 대신 사용자 정의 함수를 작성하여 해당 사용자 정의 함수가 테이블을 리턴하도록 할 수 있습니다. 또는 저장 프로 시저를 사용하려면 다음과 같이 해보십시오.

CREATE TABLE #tmpBus
(
   COL1 INT,
   COL2 INT
)

INSERT INTO #tmpBus
Exec SpGetRecords 'Params'

170
요점은 명시 적으로 선언하지 않고도 스키마를 생성하는 것이 중요하다고 생각합니다.
Craig

5
위와 @Aaron Alton 솔루션의 차이점이 무엇인지 알고 싶습니다. 이것은 훨씬 간단 해 보이지만 다른 의미는 확실하지 않습니다.
funkymushroom

11
이것은 작동하지만 SpGetRecords 저장 프로 시저에 추가 열을 추가하면 폭파됩니다.
Brady Holt

15
호출 스택 당 하나의 INSERT INTO EXEC 만 얻습니다. SpGetRecords 및 호출하는 다른 프로세스는 고유 한 코드에서이 전략을 사용할 수 없습니다. 이것은 SpGetRecords의 관리자를 놀라게 할 수 있습니다.
매트 스티븐슨

33
이것은 전혀 질문에 대한 답변이 아니며 왜 그렇게 많이 올려 진지 모르겠습니다. OP는 명시 적으로 "[temp table]을 정의하지 않고"명시했으며 첫 번째 줄에는 임시 테이블 작성 문이 있습니다.
NickG

296

SQL Server 2005에서는 INSERT INTO ... EXEC저장 프로 시저 결과를 테이블에 삽입하는 데 사용할 수 있습니다 . 에서 MSDN의 INSERT문서 (사실 SQL Server 2000의) :

--INSERT...EXECUTE procedure example
INSERT author_sales EXECUTE get_author_sales

122
이를 위해서는 authors_sales를 미리 정의해야합니다. 나는 이것을 피하려고합니다. 감사.
Ferdeen

5
나는 많이 생각했다. 매우 유용합니다. tmp 테이블에 즉시 삽입하지만 저장된 프로 시저에서 반환 된 데이터 집합 구조를 알아야하는 경우에는 유용하지 않습니다. 도와 주셔서 감사합니다.
Ferdeen


4
동일한 스키마를 사용하려면 다음과 같이 복사 할 수 있습니다. realTable에서 tempTable에 top 0 *를 선택하십시오 ( stackoverflow.com/a/9206463/73794 )
Even Mien

@EvenMien 나는 당신의 의견을 보았을 때 순간적으로 흥분했습니다 ...하지만 슬프게도 당신의 proc 결과가 실제로 실제 테이블을 반영하는 경우에만 작동합니다 :(
BVernon

193

이것은 약간 수정 된 질문에 대한 답변입니다. 사용자 정의 함수에 대해 저장 프로 시저 사용을 포기할 수 있으면 인라인 테이블 반환 사용자 정의 함수를 사용할 수 있습니다. 이것은 본질적으로 테이블을 결과 집합으로 반환하는 저장 프로 시저 (매개 변수 사용)입니다. 따라서 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

이것이 원하는 결과를 얻는 가장 '해킹없는'방법이라고 생각합니다. 추가 합병증없이 사용하기 위해 기존 기능을 사용합니다. 저장 프로 시저에 인라인 테이블 반환 사용자 정의 함수를 중첩하면 두 가지 방법으로 기능에 액세스 할 수 있습니다. 을 더한! 실제 SQL 코드에 대한 유지 관리 지점은 하나뿐입니다.

OPENROWSET의 사용이 제안되었지만 OPENROWSET 기능이 (도서에서 온라인으로) 의도 된 것은 아닙니다.

OLE DB 데이터 소스에서 원격 데이터에 액세스하는 데 필요한 모든 연결 정보를 포함합니다. 이 방법은 연결된 서버에서 테이블에 액세스하는 대신 사용할 수 있으며 OLE DB를 사용하여 원격 데이터에 연결하고 액세스하는 일회성 임시 방법입니다. OLE DB 데이터 소스를 더 자주 참조하려면 연결된 서버를 사용하십시오.

OPENROWSET을 사용하면 작업이 완료되지만 로컬 연결을 열고 데이터를 마샬링하는 데 약간의 추가 오버 헤드가 발생합니다. 보안 위험이있는 임시 쿼리 권한이 필요하므로 원하지 않는 경우도 있으므로 모든 경우에 옵션이 될 수는 없습니다. 또한 OPENROWSET 접근 방식은 둘 이상의 결과 집합을 반환하는 저장 프로 시저를 사용하지 못하게합니다. 단일 저장 프로 시저에서 여러 인라인 테이블 값 사용자 정의 함수를 래핑하면이를 달성 할 수 있습니다.


4
+1 테이블 반환 함수는 적절한 솔루션입니다. 사소한 단점을 고려해야합니다. 테이블 반환 함수는 추가 데이터베이스 개체이므로 권한을 부여해야 할 수도 있습니다.
spencer7593

2
해결책을 좋아하십시오. 내가 겪은 사소한 문제 중 하나는 내 테이블이 저장 프로 시저에서 가질 수있는 순서대로 정렬 할 수 없다는 것입니다. 음, 잘 정리하겠습니다
mrwaim

5
하나 더 걸림- "함수 내에서 임시 테이블에 액세스 할 수 없습니다"
mrwaim

7
원래 질문은 sp의 결과로 임시 테이블을 작성하는 방법입니다. 이것은 좋은 패턴이지만이 질문을 다루지 않습니다
greg

16
greg, 내 답변의 첫 번째 줄에 "이것은 약간 수정 된 질문에 대한 답변입니다." 귀하의 의견은 중복됩니다.
Christian Loris

131
EXEC sp_serveroption 'YOURSERVERNAME', 'DATA ACCESS', TRUE

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

2
"Msg 208, Level 16, State 1, Line 1 유효하지 않은 개체 이름 'tmpBusLine'을 가져 오십시오 (아마 사전 정의되지 않았기 때문).
Ferdeen

1
@Ferds : 죄송합니다. 처음에는 요청을 이해하지 못했습니다. 다른 솔루션으로 업데이트되었습니다.
Quassnoi

26
훌륭한 솔루션. 한가지주의 할 점은 서버에서 'DATA ACCESS'를 활성화해야합니다. EXEC sp_serveroption 'TheServerName', 'DATA ACCESS', TRUE
jcollum

8
서버에 대한 원격 액세스를 허용해야합니다. 보안에 영향을 미칩니다.
BraveNewMath

7
대상 저장 프로 시저가 임시 테이블을 사용하는 경우에는 작동하지 않습니다
Sal

125

가장 쉬운 솔루션 :

CREATE TABLE #temp (...);

INSERT INTO #temp
EXEC [sproc];

스키마를 모르는 경우 다음을 수행 할 수 있습니다. 이 방법에는 심각한 보안 위험이 있습니다.

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

반환 된 결과 집합의 열을 모른다면 ??? 열이 다를 수 있음을 의미합니다. 그래서 결과를 임시 테이블에 삽입하는 방법은 무엇입니까 ??
SHEKHAR SHETE

OPENQUERY를 사용할 수 있지만 보안 결함이 있으므로 권장되지 않습니다.
Tigerjz32

1
"반환 된 결과 집합의 열을 모른다면"논리에서 사용할 수 없습니다. 데이터가 무엇인지 모른다면 어떻게 데이터를 사용합니까?
Adriaan Davel

@AdriaanDavel 나는 당신이 항상 당신의 데이터를 알고 있어야한다는 것에 동의한다. 이 경우 OPENROWSET을 사용하여 테이블을 즉시 삽입하고 만들 수 있습니다. 그러나 이렇게하면 명백한 보안 위험이 있습니다 ...
Tigerjz32

1
@nurettin 때로는 저장 프로 시저가 무엇을 반환할지 알지 못합니다. 이 경우 어떻게됩니까? 저장 프로 시저가 무엇을 반환할지 모르는 경우 임시 테이블을 어떻게 만들어 저장 프로 시저에서 삽입 할 수 있습니까?
Tigerjz32

106

저장 프로 시저가 많은 열을 반환하고 결과를 보유하기 위해 임시 테이블을 수동으로 "생성"하지 않으려는 경우 가장 쉬운 방법은 저장 프로 시저로 이동하여 "into"절을 추가하는 것입니다. 마지막 select 문을 작성하고 where 절에 1 = 0을 추가하십시오.

저장 프로 시저를 한 번 실행 한 후 돌아가서 방금 추가 한 SQL 코드를 제거하십시오. 이제 저장 프로 시저의 결과와 일치하는 빈 테이블이 생깁니다. 임시 테이블에 대해 "만들기 스크립트 테이블"또는 단순히 해당 테이블에 직접 삽입 할 수 있습니다.


9
+1, 훌륭한 제안. @TableCreate라는 sproc에 빠른 선택적 변수를 추가하거나 null이 아닌 경우 위의 단계를 수행하는 것과 유사한 것을 추가 할 수도 있습니다. 일단 설정되면 sproc을 변경할 필요가 없습니다.
Ian Roke

1
@dotjoe SELECT INTO임시 테이블을 작성하고 임시 테이블에서 작성하는 스크립트 테이블을 수행합니까? 임시 테이블이 표시 tempdb되지만 마우스 오른쪽 버튼을 클릭하고 스크립트 작성을 수행 할 수 없습니다. 도움을 주시면 감사하겠습니다.
DotnetDude

2
@DotNetDude 당신은 select ... into new_table내재적으로 실제 테이블을 만들 수 있습니다 .
dotjoe

그런 다음 빈 테이블 스키마에서 대략적인 열 정의를 가져옵니다. 마지막에 '...'을 합법적 인 TABLE_NAME으로 declare @s varchar(max)='';select @s=@s+','+COLUMN_NAME+' '+DATA_TYPE+isnull('('+case CHARACTER_MAXIMUM_LENGTH when -1 then 'max' else cast(CHARACTER_MAXIMUM_LENGTH as varchar(10))end+')','')from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='...';select @s
바꾸십시오

이것이 최고의 솔루션입니다!
Lucas925

66
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;

3
임시 테이블을 먼저 정의하지 않고 삽입을 수행하여 OP 원래 질문을 해결하지 않습니다.
t.durden

48

저장 프로시 저는 데이터를 검색 만하거나 수정합니까? 검색에만 사용되는 경우 다음과 같이 저장 프로 시저를 함수로 변환하고 선언하지 않고도 CTE (Common Table Expressions)를 사용할 수 있습니다.

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

그러나 CTE에서 검색해야하는 것은 하나의 명령문에서만 사용해야합니다. with temp as ...몇 줄의 SQL 후에는 사용할 수 없습니다 . 보다 복잡한 쿼리를 위해 하나의 명령문에 여러 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)

1
이들은 임시 테이블이 아니며 CTE입니다. technet.microsoft.com/ko-kr/library/…
yucer

5
@yucer 감사합니다 ... 나는 그들이 그때 CTE라고 불렀다는 것을 믿습니다 :)
SO User

48

저장 프로 시저의 결과 테이블이 너무 복잡하여 "테이블 만들기"문을 직접 입력 할 수없고 OPENQUERY 또는 OPENROWSET을 사용할 수없는 경우 sp_help를 사용하여 열 및 데이터 유형 목록을 생성 할 수 있습니다. 열 목록이 있으면 필요에 맞게 형식을 지정하기 만하면됩니다.

1 단계 : "into #temp"를 출력 쿼리에 추가합니다 (예 : "select from ......을 #temp from [...]").

가장 쉬운 방법은 proc에서 출력 쿼리를 직접 편집하는 것입니다. 저장된 프로 시저를 변경할 수없는 경우 내용을 새 쿼리 창에 복사하고 쿼리를 수정할 수 있습니다.

2 단계 : 임시 테이블에서 sp_help를 실행하십시오. (예 : "exec tempdb..sp_help #temp")

임시 테이블을 만든 후 임시 테이블에서 sp_help를 실행하여 varchar 필드의 크기를 포함한 열 및 데이터 유형 목록을 가져옵니다.

3 단계 : 데이터 열 및 유형을 테이블 작성 명령문으로 복사

sp_help의 출력을 "테이블 만들기"문으로 형식화하는 데 사용하는 Excel 시트가 있습니다. 멋진 것을 필요로하지 않고 SQL 편집기에 복사하여 붙여 넣으십시오. 열 이름, 크기 및 유형을 사용하여 저장 프로 시저의 결과를 삽입하는 데 사용할 수있는 "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명령문을 직접 작성하는 것보다 더 많은 단계 일 수 있지만 큰 프로세스에서 오타 및 데이터 유형 불일치와 같은 수동 오류를 방지합니다. 오타 디버깅은 처음에 쿼리를 작성하는 것보다 시간이 더 걸릴 수 있습니다.


37

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을 실행하면 자체 세션이 작성되므로 일반적인 임시 테이블은 후속 코드의 범위를 벗어나기 때문입니다. 글로벌 임시 테이블이 문제인 경우 일반 임시 테이블을 사용할 있지만 후속 SQL은 동적이어야합니다 (즉, EXEC 문에 의해 실행되어야 함).


4
에서 테이블을 만드는 것을 잊었습니다 @SQL.
Trisped

32

Quassnoi는 저에게 가장 많은 길을 제시했지만 한 가지 누락되었습니다.

**** 저장 프로 시저에서 매개 변수를 사용해야했습니다. ****

그리고 OPENQUERY는 이것을 허용하지 않습니다.

그래서 시스템을 작동시키는 방법을 찾았고 테이블 정의를 너무 엄격하게 만들 필요가 없으며 다른 저장 프로 시저 내에서 재정의해야합니다 (물론 깨질 수 있습니다)!

예, 가짜 변수가있는 OPENQUERY 문을 사용하여 스토어드 프로 시저에서 리턴 된 테이블 정의를 동적으로 작성할 수 있습니다 ( NO RESULT SET 가 동일한 수의 필드를 리턴하고 올바른 데이터가있는 데이터 세트와 동일한 위치에있는 경우).

테이블이 생성되면 하루 종일 임시 테이블에 exec 저장 프로 시저를 사용할 수 있습니다.


(위에 표시된대로) 데이터 액세스를 활성화해야합니다.

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

... 원래 제공 한 정보를 주셔서 감사합니다 예는, 마침내이 모든 가짜 만들 필요가 없습니다 다른 저장 프로 시저 또는 데이터베이스에서 데이터를 사용하는 경우 (엄격한) 테이블되어 정의를, 그리고 당신은 너무 매개 변수를 사용할 수 있습니다.

참조 태그 검색 :

  • 임시 테이블에 SQL 2005 저장 프로 시저

  • 저장 프로 시저 및 변수 2005를 사용한 openquery

  • 변수가있는 openquery

  • 임시 테이블로 저장 프로 시저 실행

업데이트 : 임시 테이블에서는 작동하지 않으므로 수동으로 임시 테이블을 작성해야했습니다.

Bummer 공지 : 임시 테이블 , 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를 호출 할 때 잠금을 보유중인 경우 호출 된 프로시 저는 잠금에 액세스 할 수 없습니다. 즉, 조심하지 않으면 자신을 차단하게됩니다.

연결은 무료가 아니므로 성능이 저하됩니다.


1
서버 이름을 모르면을 사용하십시오 SELECT @@SERVERNAME. 당신은 또한 사용할 수 있습니다EXEC sp_serveroption @@SERVERNAME, 'DATA ACCESS', TRUE
증권 결제 유예 금

24

운이 좋으면 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

1
우수한! 내장 된 프로 시저에 대해이 작업을 수행하려는 경우 sys.all_objects대신 사용하십시오 sys.procedures.
게르트 아놀드

2
SP가 임시 테이블을 사용하는 경우에도 실패합니다. (그러나 당신의 무기고에서
프록

23

이 저장된 proc은 다음 작업을 수행합니다.

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

이것은 약간의 재 작업입니다 . 실제로 작동하도록 저장 프로 시저 결과를 테이블에 삽입하십시오 .

임시 테이블로 작업하려면 ##GLOBAL테이블 을 사용하고 나중에 삭제해야합니다.


17

저장 프로 시저의 첫 번째 레코드 세트를 임시 테이블에 삽입하려면 다음을 알아야합니다.

  1. 스토어드 프로 시저의 첫 번째 행 세트 만 임시 테이블에 삽입 할 수 있습니다.
  2. 저장 프로시 저는 동적 T-SQL 문 ( sp_executesql)을 실행하지 않아야합니다.
  3. 먼저 임시 테이블의 구조를 정의해야합니다

위의 제한 사항으로 보일 수 있지만 IMHO는 완벽하게 의미가 있습니다. 사용하는 경우 sp_executesql두 개의 열과 한 번의 열을 반환 할 수 있으며 여러 결과 집합이있는 경우 여러 테이블에 삽입 할 수 없습니다-최대를 삽입 할 수 있습니다 하나의 T-SQL 문에있는 두 개의 테이블 ( OUTPUT구문 사용 및 트리거 없음)

따라서 문제는 주로 EXEC ... INTO ...명령문을 수행하기 전에 임시 테이블 구조를 정의하는 방법 입니다.

첫 번째는 작동 OBJECT_ID하지만 두 번째와 세 번째는 임시 쿼리에서도 작동합니다. 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 문이 실행되거나 임시 테이블이 저장 프로 시저에 사용되는 경우 와 같은 일부 경우 위의 개체가 첫 번째 결과 집합 데이터를 정의하지 못합니다 .


제한 사항에 대한 실질적인 관찰 : 다른 sp (SP_LEVEL_1이라고 함)에서 위의 접근 방식을 사용하여 동적으로 생성 된 임시 테이블에 일부 sp (SP_LEVEL_0이라고 함)의 출력을 삽입해야하는 경우이 SP_LEVEL_1의 출력에 대해 동일한 트릭을 수행 할 수 없습니다. SP_LEVEL_2의 다른 임시 테이블
nahab

17
  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

    값 (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

쿼리에 매개 변수가 없으면 OpenQueryelse를 사용하십시오 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

13

암호

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

이게 도움이 되길 바란다. 적절한 자격을 갖추십시오.


11

저장 프로 시저에 배열 / 데이터 테이블 전달을 찾았습니다. 하여 문제 해결 방법에 대한 또 다른 아이디어를 얻을 수 있습니다.

이 링크는 이미지 유형 매개 변수 를 사용 하여 저장 프로 시저에 전달 하도록 제안 합니다. 그런 다음 저장 프로 시저에서 이미지는 원래 데이터를 포함하는 테이블 변수로 변환됩니다.

아마도 이것이 임시 테이블과 함께 사용될 수있는 방법이있을 것입니다.


4
Sql2008 이상 버전에서는 더 이상 필요하지 않으며 Table Value Parameters 가 도입되었습니다 . 이제 위의 링크에서 언급 한 것처럼 바이트로 변환해야하는 .net 데이터 셋 또는 데이터 테이블 객체를 SQL 저장 프로 시저에 직접 전달할 수 있습니다.
EndlessSpace

10

나는 같은 문제를 만났고 여기에 바울의 제안 에서 내가 한 일이 있습니다 . 주요 부분은 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

다른 방법은 유형을 생성하고 PIPELINED를 사용하여 객체를 다시 전달하는 것입니다. 그러나 이것은 열을 아는 것으로 제한됩니다. 그러나 다음과 같은 이점이 있습니다.

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

이게 뭐야? 이 질문에 관한 SQL Server와 관련이없는 것 같습니다
Martin Smith

8

간단한 2 단계 프로세스입니다.-임시 테이블 작성-임시 테이블에 삽입하십시오.

동일하게 수행하는 코드 :

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

공감; 기존 답변과 매우 유사합니다.
iokevins

6

검색 후 특히 데이터베이스 관리자가 아닌 경우 저장 프로 시저 결과 정의의 일반 스키마를 사용 OPENROWSET하거나 OPENQUERY사용 하지 않고 저장 프로 시저에 대해 임시 테이블을 동적으로 작성하는 방법을 찾았습니다 .

SQL Server에는 sp_describe_first_result_set모든 프로 시저 결과 집합의 스키마를 제공 할 수 있는 buit-in proc 이 있습니다. 이 절차의 결과에서 스키마 테이블을 만들고 모든 필드를 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 (빌드 17134 :)

사용중인 SQL Server 버전에 대한 스키마를 조정할 수 있습니다 (필요한 경우).


4

전달되는 매개 변수를 알고 있고 sp_configure를 만들 수있는 액세스 권한이없는 경우 이러한 매개 변수를 사용하여 저장 프로 시저를 편집하면 ## global 테이블에 저장 프로 시저를 저장할 수 있습니다.


3

저장 프로 시저가 하나의 테이블 만 반환하면 SQL Server 2014+에서이 작업을 수행 할 수 있습니다. 누군가가 여러 테이블에 대해이 작업을 수행하는 방법을 찾으면 그것에 대해 알고 싶습니다.

DECLARE @storedProcname NVARCHAR(MAX) = ''
SET @storedProcname = '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(@storedProcname),0)
FOR XML PATH('')
),1,1,'(') + ')'

EXEC (@strSQL)

INSERT INTO myTableName

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

SELECT * FROM myTableName

DROP TABLE myTableName

이것은 시스템 테이블에서 리턴 된 테이블의 정의를 가져 와서이를 사용하여 임시 테이블을 빌드합니다. 그런 다음 앞에서 설명한대로 스토어드 프로 시저에서이를 채울 수 있습니다.

Dynamic SQL에서도 작동하는 변형이 있습니다.


2

몇 년 동안 질문에 늦었지만, 빠르고 더러운 코드 생성을 위해서는 이와 같은 것이 필요했습니다. 다른 사람들이 언급했듯이 임시 테이블을 미리 정의하는 것이 더 쉽지만이 방법은 간단한 저장 프로 시저 쿼리 또는 SQL 문에 작동해야합니다.

이것은 약간 복잡하지만 DBA Stack Exchange의 Paul White 솔루션뿐만 아니라 여기에 기고자로부터 빌려옵니다. 저장 프로 시저 결과 열 유형 가져 오기 . 다시 한번,이 접근법을 반복하는 것은 다중 사용자 환경에서의 프로세스를 위해 설계된 것이 아닙니다. 이 경우 테이블 생성은 코드 생성 템플릿 프로세스에서 참조 할 수 있도록 전역 임시 테이블에서 짧은 시간 동안 설정됩니다.

필자는 이것을 완전히 테스트하지 않았으므로 경고가있을 수 있으므로 Paul White의 답변에서 MSDN 링크로 이동하십시오. 이는 SQL 2012 이상에 적용됩니다.

먼저 Oracle의 describe와 유사한 저장 프로 시저 sp_describe_first_result_set 을 사용하십시오 .

이것은 첫 번째 결과 세트의 첫 번째 행을 평가하므로 스토어드 프로 시저 또는 명령문이 여러 쿼리를 리턴하는 경우 첫 번째 결과 만 설명합니다.

임시 테이블 정의를 만들기 위해 선택할 단일 필드를 반환하는 작업을 분류하기 위해 저장 프로 시저를 만들었습니다.

CREATE OR ALTER PROCEDURE [dbo].[sp_GetTableDefinitionFromSqlBatch_DescribeFirstResultSet]
(
     @sql NVARCHAR(4000)
    ,@table_name VARCHAR(100)
    ,@TableDefinition NVARCHAR(MAX) OUTPUT
)
AS
BEGIN
    SET NOCOUNT ON
    DECLARE @TempTableDefinition NVARCHAR(MAX)
    DECLARE @NewLine NVARCHAR(4) = CHAR(13)+CHAR(10)

    DECLARE @ResultDefinition TABLE (  --The View Definition per MSDN
      is_hidden         bit NOT NULL
    , column_ordinal    int NOT NULL
    , [name]            sysname NULL
    , is_nullable       bit NOT NULL
    , system_type_id    int NOT NULL
    , system_type_name  nvarchar(256) NULL
    , max_length        smallint NOT NULL
    , [precision]       tinyint NOT NULL
    , scale             tinyint NOT 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 NOT NULL            
    , is_case_sensitive         bit NOT NULL            
    , is_fixed_length_clr_type  bit NOT 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_is_descending    smallint NULL   
    , order_by_list_length      smallint NULL
    , tds_type_id               int NOT NULL
    , tds_length                int NOT NULL
    , tds_collation_id          int NULL
    , tds_collation_sort_id     tinyint NULL
    )

    --Insert the description into table variable    
    INSERT @ResultDefinition
    EXEC sp_describe_first_result_set @sql

    --Now Build the string to create the table via union select statement
    ;WITH STMT AS (
        SELECT N'CREATE TABLE ' + @table_name + N' (' AS TextVal
        UNION ALL

        SELECT 
         CONCAT(
                CASE column_ordinal
                    WHEN 1 THEN '     ' ELSE '   , ' END  --Determines if comma should precede
                , QUOTENAME([name]) , '   ', system_type_name  -- Column Name and SQL TYPE
                ,CASE is_nullable 
                    WHEN 0 THEN '   NOT NULL' ELSE '   NULL' END --NULLABLE CONSTRAINT          
               ) AS TextVal
        FROM @ResultDefinition WHERE is_hidden = 0  -- May not be needed
        UNION ALL

        SELECT N');' + @NewLine
    ) 

    --Now Combine the rows to a single String
    SELECT @TempTableDefinition = COALESCE (@TempTableDefinition + @NewLine + TextVal, TextVal) FROM STMT

    SELECT @TableDefinition = @TempTableDefinition
END

수수께끼는 전역 테이블을 사용해야하지만 충돌에 대해 걱정하지 않고 자주 테이블에서 삭제하고 만들 수 있도록 고유하게 만들어야합니다.
이 예에서는 하이픈을 밑줄로 바꾸는 전역 변수에 Guid (FE264BF5_9C32_438F_8462_8A5DC8DEE49E)를 사용했습니다.

DECLARE @sql NVARCHAR(4000) = N'SELECT @@SERVERNAME as ServerName, GETDATE() AS Today;'
DECLARE @GlobalTempTable VARCHAR(100) = N'##FE264BF5_9C32_438F_8462_8A5DC8DEE49E_MyTempTable'

--@sql can be a stored procedure name like dbo.foo without parameters

DECLARE @TableDef NVARCHAR(MAX)

DROP TABLE IF EXISTS #MyTempTable
DROP TABLE IF EXISTS ##FE264BF5_9C32_438F_8462_8A5DC8DEE49E_MyTempTable

EXEC [dbo].[sp_GetTableDefinitionFromSqlBatch_DescribeFirstResultSet] 
    @sql, @GlobalTempTable, @TableDef OUTPUT

--Creates the global table ##FE264BF5_9C32_438F_8462_8A5DC8DEE49E_MyTempTable
EXEC sp_executesql @TableDef 

--Now Call the stored procedure, SQL Statement with Params etc.
INSERT ##FE264BF5_9C32_438F_8462_8A5DC8DEE49E_MyTempTable
    EXEC sp_executesql @sql 

--Select the results into your undefined Temp Table from the Global Table
SELECT * 
INTO #MyTempTable
FROM ##FE264BF5_9C32_438F_8462_8A5DC8DEE49E_MyTempTable

SELECT * FROM #MyTempTable

DROP TABLE IF EXISTS #MyTempTable
DROP TABLE IF EXISTS ##FE264BF5_9C32_438F_8462_8A5DC8DEE49E_MyTempTable

다시 말하지만, 간단한 저장 프로 시저 쿼리와 간단한 쿼리로 테스트했기 때문에 마일리지가 다를 수 있습니다. 이것이 누군가를 돕기를 바랍니다.


1

글쎄, 임시 테이블을 만들어야하지만 올바른 스키마를 가질 필요는 없습니다 .... 기존 임시 테이블을 수정하여 올바른 데이터가있는 필수 열을 갖도록 저장 프로 시저를 만들었습니다. 유형 및 순서 (기존의 모든 열 삭제, 새 열 추가) :

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

동적 SQL이 임시 테이블을 작성하게하는 경우이 프로시 저는 스토어드 프로 시저가 호출되는 연결과 달리 동적 SQL 연결이 소유합니다.

DECLARE @COMMA_SEPARATED_KEYS varchar(MAX);
DROP TABLE IF EXISTS KV;
CREATE TABLE KV (id_person int, mykey varchar(30), myvalue int);
INSERT INTO KV VALUES
(1, 'age', 16),
(1, 'weight', 63),
(1, 'height', 175),
(2, 'age', 26),
(2, 'weight', 83),
(2, 'height', 185);
WITH cte(mykey) AS (
    SELECT DISTINCT mykey FROM KV
) 
SELECT @COMMA_SEPARATED_KEYS=STRING_AGG(mykey,',') FROM cte;
SELECT @COMMA_SEPARATED_KEYS AS keys;

여기에 이미지 설명을 입력하십시오

DECLARE @ExecuteExpression varchar(MAX);

DROP TABLE IF EXISTS #Pivoted;

SET @ExecuteExpression = N'
SELECT * 
INTO #Pivoted
FROM
(
    SELECT
        mykey,
        myvalue,
        id_person
    FROM KV
) AS t
PIVOT(
    MAX(t.myvalue) 
    FOR mykey IN (COMMA_SEPARATED_KEYS)
) AS pivot_table;
';

SET @ExecuteExpression = REPLACE(@ExecuteExpression, 'COMMA_SEPARATED_KEYS', @COMMA_SEPARATED_KEYS);

EXEC(@ExecuteExpression);

SELECT * FROM #Pivoted;

메시지 208, 수준 16, 상태 0 잘못된 개체 이름 '#Pivoted'. #Pivoted는 Dynamic SQL 연결이 소유하고 있기 때문입니다. 마지막 명령

SELECT * FROM #Pivoted

실패합니다.

이 문제에 직면하지 않는 한 가지 방법은 #Pivoted에 대한 모든 참조가 동적 쿼리 자체에서 이루어 지도록하는 것입니다.

DECLARE @COMMA_SEPARATED_KEYS varchar(MAX);
DROP TABLE IF EXISTS KV;
CREATE TABLE KV (id_person int, mykey varchar(30), myvalue int);
INSERT INTO KV VALUES
(1, 'age', 16),
(1, 'weight', 63),
(1, 'height', 175),
(2, 'age', 26),
(2, 'weight', 83),
(2, 'height', 185);
WITH cte(mykey) AS (
    SELECT DISTINCT mykey FROM KV
) 
SELECT @COMMA_SEPARATED_KEYS=STRING_AGG(mykey,',') FROM cte;
SELECT @COMMA_SEPARATED_KEYS AS keys;


DECLARE @ExecuteExpression varchar(MAX);

DROP TABLE IF EXISTS #Pivoted;

SET @ExecuteExpression = N'
SELECT * 
INTO #Pivoted
FROM
(
    SELECT
        mykey,
        myvalue,
        id_person
    FROM KV
) AS t
PIVOT(
    MAX(t.myvalue) 
    FOR mykey IN (COMMA_SEPARATED_KEYS)
) AS pivot_table;
SELECT * FROM #Pivoted;
';

SET @ExecuteExpression = REPLACE(@ExecuteExpression, 'COMMA_SEPARATED_KEYS', @COMMA_SEPARATED_KEYS);

EXEC(@ExecuteExpression);

여기에 이미지 설명을 입력하십시오


-5

나는 다음을 할 것이다

  1. UDF (테이블 값 UDF)를 작성 (SP로 변환)하십시오.

  2. select * into #tmpBusLine from dbo.UDF_getBusinessLineHistory '16 Mar 2009'


2
첫 발걸음을 내딛는 데 방해가 될 수 있습니다. 예를 들어 원래 SP가 임시 테이블을 사용하는 경우. UDF는 임시 테이블을 사용할 수 없습니다.
yucer December
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.