Как сохранить один набор результатов во временную таблицу из хранимой процедуры SQL, возвращающей несколько наборов? - PullRequest
2 голосов
/ 08 октября 2009

Мне нужно сохранить набор результатов хранимой процедуры во временной таблице (с использованием SQL Server 2000). Из того, что я прочитал, этот (плохо построенный пример) должен работать:

create table #tempTable (TempId int primary key, Column1 varchar(100), 
Column2 varchar(100), DateCreated datetime)

insert into #tempTable (TempId, Column1, Column2, DateCreated)
exec sproc_Select_Stuff_By_DateCreated @Date1 = '1/1/2009', @Date2 = '1/2/2009'

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

Изучение процедуры (которую я не могу отредактировать) показывает следующее:

CREATE PROCEDURE sproc_Select_Stuff_By_DateCreated

@Date1 datetime,
@Date2 datetime
AS

BEGIN

SELECT TempId, Column1, Column2, DateCreated
FROM ReallyHugeMessOfJoinsAndCalculatedColumns
WHERE DateCreated between @Date1 and @Date2

SELECT @Date1 as Date1, @Date2 as Date2

END

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

Мое тестирование заставляет меня думать, что второй набор результатов является причиной сбоя вставки - как SQL пытается объединить наборы результатов вместе и терпит неудачу.

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

Редактировать

Спасибо за указание хранимых процедур CLR, но эта функция была введена в SQL 2005 - она ​​не будет работать в 2000 году. (Но я раньше не знал о них, и они выглядят так, как будто они будут полезны, когда мы обновить.)

Поскольку единственные другие ответы выглядят так: «Вы не можете» - я думаю, что я вернулся к чертежной доске.

Ответы [ 4 ]

2 голосов
/ 08 октября 2009

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

  • используйте CLR, который может захватывать оба набора результатов и возвращать только тот, который вам нужен.
  • продублируйте запрос, который вам нужен, в своей собственной процедуре или представлении. Это настоящий взлом, и CLR является предпочтительным. Однако у вас не так много вариантов.
1 голос
/ 08 октября 2009

Как правило, в простом SQL это невозможно. Ссылка Браннона дает возможный обходной путь, используя CLR.

С другой стороны, если рефакторинг является опцией, подумайте о том, чтобы сделать первый запрос атомарным в своей собственной хранимой процедуре. Затем он может быть вызван как из существующей хранимой процедуры, так и из любого другого кода. Ваш код все еще только в одном месте, ничего не сломано, и вы получаете что-то, что может быть легче использовать из чистого SQL. В зависимости от его функции, первая часть SP может даже быть хорошим кандидатом для встроенной табличной функции (я нашел, что они хорошо работают и гибки). Тогда вам даже не понадобится для захвата вывода во временную таблицу, чтобы использовать его в качестве таблицы при выполнении другой обработки (хотя вам может потребоваться, если вы хотите использовать ее несколько раз)!

0 голосов
/ 08 октября 2009

Из справочника Microsoft T-SQL

INSERT EmployeeSales 
EXECUTE uspGetEmployeeSales;
GO
0 голосов
/ 08 октября 2009

Ниже приведен полный рабочий (для SQL 2005) пример того, о чем вы говорите.

Плохая новость: я не верю, что есть какой-то способ сделать то, что ты пытаешься сделать. Сожалею. Похоже, писатель SP сделал это невозможным.

Если кто-то придумает какой-нибудь творческий способ сделать эту работу, отлично!

IF OBJECT_ID('tempdb..#tempTable') IS NOT NULL
    DROP TABLE #tempTable
GO
IF EXISTS (SELECT * FROM sys.procedures WHERE name = 'sproc_Select_Stuff_By_DateCreated')
    DROP PROCEDURE dbo.sproc_Select_Stuff_By_DateCreated
GO
CREATE PROCEDURE dbo.sproc_Select_Stuff_By_DateCreated
    @Date1 datetime,
    @Date2 datetime
AS BEGIN
    ;WITH t AS (
        SELECT
            1                       AS TempId,
            'Column1-val1'          AS Column1,
            'Column2-val1'          AS Column2,
            '2009-01-01 10:00:00'   AS DateCreated
        UNION ALL
        SELECT
            2,
            'Column1-val2',
            'Column2-val2',
            '2009-01-01 11:00:00'
    )
    SELECT
        TempId,
        Column1,
        Column2,
        DateCreated
    FROM t -- ReallyHugeMessOfJoinsAndCalculatedColumns
    WHERE DateCreated between @Date1 and @Date2

    SELECT @Date1 as Date1, @Date2 as Date2
END
GO

create table #tempTable (
    TempId int primary key,
    Column1 varchar(100),
    Column2 varchar(100),
    DateCreated datetime
)

insert into #tempTable (TempId, Column1, Column2, DateCreated)
exec dbo.sproc_Select_Stuff_By_DateCreated
    @Date1 = '1/1/2009',
    @Date2 = '1/2/2009'

--SELECT * FROM #tempTable

----------------------------------------

Msg 213, Level 16, State 7, Procedure sproc_Select_Stuff_By_DateCreated, Line 26
Insert Error: Column name or number of supplied values does not match table definition.
...