CTE в курсоре выдает ошибку "Соединение занято результатами для другой команды", а производная таблица - нет.

Недавно я столкнулся с ошибкой при извлечении из курсора запроса, который использовал CTE.

"[Microsoft] [родной клиент SQL Server 10.0] Соединение разорвано с результатами для другой команды"

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

Мне удалось устранить ошибку, заменив CTE производной таблицей.

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

Исходный запрос был относительно сложным, включал несколько объединений, но в основном сводился к следующему:

WITH cteResults AS (
    SELECT Account.Id AS AccountId
    FROM Accounts AS Account
    WHERE Account.Number = '12345'
    UNION
    SELECT SubAccount.Id
    FROM SubAccounts AS SubAccount
    WHERE SubAccount.Number = '12345')

SELECT
    Invoice.Value AS InvoiceValue,
    CASE
        WHEN Representative.Sequence IS NOT NULL THEN THEN Representative.Name
        ELSE Account.OwnerName
    END AS InvoiceName
FROM cteResults
INNER JOIN Invoices AS Invoice ON
    Invoice.AccountId = cteResults.AccountId
LEFT OUTER JOIN Accounts AS Account ON
    Account.Id = Invoice.AccountId
LEFT OUTER JOIN AccountRepresentatives AS Representative ON
    Representative.Id = Invoices.AccountRepresentativeId

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

FOREACH InvoicesCursor INTO InvoiceResults.*
    OPEN FormattingRulesCursor
    FETCH FormattingRulesCursor into FormattingRules.*
    // Error appears here
    CLOSE FormattingRulesCursor
END FOREACH

Любой курсор, который открывается из приложения во время оператора FOREACH, завершается с ошибкой, о которой я упоминал выше.

Однако, если я отбрасываю CTE и использую производную таблицу, я не получаю сообщение об ошибке, и все работает правильно.

SELECT
    Invoice.Value AS InvoiceValue,
    CASE
        WHEN Representative.Sequence IS NOT NULL THEN THEN Representative.Name
        ELSE Account.OwnerName
    END AS InvoiceName
FROM (SELECT Account.Id AS AccountId
    FROM Accounts AS Account
    WHERE Account.Number = '12345'
    UNION
    SELECT SubAccount.Id
    FROM SubAccounts AS SubAccount
    WHERE SubAccount.Number = '12345') AS cteResults
INNER JOIN Invoices AS Invoice ON
    Invoice.AccountId = cteResults.AccountId
LEFT OUTER JOIN Accounts AS Account ON
    Account.Id = Invoice.AccountId
LEFT OUTER JOIN AccountRepresentatives AS Representative ON
    Representative.Id = Invoices.AccountRepresentativeId

0 ответов

Другие вопросы по тегам