Обход иерархии в Azure SQL из изначально скомпилированной хранимой процедуры - PullRequest
0 голосов
/ 19 октября 2018

У меня есть простая самореферентная таблица в памяти

CREATE TABLE [Accounts]
(
  Id UNIQUEIDENTIFIER NOT NULL,
  [ParentAccount_Id] UNIQUEIDENTIFIER NULL, 
  CONSTRAINT [PK_Accounts] PRIMARY KEY NONCLUSTERED ([Id])
)  
WITH  
(
  MEMORY_OPTIMIZED = ON,  
  DURABILITY = SCHEMA_AND_DATA
);

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

Обычно, когда не используются нативно скомпилированные sprocs, я бы использовал тип данных CTE или HIERARCHYID.Однако ни один из них не поддерживается для нативно скомпилированных sprocs.

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

Примеры данных иожидаемые результаты:

|Id                                     |ParentAccounts_Id                     |
|---------------------------------------|--------------------------------------|
|00000000-0000-0000-0000-000000000006   |00000000-0000-0000-0000-000000000002  |
|00000000-0000-0000-0000-000000000005   |00000000-0000-0000-0000-000000000002  |
|00000000-0000-0000-0000-000000000004   |00000000-0000-0000-0000-000000000001  |
|00000000-0000-0000-0000-000000000003   |00000000-0000-0000-0000-000000000001  |
|00000000-0000-0000-0000-000000000002   |00000000-0000-0000-0000-000000000001  |
|00000000-0000-0000-0000-000000000001   |NULL                                  |

Если исходный идентификатор равен 00000000-0000-0000-0000-000000000006, я ожидаю увидеть следующий результат

00000000-0000-0000-0000-000000000006
00000000-0000-0000-0000-000000000002
00000000-0000-0000-0000-000000000001

Ответы [ 2 ]

0 голосов
/ 19 октября 2018

У вас есть два варианта:

1) Создать обычную хранимую процедуру.Обычный (или не скомпилированный код), работающий с таблицами в памяти, называется interop, и нет никакой реальной причины, по которой это не будет быстрым:

DECLARE @id UNIQUEIDENTIFIER = '00000000-0000-0000-0000-000000000006'

;WITH cte AS
(
SELECT 1 xlevel, Id, ParentAccount_Id
FROM dbo.accounts
WHERE Id = @id

UNION ALL

SELECT xlevel + 1, a.Id, a.ParentAccount_Id
FROM cte c
    INNER JOIN dbo.accounts a ON c.ParentAccount_Id = a.Id
)
SELECT Id
FROM cte

Или, 2) реализовать цикл визначально скомпилированная процедура.Если вы посмотрите на этот пример , который я сделал с Fizzbuzz , он молниеносно - менее секунды за 1 миллион циклов.

DROP PROC IF EXISTS dbo.usp_getAccounts
DROP TYPE IF EXISTS dbo.typ_accounts
GO

CREATE TYPE dbo.typ_accounts
AS TABLE
(
    Id                  UNIQUEIDENTIFIER NOT NULL,

    PRIMARY KEY NONCLUSTERED ( Id )
)
WITH ( MEMORY_OPTIMIZED = ON ); 
GO


DROP PROC IF EXISTS dbo.usp_getAccounts
GO
CREATE PROC dbo.usp_getAccounts

    @targetAccountId UNIQUEIDENTIFIER

WITH
    NATIVE_COMPILATION, 
    SCHEMABINDING, 
    EXECUTE AS OWNER
AS
BEGIN ATOMIC
WITH
(
    TRANSACTION ISOLATION LEVEL = SERIALIZABLE, 
    LANGUAGE = N'english'
)   

    DECLARE @t AS dbo.typ_accounts;

    WHILE ( @targetAccountId IS NOT NULL )
    BEGIN

        INSERT INTO @t ( Id )
        SELECT @targetAccountId;

        SELECT @targetAccountId = ParentAccount_Id
        FROM dbo.Accounts
        WHERE Id = @targetAccountId;

    END

    SELECT Id
    FROM @t;

    RETURN;

END
GO


EXEC dbo.usp_getAccounts '00000000-0000-0000-0000-000000000006'

Какие у вас есть тома?Есть ли конкретная причина, по которой вы используете таблицы в памяти?

0 голосов
/ 19 октября 2018

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

DECLARE @targetAccountId UNIQUEIDENTIFIER = '00000000-0000-0000-0000-000000000006'
WHILE (@targetAccountId IS NOT NULL)
BEGIN
    PRINT @targetAccountId

    SELECT @targetAccountId = ParentAccounts_Id
            FROM [im].[Accounts]
            WHERE Id = @targetAccountId
END

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

...