Использование OPENQUERY (хранимая процедура exec) для создания новой временной таблицы завершается ошибкой 11526

на моем компьютере разработки установлена полная версия SQL Server 2012.

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

чтобы проверить, работает ли сантехника, я выпускаю это запрос:

 SELECT * FROM OPENQUERY("FOOSQL2012", 'exec mySchema.myStoredProc')

но я получаю эту ошибку из этого простого запроса выбора test-the-plumbing:

Msg 11526, Уровень 16, состояние 1, процедура sp_describe_first_result_set, строка 1
Не удалось определить метаданные, так как инструкция ' insert #tmp(foo1, foo2, foo3) выберите " O "как foo1, foo2, foo3 в процедуре "myStoredProc" использует временную таблицу.

Если я правильно понимаю ошибку, OPENQUERY зависит от сервер может извлечь типы данных столбца из постоянные определение в базе данных, а временная таблица, созданная в моем сохраненном proc, будучи эфемерной, не имеет постоянного определения. Если это так, то ... --22-->есть ли какой-либо параметр, который говорит OPENQUERY сделать все возможное и попытаться сделать интеллектуальное предположение о типах данных столбца?

вот манекен SP, с которым я тестирую:

create proc testproc
as
begin

create table #test
(id int, name varchar(5) );

insert into #test(id,name)values(1,'xxx');
select * from #test;
--drop table #test;   -- tried dropping and not dropping, same error either way
end

3 ответов


попробуйте это:

SELECT *
FROM OPENQUERY("FOO\SQL2012", 'SET FMTONLY OFF; EXEC mySchema.myStoredProc;') X;

причина этого заключается в том, что при выполнении хранимой процедуры на связанном сервере поставщик сначала пытается определить форму результирующего набора строк. Он делает это, выдавая SET FMTONLY ON; и затем запуск вашего оператора. В хранимой процедуре, которая не использует временные таблицы, это прекрасно работает. Синтаксический анализатор запросов в основном выполняет сухой запуск без фактической выборки всех данных, только метаданных (вроде показа предполагаемого выполнения план.)

проблема в том, что, когда хранимая процедура тут использовать временные таблицы, это не удается, потому что метаданные временной таблицы не существуют: их нельзя собрать с помощью метаанализа, который работает для хранимых процедур, которые не используют временные таблицы. Лечение, таким образом, состоит в том, чтобы вручную SET FMTONLY OFF; в пакете, который выполняет хранимую процедуру.

имейте в виду, что использование этого метода сделает хранимую процедуру бежать в два раза. Первый раз для сбора метаданных (данные отбрасываются), и во второй раз, чтобы фактически вернуть данные. Если вызываемая хранимая процедура является особенно дорогостоящей или имеет побочные эффекты, вам может потребоваться сделать скидку.

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

в ответ на ваше обновление, что SET FMTONLY OFF не работает: можете ли вы реструктурировать свой SP, чтобы не использовать временную таблицу или использовать постоянную таблицу с сеансовой клавишей? Любой из этих вариантов может сделать свою работу. В SQL Server 2012 у вас также есть возможность передавать данные с помощью табличные параметры.

вы могли бы прочитать Ерланд сайт sommarskog по как обмениваться данными между хранимыми процедурами по мере того как оно смогло обеспечить вас с воодушевленностью для пути выполнить ваше цель.


добавляем "WITH RESULT SETS [NONE | UNDEFINED] " до конца вызова EXEC следует исправить эту проблему. http://technet.microsoft.com/en-us/library/ms188332.aspx


если SP гостевого сервера не имеет результирующего набора (запроса select) в начале, связанный сервер не смог проанализировать результирующий набор. я использую следующий вариант:

create procedure test
as

    if 1=2
    select a, b, c from table

    declare @variable varchar(10)
    ----...and rest of your procedure...

    --in the end
    select a, b, c from table