Решение после 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