Динамически создавать временную таблицу на основе результатов из SP - PullRequest
2 голосов
/ 13 марта 2009

У меня есть SP, который вызывает другой SP, и набор результатов должен быть отфильтрован только по интересующим меня столбцам.

DECLARE @myTable TABLE
(
  Field1 INT,
  Field2 INT,
  Field3 INT
)

--If someSP returns say 30 params and I need only 3 params, I don't want to declare all 30 in my temp table @myTable

INSERT INTO @myTable
(Field1, Field2, Field3)   
EXEC someSP          --Need to selectively filter recordset from SP
  @InputParam1 = 'test'

Если я не могу сделать это, я бы хотел создать временную таблицу DYNAMICALLY на основе набора результатов из someSP (таким образом, он устраняет проблемы с обслуживанием, когда someSP модифицируется для добавления нового параметра, мне также не нужно изменять этот процесс

Ответы [ 5 ]

2 голосов
/ 30 марта 2009

Краткий ответ: нет, вы не можете этого сделать.

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

Обходной путь должен использовать постоянные таблицы. Например, в вашей базе данных может быть постоянная таблица с именем someSPResults. Всякий раз, когда SomeSP изменяется, чтобы иметь различное количество выходных столбцов, изменяйте формат SomeSPResults как часть развертывания.

Тогда вы можете сделать это:

insert into dbo.someSPresults
exec someSP

Или внутри someSP вы можете вставить результаты непосредственно в таблицу someSPresults как обычную часть выполнения. Вам просто нужно точно определить, какие записи в таблице someSPresults приходили при каждом выполнении someSP, потому что этот хранимый процесс может запускаться несколько раз одновременно, тем самым выкидывая большое количество данных в someSPresults.

1 голос
/ 13 марта 2009

cmsjr заявил: «Переменная таблицы не может быть целью набора результатов из другой хранимой процедуры.»

Я тоже думал, что это правда, но потом я проверил это. Этот код работает как в 2005, так и в 2008 году:

CREATE PROCEDURE someSP (@InputParam1 varchar(100)) AS
SELECT LEN(@InputParam1), DATALENGTH(@InputParam1), @@SPID
GO

DECLARE @myTable TABLE (
    Field1 INT,
    Field2 INT,
    Field3 INT
)

INSERT INTO @myTable (Field1, Field2, Field3)   
EXEC someSP
    @InputParam1 = 'test'

SELECT * FROM @myTable

Я знал, что это будет работать с таблицами #temp, но я думал, что это не будет работать с таблицами @temp.

Это не отвечает на вопрос DotnetDude.

0 голосов
/ 13 марта 2009

Основываясь на комментариях выше, я бы посоветовал вам рассмотреть табличную функцию. Это может быть параметризовано, и вы можете сделать это:

INSERT @foo (col1, col14, col29)
SELECT col1, col14, col29 FROM dbo.ufnTVF (@p1, @p2)

В противном случае, это OPENROWSET как «самое чистое» (я использую это слабо) решение

Или вы изменяете набор результатов вашего сохраненного процесса, чтобы он возвращал нужные вам столбцы. Это подразумевает динамический SQL или множество операторов IF. Который при некоторых обстоятельствах не будет анализироваться правильно (с помощью SET FMTONLY и т. Д.).

Возможно, вы пытаетесь закодировать против стороннего приложения или системных хранимых процедур (у нас нет полной информации), но это кажется грязным и неправильным. SQL Server 2005 имеет огромное количество DMV и каталогов (или каталогов, в зависимости от того, на какой стороне Атлантики вы находитесь), что устраняет необходимость в системных вызовах процедур.

Если вы пытаетесь имитировать некоторые аспекты ОО-дизайна (один процесс, чтобы сделать что-то для каждого), я бы не стал. Если вам нужен запрос, который повторяет 3 столбца из 30, то сделайте это. Это будет работать намного лучше, потому что неиспользуемые таблицы и столбцы будут игнорироваться в плане, на самом деле их не нужно включать.

0 голосов
/ 13 марта 2009

Я мог бы придумать два варианта, но у меня не было времени проверить их: преобразовать SP в пользовательскую функцию и использовать SELECT * FROM {function} INTO {table}, или использовать OPENROWSET:

SELECT *
FROM OPENROWSET('SQLOLEDB',
                'servername';'username';'password',
                'exec dbname.{owner}.yourstoredproc') AS spResult
INTO {tablename}

Оба решения должны создавать таблицу на лету, тогда вы можете просто выбрать из нее.

0 голосов
/ 13 марта 2009

Табличная переменная не может быть целью набора результатов из другой хранимой процедуры, также вы не можете выполнить DDL для табличных переменных после их объявления, они всегда будут иметь то же определение, с которым были объявлены. Темп стол - ваша лучшая ставка.

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