如何在 Oracle PL/SQL 中动态获取 OBJECT 或 ROWTYPE 的值(反射)?

2024-01-19

我正在尝试采用 ROWTYPE、RECORD 或 OBJECT 类型并将其动态转换为单个字符串表示形式。
我想动态地执行此操作。

Update:感谢 Justin Cave 的反馈,对 OBJECT 类型执行此操作现在可以正常工作。

示例数据:

ID | VAL
---------
1  | BOB

期望的输出:

ID=1, VAL=BOB

收到错误:

ORA-06550: line 7, column 25:
PLS-00306: wrong number or types of arguments in call to 'TO_STRING'
ORA-06550: line 7, column 4:
PL/SQL: Statement ignored

到目前为止我所拥有的(尚未循环遍历列。):

CREATE OR REPLACE FUNCTION to_string (
    ip_anydata in out anydata --note the "out" - this is required for the "piecewise"
)
RETURN VARCHAR2
IS
   lv_typecode PLS_INTEGER;
   lv_anytype anytype;
BEGIN
   DBMS_OUTPUT.PUT_LINE('[Expected='||dbms_types.typecode_object||', Actual='||ip_anydata.getType(lv_anytype)||']');
   --Get the typecode, and the ANYTYPE
   lv_typecode := ip_anydata.getType(lv_anytype);

   --Check that it's really an object
   IF lv_typecode = dbms_types.typecode_object
   THEN
      --If it is an object, find the first item
      DECLARE
         lv_first_attribute_typecode pls_integer;
         lv_aname          varchar2(32767);
         lv_result         pls_integer;
         lv_varchar        varchar2(32767);
         --Variables we don't really care about, but need for function output
         lv_prec           pls_integer; 
         lv_scale          pls_integer;
         lv_len            pls_integer;
         lv_csid           pls_integer;
         lv_csfrm          pls_integer;
         lv_attr_elt_type  anytype;
      BEGIN
         lv_first_attribute_typecode := lv_anytype.getAttrElemInfo(
            pos            => 1, --First attribute
            prec           => lv_prec,
            scale          => lv_scale,
            len            => lv_len,
            csid           => lv_csid,
            csfrm          => lv_csfrm,
            attr_elt_type  => lv_attr_elt_type,
            aname          => lv_aname
         );

         --Check typecode of attribute
         IF lv_first_attribute_typecode = dbms_types.typecode_varchar2
         THEN
            --Now that we've verified the type, get the actual value.
            ip_anydata.piecewise;
            lv_result := ip_anydata.getVarchar2(c => lv_varchar);

            --DEBUG: Print the attribute name, in case you're curious
            --dbms_output.put_line('lv_aname: '||lv_aname);
            RETURN lv_aname||'='||lv_varchar;
         ELSE
            raise_application_error(-20000, 'Unexpected 1st Attribute Typecode: '||lv_first_attribute_typecode);
         END IF;
      END;
   ELSE
       raise_application_error(-20000, 'Unexpected Typecode: '||lv_typecode);
   END IF;
END;
/

场景#1 - 选择 INTO w/ ROWTYPE:

DECLARE
   lv_cv dual%ROWTYPE;
   lv_str VARCHAR2(32767);
BEGIN
   DBMS_OUTPUT.PUT_LINE('-----------------------------');
   SELECT * INTO lv_cv FROM dual WHERE ROWNUM <= 1;
   DBMS_OUTPUT.PUT_LINE(to_string(lv_cv));
END;
/

场景#2 - 使用游标 ROWTYPE 进行 FETCH INTO:

DECLARE
   CURSOR cv_cur IS SELECT * FROM dual WHERE ROWNUM <= 1;
   lv_cv cv_cur%ROWTYPE;
   lv_str VARCHAR2(32767);
BEGIN
   DBMS_OUTPUT.PUT_LINE('-----------------------------');
   OPEN cv_cur;
   FETCH cv_cur INTO lv_cv;
   CLOSE cv_cur;
   DBMS_OUTPUT.PUT_LINE(to_string(lv_cv));
END;
/

场景#3 - 常规对象: (更新)

DECLARE
   lv_cv T_CODE_VAL_REC := T_CODE_VAL_REC('BOB', 5);
   lv_str VARCHAR2(32767);
   lv_any ANYDATA;
BEGIN
   DBMS_OUTPUT.PUT_LINE('-----------------------------');
   lv_any := sys.anydata.ConvertObject(lv_cv);
   DBMS_OUTPUT.PUT_LINE(to_string(lv_any));
EXCEPTION WHEN OTHERS THEN
   pts2_test_valitation_util.fail(999, CHR(10)||CHR(10)||'Unexpected Error:'||CHR(10)||SQLERRM||CHR(10)||DBMS_UTILITY.FORMAT_ERROR_BACKTRACE);
END;
/

