Вставка в пользовательский тип таблицы с помощью динамического запроса в SQL Server?

#sql #sql-server #sql-server-2016

Вопрос:

У меня есть пользовательский тип таблицы tyAnalysisNumbers . Мне нужно заполнить свой определенный пользователем тип данных в хранимой процедуре SELECT инструкцией, и я изо всех сил пытаюсь заставить ее работать в моей хранимой процедуре.

Следующие способы, которые я пробовал, не работают

 DECLARE @MyTable tyAnalysisNumbers;

INSERT INTO @MyTable 
    EXEC ('SELECT * FROM '   @someTable);
 

Я получаю эту ошибку:

Инструкция INSERT EXEC не может быть вложенной

Я не уверен, как вставить в свою пользовательскую таблицу с помощью инструкции select.

Может ли кто-нибудь помочь мне в этом?

Комментарии:

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

2. У меня есть две хранимые процедуры, родительская, которая вызывает дочернюю. Дочерний sp, над которым я работаю, использует пользовательскую таблицу, работает как есть, вы правы. Но он должен быть вызван из родительской хранимой процедуры в нашем приложении, в которой запускаются следующие строки: ` ВСТАВИТЬ В @resultsTable выполнить транзакцию фиксации дочернего хранилища ВЫБЕРИТЕ * ИЗ @resultsTable Конец Попробуйте начать Перехватывать, если XACT_STATE() <> 0 ` ` В этот момент ошибки регистрируются в отладочных событиях, и именно там я вижу ошибку An INSERT EXEC statement cannot be nested .

3. Что такое @someTable ? Название постоянной таблицы? Табличная переменная, объявленная ранее в коде? ТВП?

4. @someTable-это имя схемы и таблицы, постоянное, а не временное.

5. Это все, что делает вложенная хранимая процедура? Вставьте выходные данные из какой-либо таблицы в тип таблицы, а затем выберите ее? Зачем беспокоиться о типе таблицы? Если есть другие вещи, которые происходят до окончательного выбора, пожалуйста, включите эту информацию и не скрывайте ее и не заглушайте. Возможно, решение состоит в том, чтобы просто выполнять все в динамической области SQL (или, если набор операций, выполняемых после заполнения типа, велик и/или список @someTable возможностей невелик, могут быть и другие решения).

Ответ №1:

Инструкция INSERT EXEC не может быть вложенной

Приведенная выше ошибка объясняется сама собой. Пожалуйста, посмотрите на приведенный ниже сценарий:

Например, у нас есть одна процедура, которая вставляет данные в тип таблицы и возвращает результат.

 CREATE PROCEDURE uspInsertData1
AS 
BEGIN
    DECLARE @MyTable tyAnalysisNumbers;

    INSERT INTO @MyTable 
    EXEC ('SELECT * FROM someTable');

    select * from @MyTable
END
 

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

 CREATE PROCEDURE uspInsertData2
AS
BEGIN
    DECLARE @MyTable tyAnalysisNumbers;

    INSERT INTO sometable
    EXEC uspInsertData1
END
 

Теперь, если вы выполните 1-ю процедуру, она будет работать нормально, но если вы выполните вторую процедуру, вы получите эту ошибку.

Инструкция INSERT EXEC не может быть вложенной.

Потому что теперь у вас есть вложенные операторы EXEC.

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

Комментарии:

1. Это объясняет проблему операции, но не является решением.

2. @AaronBertrand Согласен.. Но у меня есть и такие сценарии, но я никогда не предпочитаю и не предлагаю называть такие вложенные процедуры. Я всегда избегаю таких вложенных вызовов, чтобы предотвратить такие побочные эффекты. Я предлагаю завершить вашу работу в одной хранимой процедуре.

Ответ №2:

Попробуй вот так:

 DECLARE @MyTable tyAnalysisNumbers;
SELECT * INTO #Temp FROM @MyTable;

DECLARE @tblName AS SYSNAME = (SELECT name FROM sys.tables WHERE name = @someTable);

EXEC ('INSERT INTO #Temp SELECT * FROM '   @tblName);
 

Это также решает проблему внедрения SQL.