PLSQL : Return 对象所有属性的串联字符串
PLSQL : Return Concatenated string of all attributes of a Object
--Declare Object
create or replace TYPE INP_OBJ AS OBJECT
( attribute_1 VARCHAR2(20 CHAR)
,attribute_2 VARCHAR2(20 CHAR)
);
--Create Package
CREATE OR REPLACE PACKAGE TEST AS
PROCEDURE PROC1 (l_inp_obj IN INP_OBJ) ;
END TEST;
--Create Package Body
create or replace PACKAGE BODY TEST AS
PROCEDURE PROC1 (l_inp_obj IN INP_OBJ) IS
BEGIN
dbms_output.put_line(l_inp_obj.attribute_1 || ' ~ '|| l_inp_obj.attribute_2);
-- have to write every element individually here
END PROC1;
END TEST;
-- Calling Procedure
DECLARE
L_INP_OBJ INP_OBJ;
BEGIN
L_INP_OBJ := (INP_OBJ('VALUE OF ATTR 1'
,'VALUE OF ATTR 2'));
TEST.PROC1(L_INP_OBJ => L_INP_OBJ);
END;
为了显示,我必须单独编写输入对象的每个属性。有没有更好的方法 return 连接输入对象所有值的字符串?
根据我对的回答,你可以写一个包:
CREATE PACKAGE reflection IS
TYPE type_info IS RECORD(
prec PLS_INTEGER,
scale PLS_INTEGER,
len PLS_INTEGER,
csid PLS_INTEGER,
csfrm PLS_INTEGER,
schema_name VARCHAR2(30),
type_name VARCHAR2(30),
version VARCHAR2(100),
count PLS_INTEGER
);
TYPE attr_info IS RECORD(
prec PLS_INTEGER,
scale PLS_INTEGER,
len PLS_INTEGER,
csid PLS_INTEGER,
csfrm PLS_INTEGER,
attr_elt_type ANYTYPE,
aname VARCHAR2(30)
);
FUNCTION get_size(
p_anydata IN ANYDATA
) RETURN PLS_INTEGER;
FUNCTION get_attr_name_at(
p_anydata IN ANYDATA,
p_index IN PLS_INTEGER DEFAULT 1
) RETURN VARCHAR2;
FUNCTION get_attr_value_at(
p_anydata IN ANYDATA,
p_index IN PLS_INTEGER DEFAULT 1
) RETURN VARCHAR2;
END;
/
配正文:
CREATE PACKAGE BODY reflection IS
DEBUG BOOLEAN := FALSE;
FUNCTION get_type(
p_anydata IN ANYDATA
) RETURN ANYTYPE
IS
v_typeid PLS_INTEGER;
v_anytype ANYTYPE;
v_type_info REFLECTION.TYPE_INFO;
BEGIN
v_typeid := p_anydata.GetType( typ => v_anytype );
RETURN v_anytype;
END;
FUNCTION get_info(
p_anytype IN ANYTYPE
) RETURN type_info
IS
v_typeid PLS_INTEGER;
v_type_info REFLECTION.TYPE_INFO;
BEGIN
v_typeid := p_anytype.GetInfo (
v_type_info.prec,
v_type_info.scale,
v_type_info.len,
v_type_info.csid,
v_type_info.csfrm,
v_type_info.schema_name,
v_type_info.type_name,
v_type_info.version,
v_type_info.count
);
IF v_typeid <> DBMS_TYPES.TYPECODE_OBJECT THEN
RAISE_APPLICATION_ERROR( -20000, 'Not an object.' );
END IF;
RETURN v_type_info;
END;
FUNCTION get_size(
p_anydata IN ANYDATA
) RETURN PLS_INTEGER
IS
BEGIN
RETURN Get_Info( Get_Type( p_anydata ) ).COUNT;
END;
FUNCTION get_attr_name_at(
p_anydata IN ANYDATA,
p_index IN PLS_INTEGER DEFAULT 1
) RETURN VARCHAR2
IS
v_anydata ANYDATA := p_anydata;
v_anytype ANYTYPE;
v_type_info REFLECTION.TYPE_INFO;
v_output VARCHAR2(4000);
v_attr_typeid PLS_INTEGER;
v_attr_info REFLECTION.ATTR_INFO;
BEGIN
v_anytype := Get_Type( v_anydata );
v_type_info := Get_Info( v_anytype );
IF p_index < 1 OR p_index > v_type_info.COUNT THEN
RETURN NULL;
END IF;
v_anydata.PIECEWISE;
v_attr_typeid := v_anytype.getAttrElemInfo(
pos => p_index,
prec => v_attr_info.prec,
scale => v_attr_info.scale,
len => v_attr_info.len,
csid => v_attr_info.csid,
csfrm => v_attr_info.csfrm,
attr_elt_type => v_attr_info.attr_elt_type,
aname => v_attr_info.aname
);
RETURN v_attr_info.aname;
END;
FUNCTION get_attr_value_at(
p_anydata IN ANYDATA,
p_index IN PLS_INTEGER DEFAULT 1
) RETURN VARCHAR2
IS
v_anydata ANYDATA := p_anydata;
v_anytype ANYTYPE;
v_type_info REFLECTION.TYPE_INFO;
v_output VARCHAR2(4000);
BEGIN
v_anytype := Get_Type( v_anydata );
v_type_info := Get_Info( v_anytype );
IF p_index < 1 OR p_index > v_type_info.COUNT THEN
RETURN NULL;
END IF;
v_anydata.PIECEWISE;
FOR i IN 1 .. p_index LOOP
DECLARE
v_attr_typeid PLS_INTEGER;
v_attr_info REFLECTION.ATTR_INFO;
v_result_code PLS_INTEGER;
BEGIN
v_attr_typeid := v_anytype.getAttrElemInfo(
pos => i,
prec => v_attr_info.prec,
scale => v_attr_info.scale,
len => v_attr_info.len,
csid => v_attr_info.csid,
csfrm => v_attr_info.csfrm,
attr_elt_type => v_attr_info.attr_elt_type,
aname => v_attr_info.aname
);
IF DEBUG THEN
DBMS_OUTPUT.PUT_LINE(
'Attribute ' || i || ': '
|| v_attr_info.aname
|| ' (type ' || v_attr_typeid || ')'
);
END IF;
CASE v_attr_typeid
WHEN DBMS_TYPES.TYPECODE_NUMBER THEN
DECLARE
v_value NUMBER;
BEGIN
v_result_code := v_anydata.GetNumber( v_value );
IF i = p_index THEN
RETURN TO_CHAR( v_value );
END IF;
END;
WHEN DBMS_TYPES.TYPECODE_VARCHAR2 THEN
DECLARE
v_value VARCHAR2(4000);
BEGIN
v_result_code := v_anydata.GetVarchar2( v_value );
IF i = p_index THEN
RETURN v_value;
END IF;
END;
WHEN DBMS_TYPES.TYPECODE_DATE THEN
DECLARE
v_value DATE;
BEGIN
v_result_code := v_anydata.GetDate( v_value );
IF i = p_index THEN
RETURN TO_CHAR( v_value, 'YYYY-MM-DD HH24:MI:SS' );
END IF;
END;
ELSE
NULL;
END CASE;
END;
END LOOP;
RETURN NULL;
END;
END;
/
然后你可以遍历对象来找到属性并将包写为:
CREATE PACKAGE TEST AS
PROCEDURE PROC1 (p_anydata IN ANYDATA);
END TEST;
/
CREATE PACKAGE BODY TEST AS
PROCEDURE PROC1 (p_anydata IN ANYDATA)
IS
p_attr_name VARCHAR2(30);
p_attr_value VARCHAR2(4000);
BEGIN
FOR attr_no IN 1 .. REFLECTION.get_size(p_anydata) LOOP
p_attr_name := REFLECTION.get_attr_name_at(p_anydata, attr_no);
p_attr_value := REFLECTION.get_attr_value_at(p_anydata, attr_no);
IF attr_no > 1 THEN
DBMS_OUTPUT.PUT( ' ~ ' );
END IF;
DBMS_OUTPUT.PUT( p_attr_value );
END LOOP;
DBMS_OUTPUT.NEW_LINE;
END PROC1;
END TEST;
/
然后调用它:
DECLARE
L_INP_OBJ INP_OBJ;
BEGIN
L_INP_OBJ := INP_OBJ('VALUE OF ATTR 1' ,'VALUE OF ATTR 2');
TEST.PROC1(P_ANYDATA => ANYDATA.ConvertObject(L_INP_OBJ);
END;
/
--Declare Object
create or replace TYPE INP_OBJ AS OBJECT
( attribute_1 VARCHAR2(20 CHAR)
,attribute_2 VARCHAR2(20 CHAR)
);
--Create Package
CREATE OR REPLACE PACKAGE TEST AS
PROCEDURE PROC1 (l_inp_obj IN INP_OBJ) ;
END TEST;
--Create Package Body
create or replace PACKAGE BODY TEST AS
PROCEDURE PROC1 (l_inp_obj IN INP_OBJ) IS
BEGIN
dbms_output.put_line(l_inp_obj.attribute_1 || ' ~ '|| l_inp_obj.attribute_2);
-- have to write every element individually here
END PROC1;
END TEST;
-- Calling Procedure
DECLARE
L_INP_OBJ INP_OBJ;
BEGIN
L_INP_OBJ := (INP_OBJ('VALUE OF ATTR 1'
,'VALUE OF ATTR 2'));
TEST.PROC1(L_INP_OBJ => L_INP_OBJ);
END;
为了显示,我必须单独编写输入对象的每个属性。有没有更好的方法 return 连接输入对象所有值的字符串?
根据我对
CREATE PACKAGE reflection IS
TYPE type_info IS RECORD(
prec PLS_INTEGER,
scale PLS_INTEGER,
len PLS_INTEGER,
csid PLS_INTEGER,
csfrm PLS_INTEGER,
schema_name VARCHAR2(30),
type_name VARCHAR2(30),
version VARCHAR2(100),
count PLS_INTEGER
);
TYPE attr_info IS RECORD(
prec PLS_INTEGER,
scale PLS_INTEGER,
len PLS_INTEGER,
csid PLS_INTEGER,
csfrm PLS_INTEGER,
attr_elt_type ANYTYPE,
aname VARCHAR2(30)
);
FUNCTION get_size(
p_anydata IN ANYDATA
) RETURN PLS_INTEGER;
FUNCTION get_attr_name_at(
p_anydata IN ANYDATA,
p_index IN PLS_INTEGER DEFAULT 1
) RETURN VARCHAR2;
FUNCTION get_attr_value_at(
p_anydata IN ANYDATA,
p_index IN PLS_INTEGER DEFAULT 1
) RETURN VARCHAR2;
END;
/
配正文:
CREATE PACKAGE BODY reflection IS
DEBUG BOOLEAN := FALSE;
FUNCTION get_type(
p_anydata IN ANYDATA
) RETURN ANYTYPE
IS
v_typeid PLS_INTEGER;
v_anytype ANYTYPE;
v_type_info REFLECTION.TYPE_INFO;
BEGIN
v_typeid := p_anydata.GetType( typ => v_anytype );
RETURN v_anytype;
END;
FUNCTION get_info(
p_anytype IN ANYTYPE
) RETURN type_info
IS
v_typeid PLS_INTEGER;
v_type_info REFLECTION.TYPE_INFO;
BEGIN
v_typeid := p_anytype.GetInfo (
v_type_info.prec,
v_type_info.scale,
v_type_info.len,
v_type_info.csid,
v_type_info.csfrm,
v_type_info.schema_name,
v_type_info.type_name,
v_type_info.version,
v_type_info.count
);
IF v_typeid <> DBMS_TYPES.TYPECODE_OBJECT THEN
RAISE_APPLICATION_ERROR( -20000, 'Not an object.' );
END IF;
RETURN v_type_info;
END;
FUNCTION get_size(
p_anydata IN ANYDATA
) RETURN PLS_INTEGER
IS
BEGIN
RETURN Get_Info( Get_Type( p_anydata ) ).COUNT;
END;
FUNCTION get_attr_name_at(
p_anydata IN ANYDATA,
p_index IN PLS_INTEGER DEFAULT 1
) RETURN VARCHAR2
IS
v_anydata ANYDATA := p_anydata;
v_anytype ANYTYPE;
v_type_info REFLECTION.TYPE_INFO;
v_output VARCHAR2(4000);
v_attr_typeid PLS_INTEGER;
v_attr_info REFLECTION.ATTR_INFO;
BEGIN
v_anytype := Get_Type( v_anydata );
v_type_info := Get_Info( v_anytype );
IF p_index < 1 OR p_index > v_type_info.COUNT THEN
RETURN NULL;
END IF;
v_anydata.PIECEWISE;
v_attr_typeid := v_anytype.getAttrElemInfo(
pos => p_index,
prec => v_attr_info.prec,
scale => v_attr_info.scale,
len => v_attr_info.len,
csid => v_attr_info.csid,
csfrm => v_attr_info.csfrm,
attr_elt_type => v_attr_info.attr_elt_type,
aname => v_attr_info.aname
);
RETURN v_attr_info.aname;
END;
FUNCTION get_attr_value_at(
p_anydata IN ANYDATA,
p_index IN PLS_INTEGER DEFAULT 1
) RETURN VARCHAR2
IS
v_anydata ANYDATA := p_anydata;
v_anytype ANYTYPE;
v_type_info REFLECTION.TYPE_INFO;
v_output VARCHAR2(4000);
BEGIN
v_anytype := Get_Type( v_anydata );
v_type_info := Get_Info( v_anytype );
IF p_index < 1 OR p_index > v_type_info.COUNT THEN
RETURN NULL;
END IF;
v_anydata.PIECEWISE;
FOR i IN 1 .. p_index LOOP
DECLARE
v_attr_typeid PLS_INTEGER;
v_attr_info REFLECTION.ATTR_INFO;
v_result_code PLS_INTEGER;
BEGIN
v_attr_typeid := v_anytype.getAttrElemInfo(
pos => i,
prec => v_attr_info.prec,
scale => v_attr_info.scale,
len => v_attr_info.len,
csid => v_attr_info.csid,
csfrm => v_attr_info.csfrm,
attr_elt_type => v_attr_info.attr_elt_type,
aname => v_attr_info.aname
);
IF DEBUG THEN
DBMS_OUTPUT.PUT_LINE(
'Attribute ' || i || ': '
|| v_attr_info.aname
|| ' (type ' || v_attr_typeid || ')'
);
END IF;
CASE v_attr_typeid
WHEN DBMS_TYPES.TYPECODE_NUMBER THEN
DECLARE
v_value NUMBER;
BEGIN
v_result_code := v_anydata.GetNumber( v_value );
IF i = p_index THEN
RETURN TO_CHAR( v_value );
END IF;
END;
WHEN DBMS_TYPES.TYPECODE_VARCHAR2 THEN
DECLARE
v_value VARCHAR2(4000);
BEGIN
v_result_code := v_anydata.GetVarchar2( v_value );
IF i = p_index THEN
RETURN v_value;
END IF;
END;
WHEN DBMS_TYPES.TYPECODE_DATE THEN
DECLARE
v_value DATE;
BEGIN
v_result_code := v_anydata.GetDate( v_value );
IF i = p_index THEN
RETURN TO_CHAR( v_value, 'YYYY-MM-DD HH24:MI:SS' );
END IF;
END;
ELSE
NULL;
END CASE;
END;
END LOOP;
RETURN NULL;
END;
END;
/
然后你可以遍历对象来找到属性并将包写为:
CREATE PACKAGE TEST AS
PROCEDURE PROC1 (p_anydata IN ANYDATA);
END TEST;
/
CREATE PACKAGE BODY TEST AS
PROCEDURE PROC1 (p_anydata IN ANYDATA)
IS
p_attr_name VARCHAR2(30);
p_attr_value VARCHAR2(4000);
BEGIN
FOR attr_no IN 1 .. REFLECTION.get_size(p_anydata) LOOP
p_attr_name := REFLECTION.get_attr_name_at(p_anydata, attr_no);
p_attr_value := REFLECTION.get_attr_value_at(p_anydata, attr_no);
IF attr_no > 1 THEN
DBMS_OUTPUT.PUT( ' ~ ' );
END IF;
DBMS_OUTPUT.PUT( p_attr_value );
END LOOP;
DBMS_OUTPUT.NEW_LINE;
END PROC1;
END TEST;
/
然后调用它:
DECLARE
L_INP_OBJ INP_OBJ;
BEGIN
L_INP_OBJ := INP_OBJ('VALUE OF ATTR 1' ,'VALUE OF ATTR 2');
TEST.PROC1(P_ANYDATA => ANYDATA.ConvertObject(L_INP_OBJ);
END;
/