Dbms_xmlgen using pl-sql record type
Hi
I want to pass pl-sql record type and want to generate xml. Can dbms_xmlgen access pl-sql record type instead of query?
OR please let me know any other package to pass pl-sql record type and generate XML.
Thanks in advance
Can dbms_xmlgen access pl-sql record type instead of query?Don't think so, but can't you pass the individual record components:
SQL> declare
type rec is record
a int,
b varchar2 (30)
r rec;
ctx int;
x xmltype;
begin
r.a := 1;
r.b := 'Michael';
ctx := dbms_xmlgen.newcontext ('select :x id, :y name from dual');
dbms_xmlgen.setbindvalue (ctx, 'x', r.a);
dbms_xmlgen.setbindvalue (ctx, 'y', r.b);
x := dbms_xmlgen.getxmltype (ctx);
dbms_output.put_line (x.getstringval ());
dbms_xmlgen.closecontext (ctx);
end;
<ROWSET>
<ROW>
<ID>1</ID>
<NAME>Michael</NAME>
</ROW>
</ROWSET>
PL/SQL procedure successfully completed.?
Similar Messages
-
How to update by using PL/SQL Records
Hi,
I want to update EMP table columns ename and empno only
from other existing table TEST_EMP
EMP table contains 14 rows.TEST_EMP table contains 3 rows.
I need to update first three rows in EMP table.
TEST_EMP DATA IS:
ENAME EMPNO
E1 1001
E2 1002
E3 1003
Following code i written to update EMP table.
DECLARE
type r is record(id emp.empno%type,
name emp.ename%type);
r1 r;
BEGIN
select ename,empno into r1 from test_emp;
FOR i IN r1.FIRST .. r1.LAST
LOOP
update emp2
set ename=r1(i).ename,
empno=r1(i).empno
WHERE empno = l_rc (i).empno;
end loop;
commit;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line (SQLERRM (SQLCODE));
END;
ERROR OCCURRED:
ORA-06550: line 9, column 14:
PLS-00302: component 'FIRST' must be declared
ORA-06550: line 9, column 2:
PL/SQL: Statement ignored
I should use PL/SQL Record to update Table This is Mandatory.
pls guide me.
Regards,
Venkat.> I want to update EMP table columns ename and empno only
from other existing table TEST_EMP
Why use PL/SQL and why use cursors?
You are running a SELECT on the source table via the SQL engine and pulling that data from the db buffer cache into PL/SQL variables.
Then you take that very same data, and push that back to the SQL engine using an UPDATE.
So if you need to update 10KB worth of data, it means pulling 10KB from the SQL engine into the PL engine.. and then pushing 10KB of data from the PL engine back to the SQL engine.
Not only pushing and pulling - you need your code to switch continually between the PL and SQL engines to do this.
Now imagine doing it for 10MB of data.. or 1GB of data.. or more.
Does it sound like your approach is effective? Does it sounds like it will perform well? Does it sound like it will scale?
The basic rule for Oracle development is:
Maximize SQL. Minimize PL/SQL (or Java or C#, etc). -
Can you confirm for me please? - jdbc to pl/sql record types
Hi, I was hoping somebody could confirm the following please? I've been researching this in the Oracle JDBC docs and the Internet, but would feel more comfortable if somebody would confirm my findings.
I have a 10g database pl/sql procedure that takes a pl/sql record type as both IN and OUT parameter. I'm not allowed to modify this legacy procedure, though I may create new supporting code.
My research shows there is no inherit support in JDBC for Oracle pl/sql record types as per the Oracle JDBC docs.
As a solution, if the procedure only returned a record type, my understanding is I could create a ref cursor in pl/sql, as well as a wrapper procedure that calls my original procedure, and returns the record type through the ref cursor. This could then be used by my JDBC code as JDBC supports ref cursors as a return type.
However in my case, as the record type is both an IN and OUT parameter of my procedure, my research so far says JDBC support for ref cursors does not allow the writing of value to the ref cursor to be submitted back to the database. Is this correct?
If this limitation exists, as such the better (and only?) solution is to create a shadow pl/sql procedure that takes all the record elements as separate IN OUT parameters and then create a private record based on the record type and pass it to the original procedure.
Is my research here correct? Any help appreciated.
Thanks & regards,
CM.Chris,
As far as I know, PL/SQL record types are not supported in JDBC.
I believe you may be able to use TopLink.
I think Kuassi Mensah may have some examples in his book Oracle Database Programming.
Alternatively, you could use an Oracle object instead of a PL/SQL record.
This would be similar to what you are suggesting except that instead of a ref cursor, you would transfer the PL/SQL record to an Oracle object.
Good Luck,
Avi. -
Any way to encode/decode PL/SQL record types ?
Hello everyone,
I came to XDK because I was looking for an easy way or working around a JDBC driver limitation. Namely that it does not access PL/SQL record types. I thought the best way was to encode my package's public types into XML streams and wrap up each public routine into a set of routines receiving and exporting data in XML.
I installed XDK 9i/PL/SQL yesterday and tried it on my 8.1.6 db. So far so good.
However, I did not see anything that does not access directly the database. The only preocupation of XSU is to access directly the DB for a variety of select, insert...
Am I wrong ?
I'm looking for a routine that takes an XML varchar, a DTD varchar and some description of my type (to map tags to fields) and parses the whole thing...
Is there anything I could use to do that ???
Thanks in advance...
AlainMarwim wrote:
You code should be instrumented. Whenever you need to debug/trace you switch it on and get a log fileor log table; it maybe a database parameter or simply a package variable, which you can set at runtime.
This will allow you to debug a production environment where you should never be allowed to change the code or to use adebugger.And very valuable advice this is...
Debugging needs to be part and parcel of a code unit (like a PL/SQL package), where you can execute it (in production or anywhere else) and tell it "+go forth, execute, and debug thyself+". -
PL/SQL Record Type to XMLType
Hi,
I wanted to convert a pl/sql record type automatically with just one command using xmltype.createXML but I am wondering if anyone out there has used it this way or whether it is possible. I can't find any examples anywhere, and I didn't really want to do the hard work of doing it one element at a time using xmlelement & xmlattributes :-).....
e.g.,
l_record emp%rowtype;
l_xml xmltype;
begin
for l_record in (select * from emp)
loop
l_xml := xmltype.convertXML (l_record) ; --> is this possible?? I can do it on a cursor but it doesn't seem to like it if its a record type
end loop;
Thanks in anticipation.
M
Edited by: user12097147 on 3/11/2009 16:48You cannot pass just any record structure to a procedure and expects it to determine its structure and contents and give you XML in return.
Also when you call XMLTYPE(), you are essentially instantiating an object - and calling the constructor method of that class. There are a number of constructors that have different parameter signatures.
If you want XML from a table, then you should be using XML functions.. in the following fashion (there's a number of approaches you can use, depending on your requirements) :
SQL> select xmlElement( "Employee", xmlForest(e.empno, e.ename,e.job) ) as XML from emp e order by e.empno;
XML
<Employee><EMPNO>7369</EMPNO><ENAME>SMITH</ENAME><JOB>CLERK</JOB></Employee>
<Employee><EMPNO>7499</EMPNO><ENAME>ALLEN</ENAME><JOB>SALESMAN</JOB></Employee>
<Employee><EMPNO>7521</EMPNO><ENAME>WARD</ENAME><JOB>SALESMAN</JOB></Employee>
<Employee><EMPNO>7566</EMPNO><ENAME>JONES</ENAME><JOB>MANAGER</JOB></Employee>
<Employee><EMPNO>7654</EMPNO><ENAME>MARTIN</ENAME><JOB>SALESMAN</JOB></Employee>
<Employee><EMPNO>7698</EMPNO><ENAME>BLAKE</ENAME><JOB>MANAGER</JOB></Employee>
<Employee><EMPNO>7782</EMPNO><ENAME>CLARK</ENAME><JOB>MANAGER</JOB></Employee>
<Employee><EMPNO>7788</EMPNO><ENAME>SCOTT</ENAME><JOB>ANALYST</JOB></Employee>
<Employee><EMPNO>7839</EMPNO><ENAME>KING</ENAME><JOB>PRESIDENT</JOB></Employee>
<Employee><EMPNO>7844</EMPNO><ENAME>TURNER</ENAME><JOB>SALESMAN</JOB></Employee>
<Employee><EMPNO>7876</EMPNO><ENAME>ADAMS</ENAME><JOB>CLERK</JOB></Employee>
<Employee><EMPNO>7900</EMPNO><ENAME>JAMES</ENAME><JOB>CLERK</JOB></Employee>
<Employee><EMPNO>7902</EMPNO><ENAME>FORD</ENAME><JOB>ANALYST</JOB></Employee>
<Employee><EMPNO>7934</EMPNO><ENAME>MILLER</ENAME><JOB>CLERK</JOB></Employee>
14 rows selected. -
Return rows from pl-sql record type
We have a requirement to create function which returns cursor to java application. This cursor will have data from pl-sql record type.
Tried with pipelined function. I have written code below.
CREATE or replace PACKAGE test_pkg IS
TYPE tp_rec IS RECORD(tt_id INTEGER,tt_text VARCHAR2(40));
TYPE obj_tp_recs IS TABLE OF tp_rec;
TYPE obj_tp_recs1 IS TABLE OF tp_rec;
FUNCTION test_func RETURN tp_rec;
function type_out return obj_tp_recs1 PIPELINED;
PROCEDURE test_type (result out sys_refcursor);
END;
CREATE OR REPLACE PACKAGE BODY OMS.test_pkg IS
FUNCTION test_func RETURN tp_rec
AS
currec tp_rec;
BEGIN
currec.tt_id := 1;
currec.tt_text := 'test1';
END;
FUNCTION type_out RETURN obj_tp_recs1 PIPELINED
AS
currec1 test_pkg.tp_rec;
begin
currec1 := test_pkg.test_func;
PIPE ROW(currec1);
dbms_output.put_line(currec1.tt_id);
end;
PROCEDURE test_type (result out sys_refcursor)
AS
BEGIN
OPEN RESULT
FOR SELECT * FROM TABLE(test_pkg.type_out());
END;
END;
SQL> VARIABLE x REFCURSOR
SQL> exec test_pkg.test_type(:x);
PL/SQL procedure successfully completed.
SQL> print xThis code returns no data found exeception from function. How to achieve result 1 and test1 from above code?
Thanks in advanceSQL> VARIABLE x REFCURSOR
SQL> exec test_pkg.test_type(:x);
PL/SQL procedure successfully completed.
SQL> print x
ERROR:
ORA-06503: PL/SQL: Function returned without value
ORA-06512: at "SCOTT.TEST_PKG", line 8
ORA-06512: at "SCOTT.TEST_PKG", line 14
no rows selectedIf you look at test_func body it is missing return statement. Now:
SQL> CREATE OR REPLACE PACKAGE BODY test_pkg IS
2 FUNCTION test_func RETURN tp_rec
3 AS
4 currec tp_rec;
5 BEGIN
6 currec.tt_id := 1;
7 currec.tt_text := 'test1';
8 RETURN currec;
9 END;
10
11 FUNCTION type_out RETURN obj_tp_recs1 PIPELINED
12 AS
13 currec1 test_pkg.tp_rec;
14 begin
15 currec1 := test_pkg.test_func;
16 PIPE ROW(currec1);
17 dbms_output.put_line(currec1.tt_id);
18 end;
19
20 PROCEDURE test_type (result out sys_refcursor)
21 AS
22 BEGIN
23 OPEN RESULT
24 FOR SELECT * FROM TABLE(test_pkg.type_out());
25
26 END;
27 END;
28 /
Package body created.
SQL> exec test_pkg.test_type(:x);
PL/SQL procedure successfully completed.
SQL> print x
TT_ID TT_TEXT
1 test1
SQL> SY. -
Implementing First In First Out Behaviour Using PL/SQL object types
Hi Friends,
I have a Integer Array of type Varray, I want to implement first in first out behaviour using Pl/SQL object type.Please provide me some idea that i can proceed. If you can provide me any sample code or any documentation,i will be very much thankful to you.Eagerly waiting for your reply.
Thanksbasically i have to implement a queue using pl/sql object types to traverse a tree as we can implement stack (LIFO).
I can give an example of Stack implementation...
CREATE or replace TYPE IntArray AS VARRAY(50) OF INTEGER;
CREATE or replace TYPE IntStack_O AS OBJECT (
maximalSize INTEGER
,top INTEGER
,position IntArray
,MEMBER PROCEDURE initialize
,MEMBER FUNCTION full RETURN BOOLEAN
,MEMBER FUNCTION empty RETURN BOOLEAN
,MEMBER FUNCTION getAnzahl RETURN INTEGER
,MEMBER PROCEDURE push (n IN INTEGER)
,MEMBER PROCEDURE pop (n OUT INTEGER)
CREATE or replace TYPE body IntStack_O AS
MEMBER PROCEDURE initialize IS
BEGIN
top := 0;
-- Call Constructor und set element 1 to NULL
position := IntArray(NULL);
maximalSize := position.LIMIT; -- Get Varray Size
position.EXTEND(maximalSize -1, 1); -- copy elements 1 in 2..50
END initialize;
MEMBER FUNCTION full RETURN BOOLEAN IS
BEGIN
RETURN (top = maximalSize); — Return TRUE when Stack is full
END full;
MEMBER FUNCTION empty RETURN BOOLEAN IS
BEGIN
RETURN (top = 0); — Return TRUE when Stack is empty
END empty;
MEMBER FUNCTION getAnzahl RETURN integer IS
BEGIN
RETURN top;
END;
MEMBER PROCEDURE push (n IN INTEGER) IS
BEGIN
IF NOT full
THEN
top := top + 1; — Push Integer onto the stack
position(top) := n;
ELSE
–Stack ist voll!
RAISE_APPLICATION_ERROR(-20101, ‘Error! Stack overflow. ‘
||’limit for stacksize reached.’);
END IF;
END push;
MEMBER PROCEDURE pop (n OUT INTEGER) IS
BEGIN
IF NOT empty
THEN
n := position(top);
top := top -1; — take top element from stack
ELSE
–Stack ist leer!
RAISE_APPLICATION_ERROR(-20102, ‘Error! Stack underflow. ‘
||’stack is empty.’);
END IF;
END pop;
END;
Now if i run this..i will be getting the following output...
DECLARE
stack intstack_o := intstack_o(NULL,NULL,NULL);
a INTEGER;
BEGIN
stack.initialize;
dbms_output.put_line('Anzahl: ' || stack.getAnzahl);
stack.push(1111);
dbms_output.put_line('Anzahl: ' || stack.getAnzahl);
stack.push(1112);
dbms_output.put_line('Anzahl: ' || stack.getAnzahl);
stack.push(1113);
dbms_output.put_line('Anzahl: ' || stack.getAnzahl);
stack.pop(a);
dbms_output.put_line('Anzahl: ' || stack.getAnzahl);
dbms_output.put_line(a);
stack.pop(a);
dbms_output.put_line('Anzahl: ' || stack.getAnzahl);
dbms_output.put_line(a);
stack.pop(a);
dbms_output.put_line('Anzahl: ' || stack.getAnzahl);
dbms_output.put_line(a);
stack.pop(a);
dbms_output.put_line('Anzahl: ' || stack.getAnzahl);
dbms_output.put_line(a);
END;
Output...
Anzahl: 0
Anzahl: 1
Anzahl: 2
Anzahl: 3
Anzahl: 2
1113
Anzahl: 1
1112
Anzahl: 0
1111
Above is the Stack (Last In First Out) Implementations of integer array.Now my Requirement is Queue(First In First Out) Implementation of Integer array. -
PL/SQL Record Type and Toplink
Can i call PL/SQL procedure having a parameter of record type in toplink. If yes, how it is possible?
Hi,
Record defines a representation of a database row as field=>value pairs.Whenever a query is exceuted the rows in the result set can be accessed thru RECORD interface.Can you be more elaborate on the question.
Are you trying to access the result set obtained after executing the Stored Proc using Record interface or you want to pass the Record as input parameter to Stored proc? -
Creating PL/SQL web services from PL/SQL records
Hello
Jdeveloper does not allow to create web services from pl/sql packages that use PL/SQL records.to do this,we have to use the jpublisher ?without using the jpublisher,if we create a webservice then the following error is displayed in the web service xml output file.
<faultstring>Internal Server Error (Caught exception while handling request: java.rmi.RemoteException: java.sql.SQLException: ORA-06550: line 1, column 49: PLS-00181: unsupported preprocessor directive '$WS_SP_EVEN' )</faultstring>
</env:Fault>
Could any one suggest me, how to solve the above issue..?
Regards
MalathiThank you, with db adapter it was working and also
pl/sql web-services working successfully with object types.If we want to send the web-services to the client, do we need to send the entire folder that is created in the web-services folder of the external oc4j..?
Creating the client process:
we are using the wsdl file that is generated in the web-services and adding to the partner link to Invoke the operations of web-services. Is there any other way to invoke the webservices?Could any one please suggest me?
Thanking you
Malathi -
We have a procedure in a package,this procedure makes use of a Record Type.
In BPEL, whiile creating the partner link, when we are trying to access this procedure we get the following error.
"WSDLException:faultCode=OTHER_ERROR:Database type is either not supported or is not implemented.
Parameter L_ECO_REC is of type SAN_REC_TYPE which is either not supported or not an implemented data type.
Check to ensure that the type of the parameter is one of the supported datatypes or that there is a collection or user defined type definition representing this type defined in the database.contact oracle support if error is not fixable."
Also please find below the package specification and body:
CREATE OR REPLACE package eco_pack is
TYPE San_Rec_Type IS RECORD
( Eco_Name VARCHAR2(10)
, Change_Notice_Prefix VARCHAR2(10)
, Change_Notice_Number NUMBER
, Organization_Code VARCHAR2(3)
PROCEDURE sandeep(l_eco_rec IN eco_pack.San_Rec_Type);
end;
CREATE OR REPLACE package body eco_pack is
PROCEDURE createeco(l_eco_rec IN eco_pack.San_Rec_Type) AS
BEGIN
INSERT
INTO ag_log
VALUES(1, 'ECO name is' || l_eco_rec.eco_name, 1);
COMMIT;
END;
end;
Does BPEl support PL/SQL Record Type, if so how ?
Thanks,
Shivram
.PL/SQL types like RECORD, BOOLEAN and TABLE are not supported in the DB adapter with the current BPEL PM release (as the error message indicates). You can use JPublisher manually to generate an OBJECT type that corresponds with the RECORD. JPublisher will also create a wrapper and conversion APIs to convert between the two. You would then call the wrapper API which takes the OBJECT and then calls the underlying PL/SQL that takes the RECORD.
With the 10.1.2 Phase 2 release of BPEL PM, the DB adapter does all of this for you from within the design time wizard. JPublisher is invoked silently under the covers, the SQL that gets generated is automatically loaded into the database schema. That will create the OBJECT type, wrapper and conversion APIs. An XSD is generated for the wrapper API. Your partner link will invoke the wrapper, not the original API.
Note also that support for BOOLEAN and TABLE was also added. JPublisher generates wrapper APIs that substitute appropriate types for these parameters (e.g. INTEGER for BOOLEAN, Nested Table for TABLE). -
Unable to INSERT PL/SQL record with EXECUTE IMMEDIATE
Hi All,
I am selecting data from a source table and after some modification inserting into a target table. Source and target table name are available at run time. You can say only source table structure is fixed.
I have crated a pl/sql table of type source record and inserting record by record in target table using execute immediate. But I am not able to write
EXECUTE IMMEDIATE string USING pl_sql_table(index); and getting error as
PLS-00457: expressions have to be of SQL types
Please see the part of code below. Is it possible to use FORALL with dynamic sql like
FORALL pl_sql_table.FIRST .. pl_sql_table.COUNT
EXECUTE IMMEDIATE .... pl_sql_table(j); -- Like this.
Please suggest why I am not able to write record here. I also want to replace 'INSERT in a loop' with a single INSERT statement out of the loop, to upload whole pl_sql table into target table in one go.
Thanks,
Ravi
DECLARE
TYPE rec_tab_CMP IS RECORD
model_id NUMBER(38),
absolute_rank NUMBER(5)
v_rec_tab_CMP rec_tab_CMP;
TYPE t_rec_tab_CMP IS TABLE OF v_rec_tab_CMP%TYPE INDEX BY BINARY_INTEGER;
v_records_CMP t_rec_tab_CMP;
rc SYS_REFCURSOR;
v_old_table_name VARCHAR2(30); -- passed from parameter
v_new_table_name VARCHAR2(30); -- passed from parameter
dyn_str VARCHAR2(500);
v_columns_str VARCHAR2(200) := ' model_id, absolute_rank ';
BEGIN
EXECUTE IMMEDIATE 'CREATE TABLE '|| v_new_table_name || ' AS SELECT * FROM ' || v_old_table_name ||' WHERE 1 = 2 ' ;
OPEN rc FOR 'SELECT '|| v_columns_str ||' FROM '|| v_old_table_name;
FETCH rc BULK COLLECT INTO v_records_CMP;
FOR j IN 1..v_records_CMP.COUNT
LOOP
v_records_CMP(j).model_id := 1; -- Do someting here, This thing can be performed in SQL stmt directly.
dyn_str := 'INSERT INTO '|| v_new_table_name ||' ( '|| v_columns_str || ' ) VALUES (:1, :2) ';
EXECUTE IMMEDIATE dyn_str USING v_records_CMP(j).model_id ,
v_records_CMP(j).absolute_rank ;
-- Here in place of two columns I want to use one record like
-- EXECUTE IMMEDIATE dyn_str USING v_records_CMP(j);
-- But it is giving me error like
-- EXECUTE IMMEDIATE dyn_str USING v_records_st(j);
-- PLS-00457: expressions have to be of SQL types
END LOOP;
CLOSE rc;
END;
/You cannot bind PL/SQL record types to dynamic SQL.
Possibly you could work around this by declaring the INDEX-BY table of records at package specification level, e.g.
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Production
SQL> CREATE PACKAGE package_name
2 AS
3 TYPE tt_emp IS TABLE OF emp%ROWTYPE;
4 t_emp tt_emp;
5 END package_name;
6 /
Package created.
SQL> CREATE TABLE new_emp
2 AS
3 SELECT *
4 FROM emp
5 WHERE 1 = 0;
Table created.
SQL> DECLARE
2 v_table_name user_tables.table_name%TYPE := 'NEW_EMP';
3 BEGIN
4 SELECT *
5 BULK COLLECT INTO package_name.t_emp
6 FROM emp;
7
8 EXECUTE IMMEDIATE
9 'BEGIN ' ||
10 ' FORALL i IN 1 ..package_name.t_emp.COUNT ' ||
11 ' INSERT INTO ' || v_table_name ||
12 ' VALUES package_name.t_emp (i); ' ||
13 'END;';
14 END;
15 /
PL/SQL procedure successfully completed.
SQL> SELECT empno, ename
2 FROM new_emp;
EMPNO ENAME
7369 SMITH
7499 ALLEN
7521 WARD
7566 JONES
7654 MARTIN
7698 BLAKE
7782 CLARK
7788 SCOTT
7839 KING
7844 TURNER
7876 ADAMS
7900 JAMES
7902 FORD
7934 MILLER
14 rows selected.
SQL> -
Hello
I have a Oracle Stored Procedure and one of the input parameter is of Type 'RECORD' , So how do i bind to this kind of types using Java Data Type through JDBC
Any help with the sample code is greatly appreciated,
KMYou can't do so directly from JDBC.
The current (10g R2) Oracle documentation (which is online and searchable, by the way) says:
PL/SQL TABLE, BOOLEAN, and RECORD Types
It is not feasible for Oracle JDBC drivers to support calling arguments or return values of the PL/SQL RECORD, BOOLEAN, or table with non-scalar element types. However, Oracle JDBC drivers support PL/SQL index-by table of scalar element types.
As a workaround to PL/SQL RECORD, BOOLEAN, or non-scalar table types, create wrapper procedures that handle the data as types supported by JDBC. For example, to wrap a stored procedure that uses PL/SQL boolean, create a stored procedure that takes a character or number from JDBC and passes it to the original procedure as BOOLEAN or, for an output parameter, accepts a BOOLEAN argument from the original procedure and passes it as a CHAR or NUMBER to JDBC. Similarly, to wrap a stored procedure that uses PL/SQL records, create a stored procedure that handles a record in its individual components, such as CHAR and NUMBER, or in a structured object type. To wrap a stored procedure that uses PL/SQL tables, break the data into components or perhaps use Oracle collection types.
See:
http://download-east.oracle.com/docs/cd/B19306_01/java.102/b14355/apxref.htm#sthref2105 -
Huge memory leaks in using PL/SQL tables and collections
I have faced a very interesting problem recently.
I use PL/SQL tables ( Type TTab is table of ... index by binary_integer; ) and collections ( Type TTab is table of ...; ) in my packages very widely. And have noticed avery strange thing Oracle does. It seems to me that there are memory leaks in PGA when I use PL/SQL tables or collections. Let me a little example.
CREATE OR REPLACE PACKAGE rds_mdt_test IS
TYPE TNumberList IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
PROCEDURE test_plsql_table(cnt INTEGER);
END rds_mdt_test;
CREATE OR REPLACE PACKAGE BODY rds_mdt_test IS
PROCEDURE test_plsql_table(cnt INTEGER) IS
x TNumberList;
BEGIN
FOR indx IN 1 .. cnt LOOP
x(indx) := indx;
END LOOP;
END;
END rds_mdt_test;
I run the following test code:
BEGIN
rds_mdt_test.test_plsql_table (1000000);
END;
and see that my session uses about 40M in PGA.
If I repeat this example in the same session creating the PL/SQL table of smaller size, for instance:
BEGIN
rds_mdt_test.test_plsql_table (1);
END;
I see again that the size of used memory in PGA by my session was not decreased and still be the same.
The same result I get if I use not PL/SQL tables, but collections or varrays.
I have tried some techniques to make Oracle to free the memory, for instance to rewrite my procedure in the following ways:
PROCEDURE test_plsql_table(cnt INTEGER) IS
x TNumberList;
BEGIN
FOR indx IN 1 .. cnt LOOP
x(indx) := indx;
END LOOP;
x.DELETE;
END;
or
PROCEDURE test_plsql_table(cnt INTEGER) IS
x TNumberList;
BEGIN
FOR indx IN 1 .. cnt LOOP
x(indx) := indx;
END LOOP;
FOR indx in 1 .. cnt LOOP
x.DELETE(indx);
END LOOP;
END;
or
PROCEDURE test_plsql_table(cnt INTEGER) IS
x TNumberList;
empty TNumberList;
BEGIN
FOR indx IN 1 .. cnt LOOP
x(indx) := indx;
END LOOP;
x := empty;
END;
and so on, but result was the same.
This is a huge problem for me as I have to manipulate collections and PL/SQL tables of very big size (from dozens of thousand of rows to millions or rows) and just a few sessions running my procedure may cause server's fall due to memory lack.
I can not understand what Oracle reseveres such much memory for (I use local variables) -- is it a bug or a feature?
I will be appreciated for any help.
I use Oracle9.2.0.1.0 server under Windows2000.
Thank you in advance.
Dmitriy.Thank you, William!
Your advice about using DBMS_SESSION.FREE_UNUSED_USER_MEMORY was very useful. Indeed it is the tool I was looking for.
Now I write my code like this
declare
type TTab is table of ... index binary_integer;
res TTab;
empty_tab TTab;
begin
res(1) := ...;
res := empty_tab;
DBMS_SESSION.FREE_UNUSED_USER_MEMORY;
end;
I use construction "res := empty_tab;" to mark all memory allocated to PL/SQL table as unused according to Tom Kyte's advices. And I could live a hapy life if everything were so easy. Unfortunately, some tests I have done showed that there are some troubles in cleaning complex nested PL/SQL tables indexed by VARCHAR2 which I use in my current project.
Let me another example.
CREATE OR REPLACE PACKAGE rds_mdt_test IS
TYPE TTab0 IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
TYPE TRec1 IS RECORD(
NAME VARCHAR2(4000),
rows TTab0);
TYPE TTab1 IS TABLE OF TRec1 INDEX BY BINARY_INTEGER;
TYPE TRec2 IS RECORD(
NAME VARCHAR2(4000),
rows TTab1);
TYPE TTab2 IS TABLE OF TRec2 INDEX BY BINARY_INTEGER;
TYPE TStrTab IS TABLE OF NUMBER INDEX BY VARCHAR2(256);
PROCEDURE test_plsql_table(cnt INTEGER);
PROCEDURE test_str_tab(cnt INTEGER);
x TTab2;
empty_tab2 TTab2;
empty_tab1 TTab1;
empty_tab0 TTab0;
str_tab TStrTab;
empty_str_tab TStrTab;
END rds_mdt_test;
CREATE OR REPLACE PACKAGE BODY rds_mdt_test IS
PROCEDURE test_plsql_table(cnt INTEGER) IS
BEGIN
FOR indx1 IN 1 .. cnt LOOP
FOR indx2 IN 1 .. cnt LOOP
FOR indx3 IN 1 .. cnt LOOP
x(indx1) .rows(indx2) .rows(indx3) := indx1;
END LOOP;
END LOOP;
END LOOP;
x := empty_tab2;
dbms_session.free_unused_user_memory;
END;
PROCEDURE test_str_tab(cnt INTEGER) IS
BEGIN
FOR indx IN 1 .. cnt LOOP
str_tab(indx) := indx;
END LOOP;
str_tab := empty_str_tab;
dbms_session.free_unused_user_memory;
END;
END rds_mdt_test;
1. Running the script
BEGIN
rds_mdt_test.test_plsql_table ( 100 );
END;
I see that usage of PGA memory in my session is close to zero. So, I can judge that nested PL/SQL table indexed by BINARY_INTEGER and the memory allocated to it were cleaned successfully.
2. Running the script
BEGIN
rds_mdt_test.test_str_tab ( 1000000 );
END;
I can see that plain PL/SQL table indexed by VARCHAR2 and memory allocated to it were cleaned also.
3. Changing the package's type
TYPE TTab2 IS TABLE OF TRec2 INDEX BY VARCHAR2(256);
and running the script
BEGIN
rds_mdt_test.test_plsql_table ( 100 );
END;
I see that my session uses about 62M in PGA. If I run this script twice, the memory usage is doubled and so on.
The same result I get if I rewrite not highest, but middle PL/SQL type:
TYPE TTab1 IS TABLE OF TRec1 INDEX BY VARCHAR2(256);
And only if I change the third, most nested type:
TYPE TTab0 IS TABLE OF NUMBER INDEX BY VARCHAR2(256);
I get the desired result -- all memory was returned to OS.
So, as far as I can judge, in some cases Oracle does not clean complex PL/SQL tables indexed by VARCHAR2.
Is it true or not? Perhaps there are some features in using such way indexed tables? -
Bulk loading BLOBs using PL/SQL - is it possible?
Hi -
Does anyone have a good reference article or example of how I can bulk load BLOBs (videos, images, audio, office docs/pdf) into the database using PL/SQL?
Every example I've ever seen in PL/SQL for loading BLOBs does a commit; after each file loaded ... which doesn't seem very scalable.
Can we pass in an array of BLOBs from the application, into PL/SQL and loop through that array and then issue a commit after the loop terminates?
Any advice or help is appreciated. Thanks
LJIt is easy enough to modify the example to commit every N files. If you are loading large amounts of media, I think that you will find that the time to load the media is far greater than the time spent in SQL statements doing inserts or retrieves. Thus, I would not expect to see any significant benefit to changing the example to use PL/SQL collection types in order to do bulk row operations.
If your goal is high performance bulk load of binary content then I would suggest that you look to use Sqlldr. A PL/SQL program loading from BFILEs is limited to loading files that are accessible from the database server file system. Sqlldr can do this but it can also load data from a remote client. Sqlldr has parameters to control batching of operations.
See section 7.3 of the Oracle Multimedia DICOM Developer's Guide for the example Loading DICOM Content Using the SQL*Loader Utility. You will need to adapt this example to the other Multimedia objects (ORDImage, ORDAudio .. etc) but the basic concepts are the same.
Once the binary content is loaded into the database, you will need a to write a program to loop over the new content and initialize the Multimedia objects (extract attributes). The example in 7.3 contains a sample program that does this for the ORDDicom object. -
Pl/sql record - Memory usage
Hi ,
I'm using pl/sql record which hold 14,00,000 rows and process those rows one by one. Will this create memory problem in prodution?
Here is the status of v$process
SELECT spid, program,
pga_max_mem max,
pga_alloc_mem alloc,
pga_used_mem used,
pga_freeable_mem free
FROM V$PROCESS
WHERE addr='070000004DF60B18'
SPID PROGRAM MAX ALLOC USED FREE
2326748 oracleax010 9629198358 9629132822 3623509662 5832704
Thanks for your help!
kannan
Edited by: user601042 on Sep 22, 2010 12:43 AMActually in our design Global Temp table is not allowed..earlier each time we read data from table(14,00,000 rows one by one) and process those rows..This look long time for job to run. instead of that using bulk collect i'm collecting all 14,00,000 rows into collection(10000 rows each collect) and processing rows from collection and this reduced my process time to 1/5 of earlier. But its taking more memory..
Used memory is 3GB ..Do we need to conside allocated momory or used memory?.If used memory is 3GB means fine?
Thanks,
kannan
Maybe you are looking for
-
How can I get my delete key to work as a delete key in Windows?
When I try to control-alt-delete in order to log onto my computer profile, using only my MacBook Pro keyboard, Windows thinks that the delete key is a backspace key and will not let give me access to the login screen. If I connect an external keyboar
-
Hey guys.. I recently had a computer crap out on me and lost everything. Luckily i save all my raw files to my external. I am trying to add the old photos to the lightroom catalog but would like all my adjustments to show up (i.e. how I originally
-
I purchased me the T1i for Christmas and downloaded the software for it off canon's website. Well after the install it tells me: Installation was stopped. Some of the programs may not work properly. Please try reinstalling the software. Well I checke
-
Adobe Muse Type Error: #1009
I have just bought single app subscription - Adobe Muse. But during use I get constantly this error. Man what is going on? Pretty bad that I have paid for the app and now can't use it :/
-
We gave basically a data mining application that can do unions over 12 dozen tables. If figures out what joins to do based on the columns being returned and the columns being searched on. So the user uses the UI in java to specify what data they want