Вставьте результаты хранимой процедуры во временную таблицу - PullRequest
1468 голосов
/ 17 марта 2009

Как мне сделать SELECT * INTO [temp table] FROM [stored procedure]? Не FROM [Table] и без определения [temp table]?

Select все данные из BusinessLine в tmpBusLine работают нормально.

select *
into tmpBusLine
from BusinessLine

Я пытаюсь сделать то же самое, но использование stored procedure, которое возвращает данные, не совсем то же самое.

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

Выходное сообщение:

Сообщение 156, Уровень 15, Состояние 1, Строка 2 Неверный синтаксис рядом с ключевым словом 'Exec'.

Я прочитал несколько примеров создания временной таблицы с той же структурой, что и для хранимой процедуры вывода, которая работает нормально, но было бы неплохо не указывать столбцы.

Ответы [ 27 ]

671 голосов
/ 04 августа 2009

Для этого вы можете использовать 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
561 голосов
/ 17 марта 2009

Если вы хотите сделать это без предварительного объявления временной таблицы, вы можете попробовать создать пользовательскую функцию, а не хранимую процедуру , и заставить эту пользовательскую функцию возвращать таблицу. В качестве альтернативы, если вы хотите использовать хранимую процедуру, попробуйте что-то вроде этого:

CREATE TABLE #tmpBus
(
   COL1 INT,
   COL2 INT
)

INSERT INTO #tmpBus
Exec SpGetRecords 'Params'
280 голосов
/ 17 марта 2009

В SQL Server 2005 вы можете использовать INSERT INTO ... EXEC, чтобы вставить результат хранимой процедуры в таблицу. Из документации MSDN INSERT (фактически для SQL Server 2000):

--INSERT...EXECUTE procedure example
INSERT author_sales EXECUTE get_author_sales
183 голосов
/ 04 августа 2009

Это ответ на слегка измененную версию вашего вопроса. Если вы можете отказаться от использования хранимой процедуры для пользовательской функции, вы можете использовать встроенную табличную пользовательскую функцию. По сути, это хранимая процедура (будет принимать параметры), которая возвращает таблицу как набор результатов; и, следовательно, будет хорошо с заявлением INTO.

Вот хорошая быстрая статья о ней и других пользовательских функциях. Если у вас все еще есть потребность в хранимой процедуре, вы можете заключить встроенную табличную пользовательскую функцию в хранимую процедуру. Хранимая процедура просто передает параметры, когда она вызывает select * из встроенной пользовательской функции с табличным значением.

Так, например, у вас есть встроенная пользовательская функция с табличным значением для получения списка клиентов для определенного региона:

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

Затем вы можете вызвать эту функцию, чтобы получить, что ваши результаты такие:

SELECT * FROM CustomersbyRegion(1)

Или сделать ВЫБОР В:

SELECT * INTO CustList FROM CustomersbyRegion(1)

Если вам все еще нужна хранимая процедура, оберните функцию следующим образом:

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

Я думаю, что это самый «бесполезный» метод для получения желаемых результатов. Он использует существующие функции, так как они предназначены для использования без дополнительных сложностей. Вложив встроенную пользовательскую функцию с табличным значением в хранимую процедуру, вы получаете доступ к этой функции двумя способами. Плюс! У вас есть только одна точка обслуживания для реального кода SQL.

Было предложено использовать OPENROWSET, но это не то, для чего предназначалась функция OPENROWSET (из Books Online):

Включает всю информацию о подключении что требуется для доступа к удаленным данным из источника данных OLE DB. это метод является альтернативой доступа таблицы в связанном сервере и является одноразовый, специальный метод подключения и доступ к удаленным данным с помощью OLE DB. Для более частых ссылок на Источники данных OLE DB, используйте связанные вместо серверов.

Использование OPENROWSET выполнит работу, но потребует дополнительных затрат для открытия локальных соединений и сортировки данных. Это также может быть не вариант во всех случаях, поскольку требует специального разрешения запроса, которое представляет угрозу безопасности и, следовательно, может быть нежелательным. Кроме того, подход OPENROWSET исключает использование хранимых процедур, возвращающих более одного набора результатов. Этого можно достичь, заключив в одну хранимую процедуру несколько встроенных пользовательских функций табличного значения.

121 голосов
/ 17 марта 2009
EXEC sp_serveroption 'YOURSERVERNAME', 'DATA ACCESS', TRUE

SELECT  *
INTO    #tmpTable
FROM    OPENQUERY(YOURSERVERNAME, 'EXEC db.schema.sproc 1')
115 голосов
/ 13 марта 2015

Самое простое решение:

CREATE TABLE #temp (...);

INSERT INTO #temp
EXEC [sproc];

Если вы не знаете схему, вы можете сделать следующее. Пожалуйста, обратите внимание, что в этом методе существуют серьезные угрозы безопасности.

SELECT * 
INTO #temp
FROM OPENROWSET('SQLNCLI', 
                'Server=localhost;Trusted_Connection=yes;', 
                'EXEC [db].[schema].[sproc]')
96 голосов
/ 17 марта 2009

Когда хранимая процедура возвращает много столбцов, и вы не хотите вручную «создавать» временную таблицу для хранения результата, я обнаружил, что самый простой способ - перейти в хранимую процедуру и добавить «в» предложение в последнем операторе select и добавьте 1 = 0 к предложению where.

Запустите хранимую процедуру один раз, вернитесь и удалите только что добавленный код SQL. Теперь у вас будет пустая таблица, соответствующая результату хранимой процедуры. Вы можете либо «сценарий таблицы как создать» для временной таблицы, либо просто вставить непосредственно в эту таблицу.

63 голосов
/ 24 марта 2011
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;
45 голосов
/ 06 августа 2009

Ваша хранимая процедура только получает данные или изменяет их тоже? Если он используется только для извлечения, вы можете преобразовать хранимую процедуру в функцию и использовать выражения общих таблиц (CTE), не объявляя ее следующим образом:

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)
45 голосов
/ 31 июля 2012

Если таблица результатов вашего хранимого процесса слишком сложна, чтобы вручную ввести оператор «создать таблицу», и вы не можете использовать OPENQUERY или OPENROWSET, вы можете использовать sp_help для генерации списка столбцов и типов данных для вы. Если у вас есть список столбцов, вам нужно просто отформатировать его в соответствии с вашими потребностями.

Шаг 1. Добавьте «в #temp» к выходному запросу (например, «выберите [...] в #temp из [...]»).

Самый простой способ - это напрямую редактировать выходной запрос в процедуре. Если вы не можете изменить сохраненный процесс, вы можете скопировать содержимое в новое окно запроса и изменить его там.

Шаг 2: Запустите sp_help для временной таблицы. (например, "exec tempdb..sp_help #temp")

После создания временной таблицы выполните sp_help для временной таблицы, чтобы получить список столбцов и типов данных, включая размер полей varchar.

Шаг 3: Скопировать столбцы и типы данных в оператор создания таблицы

У меня есть лист Excel, который я использую для форматирования вывода sp_help в оператор «создать таблицу». Вам не нужно ничего такого, что нужно, просто скопируйте и вставьте в свой редактор 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, это предотвращает ручные ошибки, такие как опечатки и несоответствия типов данных в больших процессах. Отладка опечатки может занять больше времени, чем написание запроса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...