None

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Oracle PL/SQL 中动态获取 OBJECT 或 ROWTYPE 的值(反射)? 的相关文章

  • 在Oracle中,是否可以将以逗号分隔的非常大的字符串(clob)转换为具有更好性能的表

    我需要通过逗号分隔符将非常大的 clob 字符串转换为表 下面的函数需要很长时间 有没有返回表的快速函数 create or replace FUNCTION UDF STRSPLIT2 P STR IN CLOB P DELIM IN V
  • Oracle PL/SQL - NO_DATA_FOUND 异常是否对存储过程性能不利?

    我正在编写一个需要进行大量调节的存储过程 根据 C NET 编码中的常识 异常会损害性能 因此我也始终避免在 PL SQL 中使用它们 我在此存储过程中的调节主要围绕记录是否存在 我可以通过以下两种方式之一进行 SELECT COUNT I
  • PL/SQL 触发器问题

    我正在尝试编写一个触发器来填充包含员工更新工资信息的表 我现在遇到一个无法解决的问题 这是要填充的表 drop table SalUpdates cascade constraints create table SalUpdates Sal
  • 无效号码错误!似乎无法绕过它

    Oracle 10g 数据库 我有一张桌子叫s contact 这个表有一个字段叫做person uid This person uid字段是 varchar2 但包含某些行的有效数字和其他行的无效数字 例如 一行可能有一个person u
  • 为什么Mysql的Group By和Oracle的Group by行为不同

    为什么Mysql的Group By和Oracle的Group by行为不同 我多次发现 Mysql group By 功能和 Oracle 的 GroupBy 功能表现不同 很多时候我在Oracle中发现错误 这实际上是错误的查询 但是My
  • Oracle使用with子句创建表

    我可以从使用形成的查询创建表吗with clause Sure CREATE TABLE t AS WITH some data AS SELECT 1 as some value FROM dual UNION ALL SELECT 2
  • 如何获取Oracle中命名事务的名称?

    我想在触发器中使用事务的名称 以便将其写入列中 我尝试了这个 在 SQL Developer 中 set transaction name hello select DBMS TRANSACTION LOCAL TRANSACTION ID
  • 哪一个代表null? undef 或空字符串

    我想插入null在表的一列中 哪一个代表null undef或空字符串 应该使用哪一种 为什么 我知道关于defined我可以检查一下 但我更多的是从数据库的角度来看 代表哪一个null更合适吗 Update 我在用DBI module D
  • 通过一个表中的列更新另一表中的列

    我有两张桌子 A 和 B 两者都有一个共同的列 name 并通过列 id 相互链接 表A中的 name 列是空的 而表B中有数据 我的任务是用相应的id填充从表B到表A的该列中的所有数据 我正在使用以下查询 UPDATE A SET A n
  • (PLSQL) 在 Oracle 更新触发器中测试更改值的最简单表达式是什么?

    这是一个可以解决问题的布尔表达式 nvl new location old location new location is null old location is null 但我想有一个更简单的表达方式 有任何想法吗 这些较短的方法都有
  • Oracle中如何转义单引号? [复制]

    这个问题在这里已经有答案了 我有一列包含某些存储为文本字符串的表达式 其中包括单个引号 例如 错过的交易 包括引号 发生这种情况时如何使用 where 子句 select from table where reason missed tra
  • Oracle - 仅当不存在时才创建索引

    有没有什么方法可以在oracle中创建索引 只有当它们不存在时 就像是 CREATE INDEX IF NOT EXISTS ord customer ix ON orders customer id 仅当索引不存在时添加索引 declar
  • 想要从字符格式转换为带小数的数字格式

    想要将字符格式 00001000000 转换为10000 00 请帮我 我已经尝试过 select to number 00012300 9999999999 99 nls numeric characters from dual 这个脚本
  • 将游标中的数据合并为一个

    我有一个存储过程 它多次执行另一个存储过程 我需要联合并返回数据 这是在执行第二个过程后得到的 我可以以某种方式将多个游标中的数据合并到另一个游标中吗 没有临时表或类表数据类型是否可能 编辑 联合的游标计数实际上是 n 其中 n 是 1 2
  • 如何从 Oracle 中的 select 语句调用带有 Rowtype 参数的函数

    我有一个 oracle 函数 它有一个 in 参数 它是表的行类型 我需要从 select 语句将当前行传递给这个函数 以便它进行一些处理并返回一个值 是否有一个伪变量可以在 select 语句的上下文中使用 相当于触发器中的旧的和新的 我
  • 在 Oracle 中创建数据库链接时出错

    我有两个数据库 需要编写跨数据库查询 所以我试图创建一个数据库链接 CREATE PUBLIC DATABASE LINK DBLink CONNECT TO SchemaName IDENTIFIED BY 123 using DBNam
  • Oracle Many OR 与 IN () 的 SQL 性能调优 [重复]

    这个问题在这里已经有答案了 我手头没有 解释计划 您能帮忙判断以下哪一个更有效吗 选项1 select from VIEW ABC where STRING COL AA OR STRING COL BB OR STRING COL BB
  • 用C++连接oracle数据库

    我正在寻找一种方法来连接到远程 Oracle 数据库并从 C 控制台应用程序中的表中读取一些数据 有人可以给我一些提示吗 谢谢 soci http soci sourceforge net http soci sourceforge net
  • 在 C# 中多次使用单个参数的更好方法

    我刚开始使用准备好的语句从数据库查询数据 并且在实现 C 参数 特别是 OracleParameters 时遇到问题 假设我有以下 SQL string sql select from table1 t1 table2 t2 where t
  • 如何使用 Hibernate Session.doWork(...) 进行保存点/嵌套事务?

    我正在使用 JavaEE JPA 托管事务与 Oracle DB 和 Hibernate 并且需要实现某种嵌套事务 据我所知 此类事情不受开箱即用的支持 但我应该能够为此目的使用保存点 正如建议的https stackoverflow co

随机推荐