TSQL: определить количество столбцов, возвращаемых хранимой процедурой

Вероятно, этот вопрос уже задавался ранее, но я не смог найти удовлетворительного ответа.

Мне нужно вставить результаты хранимой процедуры во временную таблицу, например:

INSERT INTO #TEMP EXEC MY_SP

Я не знаю заранее, сколько столбцов вернет SP, поэтому мне нужно подготовить таблицу #TEMP (с помощью динамических команд ALTER .. ADD), чтобы добавить столбцы, соответствующие набору результатов SP.

Предположение: SP не принимает никаких параметров, а количество столбцов всегда одинаково. Но как мне определить это число в чистом TSQL вне SP, чтобы я мог сохранить его, например, в переменной?


person Yuriy Galanter    schedule 23.07.2012    source источник
comment
Ваша жизнь была бы проще, если бы вы делали это против функции, а не SP   -  person Neil    schedule 29.07.2012
comment
К сожалению, я не контролирую это   -  person Yuriy Galanter    schedule 30.07.2012
comment
Если вы можете создать базу данных рядом с заблокированной БД (я не знаю, под какими ограничениями вы находитесь), вы можете кэшировать там некоторую информацию или что-то там делать. Грубое решение кажется таким плохим.   -  person Neil    schedule 30.07.2012


Ответы (4)


Жесткий, особенно если кто-то другой отказывает вам в необходимых разрешениях для запуска, например. ОТКРЫТЫЙ РЯД.

Рассматривали ли вы распаковку/скрипт SP и добавление его содержимого непосредственно в ваш T-SQL? Таким образом, вы можете изменять и адаптировать его по своему усмотрению.

В противном случае, если бы вы могли объяснить больше о SP:

  • Чем занимается СП?
  • Какую информацию он выводит? Один-N столбцов, - сколько строк?
  • Это медленно/быстро? (Можем ли мы, возможно, использовать подход грубой силы [try-catch])?
  • Как он определяет столбцы для вывода и как часто они меняются?
  • Можете ли вы предварительно определить столбцы каким-либо образом? (Так что вы можете использовать синтаксис INSERT #temp EXEC sp_getData).

Удачи!

person Fredrik Johansson    schedule 26.07.2012
comment
Я реализовал решение try catch в качестве примера решения, прежде чем прочитал, что вы его предложили - удалю его, если хотите. - person Neil; 30.07.2012
comment
Спасибо. Я считаю, что грубая сила в этом случае - единственный выход. - person Yuriy Galanter; 30.07.2012

Это немного неудобно, но вы можете сделать что-то вроде:

SELECT * INTO #temp 
FROM OPENROWSET('SQLOLEDB','Data Source=MyServer;Trusted_Connection=yes;Integrated Security=SSPI', 'EXECUTE MyDB.MySchema.MyProcedure @MyParm=123')

У меня есть запросил синтаксис EXECUTE INTO, такой как SELECT INTO, чтобы избежать необходимости заранее знать форму сохраненного вывода процедуры, но он был отклонен

person GilM    schedule 23.07.2012
comment
Спасибо за быстрый ответ, но я боюсь, что это не сработает для нас. OPENROWSET требует повышенных разрешений, которые будут недоступны. - person Yuriy Galanter; 23.07.2012

Позвольте мне с самого начала сказать, что если бы мне пришлось это сделать, я бы попытался найти способ сделать это вне среды SQL или что-то еще, потому что решение, которое я предлагаю, не является хорошим способом сделать это, но оно работает. Так что я не говорю, что это хорошая идея. У меня есть sp под названием test:

CREATE PROCEDURE Test
AS
SELECT 1 as One, 2 as Two

Чтобы выполнить это динамически, я делаю следующее:

DECLARE @i int
SET @i = 1;
DECLARE @SUCESS bit 
SET @SUCESS = 0
WHILE(@SUCESS = 0)
BEGIN 
  DECLARE @proc VARCHAR(MAX)
  DECLARE @count int
  SET @count = 1
  SET @proc = 'DECLARE @t TABLE ( c1 varchar(max) '
  WHILE @count < @i 
  BEGIN 
    SET @proc = @proc + ', c' + CONVERT(varchar, @count + 1) + ' varchar(max) '
    print @proc 
    SET @count = @count + 1
  END
  SET @proc = @proc + '); INSERT INTO @t EXEC Test'
  BEGIN TRY
    EXEC(@proc);
    SET @SUCESS = 1
  END TRY
  BEGIN CATCH
    SET @i = @i+1
  END CATCH

END

SET @proc = @proc + '; SELECT * into ##t FROM @t '
EXEC( @proc )

SELECT * from ##t

Это плохое решение вашей проблемы, потому что вы потеряли тип данных ваших столбцов, их имена и т. д.

person Neil    schedule 28.07.2012
comment
Это также очень хрупкое решение — в идеале вы бы не поймали все в улове — только конкретную ошибку. - person Neil; 29.07.2012

Я не понимаю синтаксис, и это, вероятно, не лучший способ, но кто-то, похоже, сделал это с преобразованием в xml и его разбором: Результаты динамического запроса во временную таблицу или табличную переменную

person Mafu Josh    schedule 28.07.2012