Как получить значения OBJECT или ROWTYPE динамически (Reflection) в Oracle PL / SQL?

Я пытаюсь взять тип ROWTYPE, RECORD или OBJECT и динамически преобразовать его в одно строковое представление.
Я хочу сделать это динамически.

Обновить: Делая это для типа 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 с 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 - FETCH INTO с курсором ROWTYPE:

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;
/

Ответы на вопрос(0)

Ваш ответ на вопрос