Метаданные, относящиеся к типам записей уровня пакета PL / SQL - PullRequest
6 голосов
/ 10 января 2012

Предположим, у вас есть пакет PL / SQL с определенным типом RECORD:

CREATE OR REPLACE PACKAGE TEST_PACKAGE AS

    TYPE PERSON_RECORD_TYPE IS RECORD
    (
        first_name VARCHAR2(1000),
        last_name  VARCHAR2(1000)
    );

END;

Есть ли способ получить список полей, содержащихся в TEST_PACKAGE.PERSON_RECORD_TYPE?Например, есть ли ALL_* представлений с этой информацией?

Меня не интересуют типы записей схема , только пакет типы записей.

Ответы [ 3 ]

2 голосов
/ 21 июня 2012

Если PERSON_RECORD_TYPE используется в качестве аргумента или типа результата какой-либо процедуры или функции, вы можете запросить ALL_ARGUMENTS.Информация там немного зашифрована (иерархия многоуровневой инкапсуляции записей и коллекций закодирована в столбцах POSITION, SEQUENCE и DATA_LEVEL), но она присутствует.архитектура.Для автоматической генерации кода PLSQL это вполне законный запрос, к сожалению, с очень слабой поддержкой языка PLSQL.

1 голос
/ 11 мая 2017

Решение после Oracle 18c

Я думаю, что это не сработало до 18c (поправьте меня, если я ошибаюсь), но теперь мы можем запросить представление ALL_PLSQL_TYPE_ATTRS:

SELECT type_name, attr_name, attr_type_name, length
FROM all_plsql_type_attrs
WHERE package_name = 'TEST_PACKAGE'
ORDER BY owner, package_name, type_name, attr_no;

Чтобы получить что-то вроде этого:

TYPE_NAME           ATTR_NAME   ATTR_TYPE_NAME  LENGTH
------------------------------------------------------
PERSON_RECORD_TYPE  FIRST_NAME  VARCHAR2        1000
PERSON_RECORD_TYPE  LAST_NAME   VARCHAR2        1000

Решение до Oracle 18c

Генератор кода jOOQ внутренне использует следующий запрос длянадежно найти все типы пакетов PL/SQL RECORD типы:

SELECT
  "x"."TYPE_OWNER",
  "x"."TYPE_NAME",
  "x"."TYPE_SUBNAME","a".subprogram_id,
  "a"."ARGUMENT_NAME" "ATTR_NAME",
  "a"."SEQUENCE" "ATTR_NO",
  "a"."TYPE_OWNER" "ATTR_TYPE_OWNER",
  nvl2("a"."TYPE_SUBNAME", "a"."TYPE_NAME", NULL) "package_name",
  COALESCE("a"."TYPE_SUBNAME", "a"."TYPE_NAME", "a"."DATA_TYPE") "ATTR_TYPE_NAME",
  "a"."DATA_LENGTH" "LENGTH",
  "a"."DATA_PRECISION" "PRECISION",
  "a"."DATA_SCALE" "SCALE"
