Доступ к наборам результатов из хранимых процедур Transact-SQL SQL Server - PullRequest
36 голосов
/ 12 сентября 2008

Я использую SQL Server 2005, и я хотел бы знать, как получить доступ к различным наборам результатов из Transact-SQL. Следующая хранимая процедура возвращает два набора результатов, как мне получить к ним доступ, например, из другой хранимой процедуры?

CREATE PROCEDURE getOrder (@orderId as numeric) AS
BEGIN   
    select order_address, order_number from order_table where order_id = @orderId
    select item, number_of_items, cost from order_line where order_id = @orderId
END

Мне нужно иметь возможность перебирать оба набора результатов по отдельности.

РЕДАКТИРОВАТЬ: просто чтобы прояснить вопрос, я хочу проверить хранимые процедуры. У меня есть набор хранимых процедур, которые используются от клиента VB.NET, которые возвращают несколько наборов результатов. Они не будут заменены на табличные функции, на самом деле я не могу изменить процедуры вообще. Изменение процедуры не вариант.

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

Ответы [ 7 ]

34 голосов
/ 12 сентября 2008

Короткий ответ: вы не можете этого сделать.

Из T-SQL невозможно получить доступ к нескольким результатам вызова вложенной хранимой процедуры без изменения хранимой процедуры, как предлагали другие.

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

INSERT INTO #Table (...columns...)
EXEC MySproc ...parameters...

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

8 голосов
/ 19 мая 2009

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

Видите ли, новый SqlDataAdapter будет. По умолчанию заполнить sproc с несколькими результирующими наборами в набор данных из нескольких таблиц. Данные в этих таблицах, в свою очередь, могут быть вставлены в таблицы #Temp в вызывающем sproc, который вы хотите записать. dataset.ReadXmlSchema покажет вам схему каждого набора результатов.

Шаг 1: Начните писать sproc, который будет считывать данные из набора с несколькими наборами результатов

а. Создайте отдельную таблицу для каждого набора результатов в соответствии со схемой.

CREATE PROCEDURE [dbo].[usp_SF_Read] AS
SET NOCOUNT ON;
CREATE TABLE #Table01 (Document_ID VARCHAR(100)
  , Document_status_definition_uid INT
  , Document_status_Code VARCHAR(100) 
  , Attachment_count INT
  , PRIMARY KEY (Document_ID));

б. На этом этапе вам может потребоваться объявить курсор для повторного вызова sproc CLR, который вы создадите здесь:

Шаг 2: Сделать CLR Sproc

Partial Public Class StoredProcedures
    <Microsoft.SqlServer.Server.SqlProcedure()> _
    Public Shared Sub usp_SF_ReadSFIntoTables()

    End Sub
End Class

а. Подключите используя New SqlConnection("context connection=true").

б. Настройте объект команды (cmd) для хранения sproc с несколькими наборами результатов.

с. Получить все данные, используя следующее:

    Dim dataset As DataSet = New DataSet
    With New SqlDataAdapter(cmd)
        .Fill(dataset) ' get all the data.
    End With
'you can use dataset.ReadXmlSchema at this point...
* * Д тысячу двадцать восемь. Выполните итерацию по каждой таблице и вставьте каждую строку в соответствующую временную таблицу (которую вы создали на первом шаге выше).

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

Вот и все!

~ Шон, около Сиэтла

5 голосов
/ 24 августа 2011

Есть еще и клудж, который вы можете сделать. Добавьте необязательный параметр N int к вашему sproc. По умолчанию значение от N до -1. Если значение N равно -1, тогда делайте каждый из ваших выборов. В противном случае, выберите Nth и выберите только Nth.

Например,

if (N = -1 or N = 0)
    select ...

if (N = -1 or N = 1)
    select ...

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

4 голосов
/ 16 сентября 2008

Обратите внимание, что есть дополнительное недокументированное ограничение для оператора INSERT INTO ... EXEC: оно не может быть вложенным. То есть хранимый процесс, который вызывает EXEC (или любой, который он вызывает по очереди), не может сам сделать INSERT INTO ... EXEC. Похоже, что существует один блокнот на процесс, который накапливает результат, и если они вложены, вы получите сообщение об ошибке, когда вызывающий объект откроет это, а затем вызываемый пользователь попытается открыть его снова.

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

2 голосов
/ 06 ноября 2008

К сожалению, это невозможно сделать. Проблема, конечно, в том, что нет синтаксиса SQL, который бы позволял это делать. Конечно, это происходит «под капотом», но вы не можете получить эти другие результаты в TSQL, только из приложения через ODBC или что-то еще.

Есть способ обойти это, как и в большинстве вещей. Хитрость заключается в том, чтобы использовать автоматизацию ole в TSQL для создания объекта ADODB, который по очереди открывает каждый набор результатов и записывает результаты в назначенные вами таблицы (или делает все, что вы хотите с наборами результатов). Вы также можете сделать это в DMO, если вам нравится боль.

1 голос
/ 12 сентября 2008

Есть два способа сделать это легко. Либо вставьте результаты в временную таблицу, а затем ссылайтесь на временную таблицу из вашего sproc. Другая альтернатива - поместить результаты в переменную XML, которая используется как переменная OUTPUT.

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

С XML, он может быть интенсивным и медленным.

0 голосов
/ 12 сентября 2008

Вы можете выбрать их во временные таблицы или написать табличные функции для возврата наборов результатов. Спрашиваете, как перебрать наборы результатов?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...