【问题标题】:How can I query for the meta data about a PL/SQL record type如何查询关于 PL/SQL 记录类型的元数据
【发布时间】:2023-03-24 19:01:01
【问题描述】:

如果我有如下记录类型:

create or replace PACKAGE ITEM_MANAGEMENT AUTHID CURRENT_USER
as
    type item IS RECORD (
        id                         NUMBER,
        Description                VARCHAR2(30),
        Category                   VARCHAR2(30)
    );
END ITEM_MANAGEMENT;

从 PL/SQL 我可以声明这种类型的记录变量l_item ITEM_MANAGEMENT.Item;

我希望能够在 Oracle 数据库中查询此记录类型的属性及其类型。

例如,如果我想对一个表执行此操作,我会执行以下操作:

select COLUMN_NAME, DATA_TYPE, DATA_LENGTH
from ALL_TAB_COLUMNS
where 1 = 1
AND OWNER = 'OWNER'
AND TABLE_NAME = 'TABLENAME';

如何查询关于 PL/SQL 记录类型的元数据?

【问题讨论】:

    标签: oracle plsql


    【解决方案1】:

    您似乎在谈论的是一种 PL/SQL 记录类型。仅当编译存储的 PL/SQL 以收集 PLSCOPE 标识符时才可能检查 PL/SQL 记录类型(否则,您的查询将没有数据)。

    我将在这里发布一个这样做的例子。但首先让我说,我从来没有为任何生产代码这样做过。根据我的经验,您尝试做的不是“正常的”,也许您需要重新评估您的方法。不管怎样,就在这里。

    -- First, tell your session that all compilations should collect
    -- PLSCOPE identifiers.  If you neglect to do this, you can always ALTER 
    -- a package later to recompile it with PLSCOPE identifiers as follows:
    --     alter package mypackage compile 
    --         plscope_settings='IDENTIFIERS:ALL' reuse settings;
    ALTER SESSION SET plscope_settings='IDENTIFIERS:ALL';
    
    CREATE OR REPLACE PACKAGE so_test1 AS
    
     TYPE Item IS RECORD (
        id                         NUMBER,
        Description                VARCHAR2(30),
        Category                   VARCHAR2(30)
    );
    
    END so_test1;
    
    
    -- Now, the information you want will be in DBA_IDENTIFIERS, which is 
    -- stored hierarchically.  This query will print that hierarchy, starting
    -- with the definition of your "ITEM" record type.     
    WITH v AS (
      SELECT    Line,
                Col,
                NAME,
                TYPE,
                USAGE,
                USAGE_ID,
                USAGE_CONTEXT_ID
        FROM USER_IDENTIFIERS
          WHERE Object_Name = 'SO_TEST1'
            AND Object_Type = 'PACKAGE'
    )
    SELECT LPAD(' ', 2*(Level-1)) || NAME,
    TYPE, USAGE, USAGE_CONTEXT_ID
      FROM v
      START WITH name = 'ITEM' and type = 'RECORD' and usage = 'DECLARATION'
      CONNECT BY PRIOR USAGE_ID = USAGE_CONTEXT_ID
      ORDER SIBLINGS BY Line, Col
    /
    

    样本输出:

    +---------------+--------------------+-------------+------------------+
    |     NAME      |        TYPE        |    USAGE    | USAGE_CONTEXT_ID |
    +---------------+--------------------+-------------+------------------+
    | ITEM          | RECORD             | DECLARATION |                1 |
    |   ID          | VARIABLE           | DECLARATION |                2 |
    |     NUMBER    | NUMBER DATATYPE    | REFERENCE   |                3 |
    |   DESCRIPTION | VARIABLE           | DECLARATION |                2 |
    |     VARCHAR2  | CHARACTER DATATYPE | REFERENCE   |                5 |
    |   CATEGORY    | VARIABLE           | DECLARATION |                2 |
    |     VARCHAR2  | CHARACTER DATATYPE | REFERENCE   |                7 |
    +---------------+--------------------+-------------+------------------+
    

    【讨论】:

    • 为了解释这一点的用处,尽管这不正常,我正在用另一种语言编写代码,该语言将调用 PL/SQL 代码,而不是对各种记录类型的可用属性进行硬编码给定函数参数最终会变成的 PL/SQL 中的底层记录类型,我想动态生成函数参数。这使我正在编写的代码更加干燥,因为它不是可用属性的真实来源,PL/SQL 中的记录类型才是真实的真实来源。
    • 我并不是要质疑您的具体设计。只是有时,人们从其他平台/语言来到 Oracle,他们试图找到“Oracle 方式”来做他们旧平台上常见的事情。所以,我只是想明确一点,这不是正常的“Oracle 方式”。动态代码在 Oracle 中很难。一般来说,表是有结构的。光标具有结构。使用它们的 PL/SQL 程序期望并依赖于这种结构。这似乎违反了其他语言中的 DRY 原则,但它与 PL/SQL 中的课程相同(恕我直言)。
    猜你喜欢
    • 1970-01-01
    • 2011-12-23
    • 1970-01-01
    • 1970-01-01
    • 2011-05-13
    • 1970-01-01
    • 2010-09-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多