我在 Oracle 中创建了一个对象类型,如下所示:
CREATE OR REPLACE TYPE Generic_MDMU_Scrub_Cols_OBJ as Object
(
i_strTypeOfEntry varchar2(50),
ID_SCRUB number,
NM_DATA_COL1 varchar2(50),
NM_DATA_COL2 varchar2(50),
NM_DATA_COL3 varchar2(50),
NM_DATA_COL4 varchar2(50),
NM_DATA_COL5 varchar2(50),
NM_DATA_COL6 varchar2(50),
NM_DATA_COL7 varchar2(50),
NM_DATA_COL8 varchar2(50),
NM_DATA_COL9 varchar2(50),
NM_DATA_COL10 varchar2(50),
NM_DATA_COL11 varchar2(50),
NM_DATA_COL12 varchar2(50),
NM_DATA_COL13 varchar2(50),
NM_DATA_COL14 varchar2(50),
NM_DATA_COL15 varchar2(50),
NM_DATA_COL16 varchar2(50),
NM_DATA_COL17 varchar2(50),
NM_DATA_COL18 varchar2(50),
NM_DATA_COL19 varchar2(50),
NM_DATA_COL20 varchar2(50),
DATA_VAL1 varchar2(50),
DATA_VAL2 varchar2(50),
DATA_VAL3 varchar2(50),
DATA_VAL4 varchar2(50),
DATA_VAL5 varchar2(50),
DATA_VAL6 varchar2(50),
DATA_VAL7 varchar2(50),
DATA_VAL8 varchar2(50),
DATA_VAL9 varchar2(50),
DATA_VAL10 varchar2(50),
DATA_VAL11 varchar2(50),
DATA_VAL12 varchar2(50),
DATA_VAL13 varchar2(50),
DATA_VAL14 varchar2(50),
DATA_VAL15 varchar2(50),
DATA_VAL16 varchar2(50),
DATA_VAL17 varchar2(50),
DATA_VAL18 varchar2(50),
DATA_VAL19 varchar2(50),
DATA_VAL20 varchar2(50),
OLD_DATA_VAL1 varchar2(50),
OLD_DATA_VAL2 varchar2(50),
OLD_DATA_VAL3 varchar2(50),
OLD_DATA_VAL4 varchar2(50),
OLD_DATA_VAL5 varchar2(50),
OLD_DATA_VAL6 varchar2(50),
OLD_DATA_VAL7 varchar2(50),
OLD_DATA_VAL8 varchar2(50),
OLD_DATA_VAL9 varchar2(50),
OLD_DATA_VAL10 varchar2(50),
OLD_DATA_VAL11 varchar2(50),
OLD_DATA_VAL12 varchar2(50),
OLD_DATA_VAL13 varchar2(50),
OLD_DATA_VAL14 varchar2(50),
OLD_DATA_VAL15 varchar2(50),
OLD_DATA_VAL16 varchar2(50),
OLD_DATA_VAL17 varchar2(50),
OLD_DATA_VAL18 varchar2(50),
OLD_DATA_VAL19 varchar2(50),
OLD_DATA_VAL20 varchar2(50)
);
/
现在我想编写一个过程,它将此对象类型作为输出参数返回给调用 Java 代码。基本上有几个表存储列,类似OLD_DATA_VAL1...OLD_DATA_VAL20
地DATA_VAL1...DATA_VAL120
,另一个表具有列NM_DATA_COL1...NM_DATA_COL20
,并且取决于各种用例,只有 3 或 5 个或任意数量的列将具有值,而其他列将为空。例如OLD_DATA_VAL1,OLD_DATA_VAL2,OLD_DATA_VAL3,DATA_VAL1,DATA_VAL2,DATA_VAL3,NM_DATA_COL1,NM_DATA_COL2,NM_DATA_COL3
,有值和其他列为空。我创建了一个元表,它会给我逗号分隔的列名。
现在,当我尝试使用类型或游标时,问题是由于未填充所有值,因此会引发错误。我的程序是这样的:
create or replace PROCEDURE METADATA_AUTOMATION_MDPR (
in_id_scrub IN NUMBER
)
AS
V_COL_NAMES_CURRENT_SCRUB_DATA VARCHAR2(500);
V_COL_NAMES_OLD_SCRUB_DATA VARCHAR2(500);
V_COL_HEADER_MAP_WORKFLOW VARCHAR2(500);
sqlstmt VARCHAR2(2000);
V_Generic_MDMU_Scrub_Cols Generic_MDMU_Scrub_Cols_OBJ;
SELECT COL_NAMES_CURRENT_SCRUB_DATA, COL_NAMES_OLD_SCRUB_DATA, COL_HEADER_MAP_WORKFLOW INTO V_COL_NAMES_CURRENT_SCRUB_DATA, V_COL_NAMES_OLD_SCRUB_DATA, V_COL_HEADER_MAP_WORKFLOW FROM MDDBO.MDMU_METADATA_AUTOMATION_MDTB WHERE ID_WORKFLOW_MAINTENANCE_MSTR = in_id_wf;
DBMS_OUTPUT.PUT_LINE(V_COL_NAMES_CURRENT_SCRUB_DATA || ' --- ' || V_COL_NAMES_OLD_SCRUB_DATA || ' --- ' || V_COL_HEADER_MAP_WORKFLOW);
sqlstmt:= 'select ' || V_COL_NAMES_CURRENT_SCRUB_DATA || ',' || V_COL_NAMES_OLD_SCRUB_DATA || ',' || V_COL_HEADER_MAP_WORKFLOW || ',AUTO.TYPE_OF_ENTRY i_strTypeOfEntry FROM MDDBO.MDMU_SCRUB_DATA_MDTB DATA, MDDBO.MDMU_SCRUB_LOG_MDTB MSTR, MDDBO.MDMU_MAP_WORK_FLOW_MDTB WKF,
MDDBO.MDMU_METADATA_AUTOMATION_MDTB AUTO WHERE
MSTR.ID_TBL = WKF.ID_WF and
MSTR.id_scrub = :in_id_scrub and MSTR.id_scrub = DATA.id_scrub and
AUTO.ID_WORKFLOW_MAINTENANCE_MSTR = WKF.ID_WF';
DBMS_OUTPUT.PUT_LINE(sqlstmt);
EXECUTE IMMEDIATE sqlstmt
INTO V_Generic_MDMU_Scrub_Cols
USING in_id_scrub;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('error '||sqlerrm);
END METADATA_AUTOMATION_MDPR;
但它会在类型的情况下引发如下所示的 Oracle 错误 -
error ORA-00932: inconsistent datatypes: expected - got -
一些 Oracle Guy 建议使用 Global Temporary Table (GTT),但我相信它们在所有会话中都很常见,在这里不可行。所以,如果我想部分填充,但我不确定这是否是最好的情况,或者可以用对象完成一些事情,比如将未使用的值部分初始化为 null。
更新
从 2 个语句中打印 dbms_ouput 以使事情更清晰
输出1:
DATA_VAL1,DATA_VAL2,DATA_VAL3,DATA_VAL4,DATA_VAL5 --- OLD_DATA_VAL1,OLD_DATA_VAL2,OLD_DATA_VAL3,OLD_DATA_VAL4,OLD_DATA_VAL5 --- NM_DATA_COL1,NM_DATA_COL2,NM_DATA_COL3,NM_DATA_COL4,NM_DATA_COL5
输出2:
select DATA_VAL1,DATA_VAL2,DATA_VAL3,DATA_VAL4,DATA_VAL5,OLD_DATA_VAL1,OLD_DATA_VAL2,OLD_DATA_VAL3,OLD_DATA_VAL4,OLD_DATA_VAL5,NM_DATA_COL1,NM_DATA_COL2,NM_DATA_COL3,NM_DATA_COL4,NM_DATA_COL5,AUTO.TYPE_OF_ENTRY i_strTypeOfEntry FROM MDDBO.MDMU_SCRUB_DATA_MDTB DATA, MDDBO.MDMU_SCRUB_LOG_MDTB MSTR, MDDBO.MDMU_MAP_WORK_FLOW_MDTB WKF,
MDDBO.MDMU_METADATA_AUTOMATION_MDTB AUTO WHERE
MSTR.ID_TBL = WKF.ID_WF and
MSTR.id_scrub = :in_id_scrub and MSTR.id_scrub = DATA.id_scrub and
AUTO.ID_WORKFLOW_MAINTENANCE_MSTR = WKF.ID_WF
主要问题- 与对象类型中的列数相比,动态选择的列数更少。(见输出 1,每个也可以有 3 个)
更新 2
现在我主要关心的是如何从由可变数量的选定列形成的动态 sql 中获取值。
使用下面的查询我能够获得列标题,但不知何故无法获得 col 值。我的查询将只返回一行-
OPEN rc_ FOR sqlstmt using in_id_scrub;
c_ := DBMS_SQL.to_cursor_number(rc_);
DBMS_SQL.DESCRIBE_COLUMNS(c_, col_count_, desc_tab_);
FOR i_ IN 1..col_count_ LOOP
DBMS_OUTPUT.PUT_LINE(desc_tab_(i_).col_name);
DBMS_SQL.DEFINE_COLUMN(c_, i_, desc_tab_(i_).COL_NAME, 2000);
END LOOP;
res := DBMS_SQL.EXECUTE_AND_FETCH(c_, TRUE);
--DBMS_OUTPUT.PUT_LINE(res);
FOR i IN 1..col_count_ LOOP
tab1.EXTEND;
DBMS_SQL.COLUMN_VALUE(c_, i, tab1(tab1.LAST));
--DBMS_SQL.COLUMN_VALUE(c_, i, tab1(i));
--DBMS_SQL.COLUMN_VALUE(c_, i, arr1);
--DBMS_OUTPUT.PUT_LINE(tab1(1));
END LOOP;
DBMS_SQL.CLOSE_CURSOR(c_);
FOR l_row IN 1 .. tab1.COUNT
LOOP
DBMS_OUTPUT.put_line (tab1 (l_row));
END LOOP;