FROM "SYS"."ALL_ARGUMENTS" "a"
JOIN (
  SELECT
    "a"."TYPE_OWNER",
    "a"."TYPE_NAME",
    "a"."TYPE_SUBNAME",
    MIN("a"."OWNER") KEEP (DENSE_RANK FIRST
      ORDER BY "a"."OWNER" ASC, "a"."PACKAGE_NAME" ASC, 
               "a"."SUBPROGRAM_ID" ASC, "a"."SEQUENCE" ASC) "OWNER",
    MIN("a"."PACKAGE_NAME") KEEP (DENSE_RANK FIRST
      ORDER BY "a"."OWNER" ASC, "a"."PACKAGE_NAME" ASC, 
               "a"."SUBPROGRAM_ID" ASC, "a"."SEQUENCE" ASC) "PACKAGE_NAME",
    MIN("a"."SUBPROGRAM_ID") KEEP (DENSE_RANK FIRST
      ORDER BY "a"."OWNER" ASC, "a"."PACKAGE_NAME" ASC, 
               "a"."SUBPROGRAM_ID" ASC, "a"."SEQUENCE" ASC) "SUBPROGRAM_ID",
    MIN("a"."SEQUENCE") KEEP (DENSE_RANK FIRST
      ORDER BY "a"."OWNER" ASC, "a"."PACKAGE_NAME" ASC, 
               "a"."SUBPROGRAM_ID" ASC, "a"."SEQUENCE" ASC) "SEQUENCE",
    MIN("next_sibling") KEEP (DENSE_RANK FIRST
      ORDER BY "a"."OWNER" ASC, "a"."PACKAGE_NAME" ASC, 
               "a"."SUBPROGRAM_ID" ASC, "a"."SEQUENCE" ASC) "next_sibling",
    MIN("a"."DATA_LEVEL") KEEP (DENSE_RANK FIRST
      ORDER BY "a"."OWNER" ASC, "a"."PACKAGE_NAME" ASC, 
               "a"."SUBPROGRAM_ID" ASC, "a"."SEQUENCE" ASC) "DATA_LEVEL"
  FROM (
    SELECT
      lead("a"."SEQUENCE", 1, 99999999) OVER (
        PARTITION BY "a"."OWNER", "a"."PACKAGE_NAME", 
                     "a"."SUBPROGRAM_ID", "a"."DATA_LEVEL"
        ORDER BY "a"."SEQUENCE" ASC
      ) "next_sibling",
      "a"."TYPE_OWNER",
      "a"."TYPE_NAME",
      "a"."TYPE_SUBNAME",
      "a"."OWNER",
      "a"."PACKAGE_NAME",
      "a"."SUBPROGRAM_ID",
      "a"."SEQUENCE",
      "a"."DATA_LEVEL",
      "a"."DATA_TYPE"
    FROM "SYS"."ALL_ARGUMENTS" "a"
    WHERE "a"."OWNER" IN ('TEST')     -- Possibly replace schema here
    ) "a"
  WHERE ("a"."TYPE_OWNER" IN ('TEST') -- Possibly replace schema here
  AND "a"."OWNER"         IN ('TEST') -- Possibly replace schema here
  AND "a"."DATA_TYPE"      = 'PL/SQL RECORD')
  GROUP BY
    "a"."TYPE_OWNER",
    "a"."TYPE_NAME",
    "a"."TYPE_SUBNAME"
  ) "x"
ON (("a"."OWNER", "a"."PACKAGE_NAME", "a"."SUBPROGRAM_ID")
 = (("x"."OWNER", "x"."PACKAGE_NAME", "x"."SUBPROGRAM_ID"))
AND "a"."SEQUENCE" BETWEEN "x"."SEQUENCE" AND "next_sibling"
AND "a"."DATA_LEVEL" = ("x"."DATA_LEVEL" + 1))
ORDER BY
  "x"."TYPE_OWNER" ASC,
  "x"."TYPE_NAME" ASC,
  "x"."TYPE_SUBNAME" ASC,
  "a"."SEQUENCE" ASC

В вашем случае результат будет примерно таким:

TYPE_NAME     TYPE_SUBNAME        ATTR_NAME   ATTR_TYPE_NAME   LENGTH
----------------------------------------------------------------------
TEST_PACKAGE  PERSON_RECORD_TYPE  FIRST_NAME  VARCHAR2         1000
TEST_PACKAGE  PERSON_RECORD_TYPE  LAST_NAME   VARCHAR2         1000

Текущие ограничения:

  • Запрос найдет только те типы, на которые ссылается хотя бы один другой тип и / или процедура.Это ограничение, унаследованное от словарного представления ALL_ARGUMENTS в запросе.
  • %ROWTYPE типы возвращаются неправильно, поскольку на тип строки не ссылаются из столбцов TYPE_NAME / TYPE_SUBNAME.

Больше информации здесь: https://blog.jooq.org/2016/11/08/use-jooq-to-read-write-oracle-plsql-record-types

1 голос
/ 10 января 2012

Вот несколько похожих вопросов о получении информации из кода пакета.

Поиск глобальных переменных пакета из словаря данных

Получение методов и параметров пакета из Oracle

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

В любом случае, я думаю, что в вашей архитектуре что-то не так, если вам это нужно.

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