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

Scr*_*Dev 5 oracle plsql

我正在尝试采用 ROWTYPE、RECORD 或 OBJECT 类型并将其动态转换为单个字符串表示形式。
我想动态地做到这一点。

更新:由于 Justin Cave 的反馈,现在可以为 OBJECT 类型执行此操作。

示例数据:

ID | VAL
---------
1  | BOB
Run Code Online (Sandbox Code Playgroud)

期望输出:

ID=1, VAL=BOB
Run Code Online (Sandbox Code Playgroud)

收到错误:

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
Run Code Online (Sandbox Code Playgroud)

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

ID | VAL
---------
1  | BOB
Run Code Online (Sandbox Code Playgroud)

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

ID=1, VAL=BOB
Run Code Online (Sandbox Code Playgroud)

场景#2 - FETCH INTO w/ Cursor ROWTYPE:

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
Run Code Online (Sandbox Code Playgroud)

场景#3 - 普通对象:( 更新)

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;
/
Run Code Online (Sandbox Code Playgroud)