Каково правило области действия для временных таблиц в exec внутри хранимых процедур? - PullRequest
4 голосов
/ 10 мая 2011

Сравните следующие хранимые процедуры:

CREATE PROCEDURE testProc1
AS
    SELECT * INTO #temp FROM information_schema.tables
    SELECT * FROM #temp
GO

CREATE PROCEDURE testProc2
AS
    EXEC('SELECT * INTO #temp FROM information_schema.tables')
    SELECT * FROM #temp
GO

Теперь, если я запускаю testProc1, это работает, и #temp, кажется, существует только на время этого вызова.Однако testProc2, похоже, не работает вообще, поскольку вместо этого я получаю сообщение об ошибке Invalid object name '#temp'.

Почему различие и как я могу использовать временную таблицу для SELECT * INTO, если источникИмя таблицы является параметром хранимой процедуры и может иметь произвольную структуру?

Обратите внимание, что я использую Microsoft SQL Server 2005.

Ответы [ 2 ]

6 голосов
/ 10 мая 2011

От BOL:

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

Различие между вашей первой и второй процедурами состоит в том, что в первой таблице определена та же область, из которой она выбрана; во втором случае EXEC () создает таблицу в своей области видимости, поэтому в этом случае выбор завершается неудачей ...

Однако, обратите внимание, что следующее прекрасно работает:

CREATE PROCEDURE [dbo].[testProc3]
AS
    SELECT * INTO #temp FROM information_schema.tables
    EXEC('SELECT * FROM #temp')
GO

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

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

CREATE PROCEDURE [dbo].[testProc4]
AS
    EXEC('SELECT * INTO #temp FROM information_schema.tables; SELECT * FROM #temp')
GO
0 голосов
/ 11 мая 2011

Вы можете попробовать использовать глобальную временную таблицу (с именем ## temp, а не #temp).Однако следует помнить, что другие соединения также могут видеть эту таблицу.

...