Выберите столбцы из набора результатов хранимой процедуры - PullRequest
416 голосов
/ 16 октября 2008

У меня есть хранимая процедура, которая возвращает 80 столбцов и 300 строк. Я хочу написать выбор, который получает 2 из этих столбцов. Что-то вроде

SELECT col1, col2 FROM EXEC MyStoredProc 'param1', 'param2'

Когда я использовал вышеуказанный синтаксис, я получаю ошибку:

«Неверное имя столбца».

Я знаю, что самым простым решением было бы изменить хранимую процедуру, но я ее не написал и не могу ее изменить.

Есть ли способ сделать то, что я хочу?

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

  • Я пытался использовать WITH SprocResults AS ...., как предложил Марк, но я получил 2 ошибки

    Неверный синтаксис рядом с ключевым словом 'EXEC'.
    Неверный синтаксис рядом с ')'.

  • Я попытался объявить табличную переменную, и я получил следующую ошибку

    Ошибка вставки: имя столбца или количество предоставленных значений не соответствует определению таблицы

  • Если я попытаюсь
    SELECT * FROM EXEC MyStoredProc 'param1', 'param2'
    Я получаю ошибку:

    Неверный синтаксис рядом с ключевым словом "exec".

Ответы [ 16 ]

6 голосов
/ 20 февраля 2016

Я считаю, что для SQL Server это работает нормально:

Создайте временную таблицу (или постоянную таблицу, на самом деле не имеет значения) и вставьте оператор в хранимую процедуру. Результирующий набор SP должен соответствовать столбцам в вашей таблице, в противном случае вы получите ошибку.

Вот пример:

DECLARE @temp TABLE (firstname NVARCHAR(30), lastname nvarchar(50));

INSERT INTO @temp EXEC dbo.GetPersonName @param1,@param2;
-- assumption is that dbo.GetPersonName returns a table with firstname / lastname columns

SELECT * FROM @temp;

Вот и все!

5 голосов
/ 24 февраля 2016

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

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

SELECT * INTO #temp FROM OPENROWSET('SQLNCLI', 'Server=localhost;Trusted_Connection=yes;'
                                   ,'EXEC MyStoredProc')

Если вы получаете какую-либо ошибку, вам нужно включить специальные распределенные запросы, выполнив следующий запрос.

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

Чтобы выполнить sp_configure с обоими параметрами для изменения параметра конфигурации или для выполнения оператора RECONFIGURE, вам необходимо предоставить ALTER SETTINGS разрешение на уровне сервера

Теперь вы можете выбрать ваши конкретные столбцы из сгенерированной таблицы

SELECT col1, col2
FROM #temp
4 голосов
/ 05 января 2010

попробуйте

use mydatabase
create procedure sp_onetwothree as
select 1 as '1', 2 as '2', 3 as '3'
go
SELECT a.[1], a.[2]
FROM OPENROWSET('SQLOLEDB','myserver';'sa';'mysapass',
    'exec mydatabase.dbo.sp_onetwothree') AS a
GO
0 голосов
/ 09 января 2019

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

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

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

DECLARE @spName VARCHAR(MAX) = 'MyStoredProc'
DECLARE @tempTableName VARCHAR(MAX) = '#tempTable'

-- might need to update this if your param value is a string and you need to escape quotes
DECLARE @insertCommand VARCHAR(MAX) = 'INSERT INTO ' + @tempTableName + ' EXEC MyStoredProc @param=value'

DECLARE @createTableCommand VARCHAR(MAX)

-- update this to select the columns you want
DECLARE @selectCommand VARCHAR(MAX) = 'SELECT col1, col2 FROM ' + @tempTableName

DECLARE @dropCommand VARCHAR(MAX) = 'DROP TABLE ' + @tempTableName

-- Generate command to create temp table
SELECT @createTableCommand = 'CREATE TABLE ' + @tempTableName + ' (' +
    STUFF
    (
        (
            SELECT ', ' + CONCAT('[', name, ']', ' ', system_type_name)
            FROM sys.dm_exec_describe_first_result_set_for_object
            (
              OBJECT_ID(@spName), 
              NULL
            )
            FOR XML PATH('')
        )
        ,1
        ,1
        ,''
    ) + ')'

EXEC( @createTableCommand + ' '+ @insertCommand + ' ' + @selectCommand + ' ' + @dropCommand)
0 голосов
/ 17 сентября 2013

Я бы вырезал и вставил оригинальный SP и удалил все столбцы, кроме 2, которые вы хотите. Или же. Я бы вернул набор результатов обратно, сопоставил бы его с соответствующим бизнес-объектом, а затем LINQ из двух столбцов.

0 голосов
/ 23 июля 2013

Самый простой способ сделать это, если вам нужно сделать это только один раз:

Экспорт в Excel в мастере импорта и экспорта, а затем импортирование этого Excel в таблицу.

...