Как я могу превратить выходные данные этой хранимой процедуры, которая использует временную таблицу, в материализованное представление? - PullRequest
0 голосов
/ 21 декабря 2018

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

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

Моя конечная цель - создать структуру данных, которая соответствует требованиям алгоритма Modified Preorder Tree Traversal.

tmp$ временная таблица:

CREATE GLOBAL TEMPORARY TABLE tmp$ 
(
    id   VARCHAR2(8),
    l    INT,
    r    INT
) ON COMMIT DELETE ROWS;

Хранимая процедура:

CREATE OR REPLACE PACKAGE pkg AS
    PROCEDURE p (
        p_id   IN VARCHAR2,
        seq IN OUT INT
    );

END pkg;

CREATE OR REPLACE PACKAGE BODY pkg AS

    PROCEDURE p (
        p_id   IN VARCHAR2,
        seq IN OUT INT
    )
        AS
    BEGIN
        seq := seq + 1;
        INSERT INTO tmp$ (
            id,
            l,
            r
        ) VALUES (
            p_id,
            seq,
            NULL
        );

        FOR i IN (
            SELECT
                id
            FROM
                tab1
            WHERE
                parent_id = p_id
            ORDER BY
                id
        ) LOOP
            p(i.id,seq);
        END LOOP;

        seq := seq + 1;
        UPDATE tmp$
            SET
                r = seq
        WHERE
            id = p_id;

    END;

END pkg;

tab1 данные

+-----+-----------+
| id  | parent_id |
+-----+-----------+
| 01  | null      |
+-----+-----------+
| 100 | 01        |
+-----+-----------+
| 901 | 01        |
+-----+-----------+
| 250 | 01        |
+-----+-----------+
| 400 | 01        |
+-----+-----------+
| 001 | 01        |
+-----+-----------+
| 500 | 01        |
+-----+-----------+
| 600 | 01        |
+-----+-----------+
| 010 | 01        |
+-----+-----------+
| 450 | 01        |
+-----+-----------+

Вызов хранимой процедуры:

VAR n NUMBER

EXEC :n := 0;

EXEC pkg.p('01',:n);

select * from tmp$;

Выполнение pkg.p заполняет таблицу tmp$ следующими данными:

+-----+----+----+
| id  | l  | r  |
+-----+----+----+
| 01  | 1  | 20 |
+-----+----+----+
| 001 | 2  | 3  |
+-----+----+----+
| 010 | 4  | 5  |
+-----+----+----+
| 100 | 6  | 7  |
+-----+----+----+
| 250 | 8  | 9  |
+-----+----+----+
| 400 | 10 | 11 |
+-----+----+----+
| 450 | 12 | 13 |
+-----+----+----+
| 500 | 14 | 15 |
+-----+----+----+
| 600 | 16 | 17 |
+-----+----+----+
| 901 | 18 | 19 |
+-----+----+----+

Если я попытаюсь поместить эти четыре строки выше в предложении CREATE MATERIALIZED VIEW, материализованное представление будет пустым.

Я не уверен, как вообще начать решать это.Стоит ли смотреть на использование таблицы сбора?Я не уверен, как это будет работать, поскольку p работает рекурсивно.

1 Ответ

0 голосов
/ 22 декабря 2018

В своей хранимой процедуре вы создаете модель вложенного набора.

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

Это довольно длительное упражнение для реализации, поэтому вот пример, уже доступный из этой статьи: CTE с несколькими рекурсивными членами Ициком Бен-Ганом

https://www.itprotoday.com/development-techniques-and-management/ctes-multiple-recursive-members

* Обратите внимание, что этот пример написан для SQL Server, но преобразование должно быть тривиальным, поскольку рекурсивные CTE также работают в Oracle.Могут быть некоторые типы данных, которые необходимо изменить для соответствия синтаксису Oracle.

Listing 6: Code to Compute Left and Right Values in the Nested Set Model

WITH EmpsRN AS

(

  SELECT *,

ROW_NUMBER() OVER(PARTITION BY mgrid ORDER BY empname, empid) * 2 - 1 AS n

  FROM dbo.Employees

),

C1 AS

(

  -- root's left arm

  SELECT empid, 1 AS arm, CAST(0x01 AS VARBINARY(8000)) AS sortpath

  FROM dbo.Employees

  WHERE mgrid is NULL


  UNION ALL


  -- root's right arm

  SELECT empid, 2 AS arm, CAST(0x02 AS VARBINARY(8000)) AS sortpath

  FROM dbo.Employees

  WHERE mgrid is NULL


  UNION ALL


  SELECT E.empid, 1 AS arm,

CAST(M.sortpath + CAST(E.n AS BINARY(1)) AS VARBINARY(8000)) AS sortpath

  FROM C1 AS M

INNER JOIN EmpsRN AS E

  ON E.mgrid = M.empid

  WHERE M.arm = 1


  UNION ALL


  SELECT E.empid, 2 AS arm,

 CAST(M.sortpath + CAST(E.n + 1 AS BINARY(1)) AS VARBINARY(8000)) AS sortpath

  FROM C1 AS M

INNER JOIN EmpsRN AS E

  ON E.mgrid = M.empid

  WHERE M.arm = 1

),

c2 AS

(

  SELECT empid, ROW_NUMBER() OVER(ORDER BY sortpath) AS sortval

  FROM C1

)

SELECT empid, MIN(sortval) AS lft, MAX(sortval) AS rgt

FROM c2

GROUP BY empid;
...