PIPELINE function in oracle
Hi,
Can any body tells when to use PIPELINE function in simple words.
Thanks,
Vinod
910575 wrote:
Can any body tells when to use PIPELINE function in simple words.Wrong question.
Correct question - WHAT is a pipeline table function.
If you understand WHAT it is, you will be able to determine WHEN to use it.
So have you read the documentation? Tried coding your own pipeline function? Do you understand what it is and how it works?
Similar Messages
-
How do you pass parameters to a Pipelined function?
I am using Oracle 10G and the ODP .NET 32 bit client.
I am facing an issue trying to use variable binding with a pipeline function in Oracle. I am using ODP .NET for connecting to the database.
If you want to be familiar with PIPELINED functions, you can read [this blog.|http://oradim.blogspot.com/2007/10/odpnet-tip-using-pipelined-functions.html]
I have very similar code with a difference. My function takes in two parameters that I need to pass to get the table. This is working in SQLPLUS without any issues.
In my C# code, however things change. My function no longer returns a recordset (data reader), if I use the standard method of assigning the parameters.
The code will work if I concat the variables in a string.
Here is the example that doesn't work.
static OracleDataReader fetchData(OracleConnection oc, string strPONumber)
try
OracleCommand od = oc.CreateCommand();
od.CommandType = System.Data.CommandType.Text;
od.CommandText = "select * from table(pkg_fetchPOInfo.getPORowsTable(:1,:2))";
OracleParameter op1 = new OracleParameter();
op1.ParameterName = "1";
op1.OracleDbType = OracleDbType.Varchar2;
op1.Direction = System.Data.ParameterDirection.Input;
op1.Size = 7;
op1.Value = strPONumber;
od.Parameters.Add(op1);
OracleParameter op2 = new OracleParameter();
op2.ParameterName = "2";
op2.OracleDbType = OracleDbType.Varchar2;
op2.Direction = System.Data.ParameterDirection.Input;
op2.Size = 3;
op2.Value = "US";
od.Parameters.Add(op2);
OracleDataReader or = od.ExecuteReader();
return or;
catch (Exception e)
Console.WriteLine("Error " + e.ToString());
return null;
}Here is the example that does.
static OracleDataReader fetchData(OracleConnection oc, string strPONumber)
try
OracleCommand od = oc.CreateCommand();
string formSQL = "Select * from table(pkg_fetchPOInfo.getPORowsTable('"+strPONumber+"','US'))";
od.CommandType = System.Data.CommandType.Text;
od.CommandText = formSQL;
OracleDataReader or = od.ExecuteReader();
return or;
catch (Exception e)
Console.WriteLine("Error " + e.ToString());
return null;
}throw it into an anonymous block and it should work for you.
--create or replace type varcharTableType as table of varchar2 (4000);
create or replace
PACKAGE TESTP AS
function TESTPIPE(nr in number, nr2 in number) return varchartabletype pipelined;
END TESTP;
CREATE OR REPLACE
PACKAGE BODY TESTP AS
function TESTPIPE(nr in number, nr2 in number) return varchartabletype pipelined AS
CURSOR TESTPIPE_cur
IS
SELECT (level + 1) datam
FROM dual
connect by level < nr;
vtt varchartabletype ;
BEGIN
OPEN TESTPIPE_cur;
LOOP
FETCH testpipe_cur
BULK COLLECT INTO vtt LIMIT nr2;
FOR indx IN 1 .. vtt.COUNT
LOOP
Pipe Row ( vtt( indx ) ) ;
END LOOP;
EXIT WHEN testpipe_cur%NOTFOUND;
END LOOP;
END TESTPIPE;
END TESTP;
public static void pipeTest()
String conString = GetConnectionString();
OracleConnection _conn = new OracleConnection(conString);
_conn.Open();
OracleCommand oCmd = new OracleCommand();
oCmd.CommandText = "begin open :crs for Select * from table(testp.testpipe(:nr,:nr2)); end;";
oCmd.CommandType = CommandType.Text ;
oCmd.Connection = _conn;
OracleParameter crs = new OracleParameter();
crs.OracleDbType = OracleDbType.RefCursor;
crs.Direction = ParameterDirection.Output;
crs.ParameterName = "crs";
oCmd.Parameters.Add(crs);
OracleParameter nr = new OracleParameter();
nr.OracleDbType = OracleDbType.Int64;
nr.Direction = ParameterDirection.Input ;
nr.ParameterName = "nr";
nr.Value = 25;
oCmd.Parameters.Add(nr);
OracleParameter nr2 = new OracleParameter();
nr2.OracleDbType = OracleDbType.Int64;
nr2.Direction = ParameterDirection.Input;
nr2.ParameterName = "nr2";
nr2.Value = 10;
oCmd.Parameters.Add(nr2);
using (OracleDataReader MyReader = oCmd.ExecuteReader())
int ColumnCount = MyReader.FieldCount;
// get the data and add the row
while (MyReader.Read())
String s = MyReader.GetOracleValue(0).ToString();
Console.WriteLine(string.Format("i={0}", s));
Console.ReadLine();
} -
Hi,
Can any one please provide me a good example to try out pipelined function in oracle pl/sql ?
ThanksI'm curious. In your biography you state "I am a software programmer working in IT field from last 7-8 years. I am a OCP in Application Development Track"
So how come that you are not familiar with Oracle Documentation and it's full text search capability, which would have given you a reference, such as this?
C. -
dear friends.
can anyone explain about Pipeline function in oracle.
if possible please explain with some small example.
--RajnishThe first rule of the forum states
When asking a question, provide all the details that someone would need to answer it. Consulting documentation first is highly recommended.The first rows of the chapter in the manual say
Streaming, pipelining, and parallel execution of table functions can improve performance:
By enabling multithreaded, concurrent execution of table functions
By eliminating intermediate staging between processes
By improving query response time: With non-pipelined table functions, the entire collection returned by a table function must be constructed and returned to the server before the query can return a single result row. Pipelining enables rows to be returned iteratively, as they are produced. This also reduces the memory that a table function requires, as the object cache does not need to materialize the entire collection.
By iteratively providing result rows from the collection returned by a table function as the rows are produced instead of waiting until the entire collection is staged in tables or memory and then returning the entire collectionI know the second rule of the forum also states
When answering a question, please be courteous; there are different levels of experience represented here. A poorly worded question is better ignored than flamed - or better yet, help the poster ask a better question.But I can't stand after people that just pretend to have everything quickly done and ready. That's why I told you what I said and to "Read The Manual", witch is not an insult. You had your answers, many members told you to learn it on the docs: the subject is not simple and it can't be explained with a simple and limited random example, you need to read the documentation to know it, otherwise you'll go nowhere.
Everyone else already did it to reach a good level of understanding about it and you'll have to do it too, if you want it.
Bye Alessandro -
Hi!
I have a problem with List View Report in mobile application (theme 50 in apex) after updating to apex 4.2.2. I created Report -> List View. I used select from pipelined function in Region Source. Then when page is running and submited three times (or refreshed three times) I get an error:
Error during rendering of region "LIST VIEW".
ORA-01007: variable not in select list
Technical Info (only visible for developers)
is_internal_error: true
apex_error_code: APEX.REGION.UNHANDLED_ERROR
ora_sqlcode: -1007
ora_sqlerrm: ORA-01007: variable not in select list
component.type: APEX_APPLICATION_PAGE_REGIONS
component.id: 21230833903737364557
component.name: LIST VIEW
error_backtrace:
ORA-06512: at "APEX_040200.WWV_FLOW_DISP_PAGE_PLUGS", line 4613
ORA-06512: at "APEX_040200.WWV_FLOW_DISP_PAGE_PLUGS", line 3220
I get this error only when I use select from pipelined function in Region Source (for example: "select value1, value2 from table(some_pipelined_function(param1, param2)) ").
You can check it on http://apex.oracle.com/pls/apex/f?p=50591 (login - demo, password - demo).
In this application:
- I created package TAB_TYPES_PKG:
create or replace PACKAGE TAB_TYPES_PKG IS
TYPE cur_rest_r IS RECORD (
STR_NAME VARCHAR2(128),
INFO VARCHAR2(128)
TYPE cur_rest_t IS TABLE OF cur_rest_r;
END TAB_TYPES_PKG;
- I created pipelined function TEST_FUNC:
create or replace
FUNCTION TEST_FUNC
RETURN TAB_TYPES_PKG.cur_rest_t PIPELINED IS
r_cur_rest TAB_TYPES_PKG.cur_rest_r;
BEGIN
r_cur_rest.STR_NAME := 'ROW 1';
r_cur_rest.INFO := '10';
PIPE ROW (r_cur_rest);
r_cur_rest.STR_NAME := 'ROW 2';
r_cur_rest.INFO := '20';
PIPE ROW (r_cur_rest);
r_cur_rest.STR_NAME := 'ROW 3';
r_cur_rest.INFO := '30';
PIPE ROW (r_cur_rest);
r_cur_rest.STR_NAME := 'ROW 4';
r_cur_rest.INFO := '40';
PIPE ROW (r_cur_rest);
r_cur_rest.STR_NAME := 'ROW 5';
r_cur_rest.INFO := '50';
PIPE ROW (r_cur_rest);
RETURN;
END TEST_FUNC;
- I created List View Report on Page 1:
Region Source:
SELECT str_name,
info
FROM TABLE (TEST_FUNC)
We can see error ORA-01007 after refresing (or submiting) Page 1 three times or more.
How to fix it?Hi all
I'm experiencing the same issue. Predictably on every third refresh I receive:
Error
Error during rendering of region "Results".
ORA-01007: variable not in select list
Technical Info (only visible for developers)
is_internal_error: true
apex_error_code: APEX.REGION.UNHANDLED_ERROR
ora_sqlcode: -1007
ora_sqlerrm: ORA-01007: variable not in select list
component.type: APEX_APPLICATION_PAGE_REGIONS
component.id: 6910805644140264
component.name: Results
error_backtrace: ORA-06512: at "APEX_040200.WWV_FLOW_DISP_PAGE_PLUGS", line 4613 ORA-06512: at "APEX_040200.WWV_FLOW_DISP_PAGE_PLUGS", line 3220
OK
I am running Application Express 4.2.2.00.11 on GlassFish 4 using Apex Listener 2.0.3.221.10.13.
Please note: this works perfectly using a classic report in my desktop application; however, no joy on the mobile side with a list view. I will use a classic report in the interim.
My region source is as follows:
SELECT description AS "DESCRIPTION", reference AS "REFERENCE" FROM TABLE(AUTOCOMPLETE_LIST_VIEW_FNC('RESULTS'))
The procedure:
FUNCTION AUTOCOMPLETE_LIST_VIEW_FNC(
p_collection_name IN VARCHAR2)
RETURN list_row_table_type
AS
v_tab list_row_table_type := list_row_table_type();
BEGIN
DECLARE
jsonarray json_list;
jsonobj json;
json_clob CLOB;
BEGIN
SELECT clob001
INTO json_clob
FROM apex_collections
WHERE collection_name = p_collection_name;
jsonobj := json(json_clob);
jsonarray := json_ext.get_json_list(jsonobj, 'predictions');
FOR i IN 1..jsonArray.count
LOOP
jsonobj := json(jsonArray.get(i));
v_tab.extend;
v_tab(v_tab.LAST) := list_row_type(json_ext.get_string(jsonobj, 'description'), json_ext.get_string(jsonobj, 'reference'));
END LOOP;
RETURN(v_tab);
END;
END AUTOCOMPLETE_LIST_VIEW_FNC;
Thanks!
Tim -
Pipelined function in reports6i....1
Hi,
i have a problem with using pipelined function in
reports6i.
can i use pipelined function in reports6i.
The following code is used to return rows
based on the parameter i am passing:
my package declaration and body is as follows:
PACKAGE P_RET_ARRAY IS
TYPE array1 AS TABLE OF NUMBER;
FUNCTION ret_array(str VARCHAR2)
RETURN ARRAY1 PIPELINED;
END;
PACKAGE BODY P_RET_ARRAY IS
FUNCTION ret_array(str VARCHAR2)
RETURN ARRAY1 pipelined
IS
str1 VARCHAR2(100);
num1 NUMBER(5);
BEGIN
str1 := str ||',';
WHILE LENGTH(str1)>=0
LOOP
num1 := TO_NUMBER(SUBSTR(str1,1,INSTR(str1,',',1)-1));
pipe (num1);
str1 := SUBSTR(str1,INSTR(str1,',',1)+1);
END LOOP;
--NULL;
RETURN ;
END;
END;
I got the above piece of code from one of the oracle forums:
now if i am trying to use this code in my reports6i it's not recognizing
pipelined.any suggestions plz .
it's urgent....Hi,
i have a problem with using pipelined function in
reports6i.
can i use pipelined function in reports6i.
The following code is used to return rows
based on the parameter i am passing:
my package declaration and body is as follows:
PACKAGE P_RET_ARRAY IS
TYPE array1 AS TABLE OF NUMBER;
FUNCTION ret_array(str VARCHAR2)
RETURN ARRAY1 PIPELINED;
END;
PACKAGE BODY P_RET_ARRAY IS
FUNCTION ret_array(str VARCHAR2)
RETURN ARRAY1 pipelined
IS
str1 VARCHAR2(100);
num1 NUMBER(5);
BEGIN
str1 := str ||',';
WHILE LENGTH(str1)>=0
LOOP
num1 := TO_NUMBER(SUBSTR(str1,1,INSTR(str1,',',1)-1));
pipe (num1);
str1 := SUBSTR(str1,INSTR(str1,',',1)+1);
END LOOP;
--NULL;
RETURN ;
END;
END;
I got the above piece of code from one of the oracle forums:
now if i am trying to use this code in my reports6i it's not recognizing
pipelined.any suggestions plz .
it's urgent.... -
Turning sql string (with dynamic columns) into a pipelined function
Hi guys,
I was working on an apex report the other day, and wrote the sql below (for those who don't know apex well, in an apex report you can define the columns at runtime.) When I was finished, I said to myself: "It would be great to have a pipeline function with this capability." So, the idea would be to have a sql string where the columns are created dynamically, depending on input parameters - and then be able to use this sql everywhere (oracle reports, sqlplus) through a pipelined function.
Here's the sql (simplified, of course, the data itself is actually not important - the LOOP is the key)
declare
v_sql varchar2(4000);
begin
v_sql := 'select client, ';
for i in (select employee from company_employees_view where condition = pi_parameter order by 1) loop
v_sql := v_sql || sum(decode(employee,''' || i.employee || ''', total)) "' || i.employee || '"';
end loop;
v_sql := v_sql || ', sum(total) "Total"';
v_sql := v_sql || ' from company_employees_view group by client';
end;
This sql would result in a final product like:
select client
, sum(decode(employee,'John',total) "John"
, sum(decode(employee,'Paul',total) "Paul"
, sum(decode(employee,'George',total) "George"
(and so on... this sql could have more or less columns depending on the input parameters of the function)
from company_employees_view
group by client;
I have tried feeding this sql into a ref cursor and an object, but always received an "inconsistent datatypes" message.
The object would be something like:
create or replace object rt_employee as (total number);
create or replace tt_employee as table of rt_employee;
create or replace object rt_client as (
client varchar2(100),
employee tt_employee);
create or replace tt_client as table of rt_client;
(I am not paying too much attention to syntax here.)
By the way, no hurry whatsoever, this is just for fun, take your time. I am using database XE with apex 2.1 and sql developer 1.2.
Thanks, RogerThis is the only solution I've ever seen to dynamic pipelined columns...
How to pipeline a function with a dynamic number of columns? -
Pass multiple values as single input parameter into pipelined function
Hi all,
My need is to pass multiple values as single input parameter into pipelined function.
For example - "2" and "3" are values of input parameter "t":
with data as (
select 1 as t from dual union all
select 2 as t from dual union all
select 3 as t from dual union all
select 4 as t from dual union all
select 5 as t from dual
select * from data where t in (2,3)Is it possible at all?Not exactly sure, but usually 'multiple values'+'pipelined function' = some IN-LIST related approach?
See:
SQL> create table data as
2 select 1 as t from dual union all
3 select 2 as t from dual union all
4 select 3 as t from dual union all
5 select 4 as t from dual union all
6 select 5 as t from dual;
Table created.
SQL> --
SQL> CREATE OR REPLACE FUNCTION in_list (p_in_list IN VARCHAR2)
2 RETURN sys.odcivarchar2list PIPELINED
3 AS
4 l_text VARCHAR2(32767) := p_in_list || ',';
5 l_idx NUMBER;
6 BEGIN
7 LOOP
8 l_idx := INSTR(l_text, ',');
9 EXIT WHEN NVL(l_idx, 0) = 0;
10 PIPE ROW (TRIM(SUBSTR(l_text, 1, l_idx - 1)));
11 l_text := SUBSTR(l_text, l_idx + 1);
12 END LOOP;
13
14 RETURN;
15 END;
16 /
Function created.
SQL> --
SQL> select *
2 from data
3 where t in ( select *
4 from table(in_list('1,2'))
5 );
T
1
2
2 rows selected.http://www.oracle-base.com/articles/misc/dynamic-in-lists.php
or
http://tkyte.blogspot.nl/2006/06/varying-in-lists.html -
PLS-00630: pipelined functions must have a supported collection return type
Hello, I created an TYPE of OBJECT and a PLSQL Function as shown below, but the function compilation errors with following. Not sure where is the issue?
PLS-00630: pipelined functions must have a supported collection return typeThis is on Oracle 10g r2
CREATE OR REPLACE TYPE cxs_plsql_profiler_object_type AS OBJECT (
cxs_object_name VARCHAR2 (128),
cxs_object_type VARCHAR2 (19),
cxs_object_status VARCHAR2 (7),
cxs_read_execution NUMBER,
cxs_buffer_gets NUMBER,
cxs_disk_reads NUMBER,
cxs_executions NUMBER,
cxs_sorts NUMBER,
cxs_sharable_mem NUMBER,
cxs_address NUMBER,
cxs_hashvalue NUMBER,
cxs_osuser VARCHAR2 (30),
cxs_username VARCHAR2 (30),
cxs_module VARCHAR2 (48),
cxs_machine VARCHAR2 (64),
cxs_status VARCHAR2 (8),
cxs_terminal VARCHAR2 (16),
cxs_percentconsume NUMBER,
cxs_percentrepeat NUMBER,
cxs_plan VARCHAR2 (120),
target_name VARCHAR2 (200),
referenced_name VARCHAR2 (200),
referenced_type VARCHAR2 (200),
targetowner VARCHAR2 (200),
refowner VARCHAR2 (200)
)and here is the API
FUNCTION CXS_GENERATE_PLSQL_PROFILER
RETURN cxs_plsql_profiler_object_type
PIPELINED IS
out_rec cxs_plsql_profiler_object_type ;
plsbatch plsql_batch;
skount integer;
dpendrec depend_tab;
dkount integer;
CURSOR objects
IS
SELECT object_name, object_type
FROM dba_objects
WHERE status = 'VALID'
AND owner NOT IN ('SYS', 'SYSTEM')
AND object_type IN ('PACKAGE', 'PROCEDURE', 'FUNCTION');
CURSOR apis (p_object dba_objects.object_name%TYPE)
IS
SELECT DISTINCT *
FROM (SELECT SUBSTR (a.sql_text, 1, 50) sql_text,
TRUNC
( a.disk_reads
/ DECODE (a.executions,
0, 1,
a.executions
) reads_per_execution,
a.buffer_gets, a.disk_reads, a.executions,
a.sorts, a.sharable_mem, a.address,
a.hash_value, b.osuser, b.username,
b.module, b.machine, b.status, b.terminal,
ROUND
(cxs_db_info.kompute_percentofsql
(a.sharable_mem),
5
) percentkonsume,
cxs_db_info.kount_repeat
(b.osuser,
b.terminal
) percentr,
c.operation explainplan
FROM v$sqlarea a, v$session b, v$sql_plan c
WHERE b.sql_hash_value = a.hash_value
AND b.sql_address = a.address
AND a.hash_value = c.hash_value
AND a.address = c.address
AND b.status = 'ACTIVE'
AND UPPER (a.sql_text) LIKE
'%' || p_object || '%'
AND c.ID = 0
ORDER BY 2 DESC)
WHERE ROWNUM <= 50; --profile option
BEGIN
skount := 0;
dkount := 0;
FOR i IN objects
LOOP
FOR j IN apis (i.object_name)
LOOP
skount := skount + 1;
plsbatch(skount).cxs_object_name := i.object_name;
plsbatch(skount).cxs_object_type := i.object_type;
plsbatch(skount).cxs_object_status := i.object_status;
plsbatch(skount).cxs_read_execution := j.reads_per_execution;
plsbatch(skount).cxs_buffer_gets := j.buffer_gets;
plsbatch(skount).cxs_disk_reads := j.disk_reads;
plsbatch(skount).cxs_executions := j.executions;
plsbatch(skount).cxs_sorts := j.sorts;
plsbatch(skount).cxs_sharable_mem := j.sharable_mem;
plsbatch(skount).cxs_address := j.address;
plsbatch(skount).cxs_hashvalue := j.hashvalue;
plsbatch(skount).cxs_osuser := j.osuser;
plsbatch(skount).cxs_username := j.username;
plsbatch(skount).cxs_module := j.module;
plsbatch(skount).cxs_machine := j.machine;
plsbatch(skount).cxs_status := j.status;
plsbatch(skount).cxs_terminal := j.terminal;
plsbatch(skount).cxs_percentconsume := j.percentconsume;
plsbatch(skount).cxs_percentrepeat := j.percentrepeat;
plsbatch(skount).cxs_plan := j.explainplan;
END LOOP;
FOR dd IN dpend (i.object_name)
LOOP
dkount := dkount + 1;
dependrec (dkount).target_name := dd.NAME;
dependrec (dkount).refname := dd.referenced_name;
dependrec (dkount).reftype := dd.referenced_type;
dependrec (dkount).target_owner := dd.owner;
dependrec (dkount).refowner := dd.referenced_owner;
END LOOP;
END LOOP;
for a in 1..skount loop
out_rec.cxs_object_type := plsbatch(a).object_type;
out_rec.cxs_object_status := plsbatch(a).object_status;
out_rec.cxs_read_execution := plsbatch(a).reads_per_execution;
out_rec.cxs_buffer_gets := plsbatch(a).buffer_gets;
out_rec.cxs_disk_reads := plsbatch(a).disk_reads;
out_rec.cxs_executions := plsbatch(a).executions;
out_rec.cxs_sorts := plsbatch(a).sorts;
out_rec.cxs_sharable_mem := plsbatch(a).sharable_mem;
out_rec.cxs_address := plsbatch(a).address;
out_rec.cxs_hashvalue := plsbatch(a).hashvalue;
out_rec.cxs_osuser := plsbatch(a).osuser;
out_rec.cxs_username := plsbatch(a).username;
out_rec.cxs_module := plsbatch(a).module;
out_rec.cxs_machine := plsbatch(a).machine;
out_rec.cxs_status := plsbatch(a).status;
out_rec.cxs_terminal := plsbatch(a).terminal;
out_rec.cxs_percentconsume := plsbatch(a).percentconsume;
out_rec.cxs_percentrepeat := plsbatch(a).percentrepeat;
out_rec.cxs_plan := plsbatch(a).explainplan;
PIPE ROW(out_rec);
end loop;
for b in 1..dkount loop
out_rec.target_name := dd.NAME;
out_rec.refname := dependrec (b).referenced_name;
out_rec.reftype := dependrec (b).referenced_type;
out_rec.target_owner := dependrec (b).owner;
out_rec.refowner := dependrec (b).referenced_owner;
PIPE ROW(out_rec);
end loop;
RETURN;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(DBMS_UTILITY.format_error_backtrace);
DBMS_OUTPUT.PUT_LINE(SQLCODE);
DBMS_OUTPUT.PUT_LINE(SQLERRM);
END; and below are tradtional table types that are used in code above.
TYPE type_plsql_rec IS RECORD (
cxs_object_name VARCHAR2 (128),
cxs_object_type VARCHAR2 (19),
cxs_object_status VARCHAR2 (7),
cxs_read_execution NUMBER,
cxs_buffer_gets NUMBER,
cxs_disk_reads NUMBER,
cxs_executions NUMBER,
cxs_sorts NUMBER,
cxs_sharable_mem NUMBER,
cxs_address NUMBER,
cxs_hashvalue NUMBER,
cxs_osuser VARCHAR2 (30),
cxs_username VARCHAR2 (30),
cxs_module VARCHAR2 (48),
cxs_machine VARCHAR2 (64),
cxs_status VARCHAR2 (8),
cxs_terminal VARCHAR2 (16),
cxs_percentconsume NUMBER,
cxs_percentrepeat NUMBER,
cxs_plan VARCHAR2 (120)
TYPE plsql_batch IS TABLE OF type_plsql_rec
INDEX BY BINARY_INTEGER;
TYPE type_depend_tab IS RECORD (
target_name dba_dependencies.NAME%TYPE,
refname dba_dependencies.referenced_name%TYPE,
reftype dba_dependencies.referenced_type%TYPE,
target_owner dba_dependencies.owner%TYPE,
refowner dba_dependencies.referenced_owner%TYPE
TYPE depend_tab IS TABLE OF type_depend_tab
INDEX BY BINARY_INTEGER;
Thank you for your time in reading this post
RThank you Billy and Saubhik,
I have followed your guidelines and was able to resolve this error. Now, after successfully compiling the code, I attempted to execute it in a following way.
SELECT * FROM TABLE (cxs_generate_plsql_profiler);It gives following error: ORA-00904: "CXS_GENERATE_PLSQL_PROFILER": invalid identifier
I also tried putting in quotes like below
SELECT * FROM TABLE ('cxs_generate_plsql_profiler');Then, it gives following error:
ORA-22905: cannot access rows from a non-nested table item
Any Idea where I am doing wrong?
Thanks,
R -
PL/SQL Pipelined Function to Compare *ANY* 2 tables
I am trying to create a pipelined function in 10g R1 that will take the name of two tables, compare the the tables using dynamic SQL and pipe out the resulting rows using the appropriate row type. The pipelined function will be used in a DML insert statement.
For example:
create table a (f1 number, f2, date, f3 varchar2);
create table b (f1 number, f2, date, f3 varchar2);
create table c (f1 number, f2, date, f3 varchar2);
create or replace TYPE AnyCollTyp IS TABLE OF ANYTYPE;
create or replace TYPE CRowType IS c%ROWTYPE;
create or replace TYPE CRowTabType IS table of CRowType;
CREATE OR REPLACE FUNCTION compareTables (p_source IN VARCHAR2, p_dest IN VARCHAR2)
RETURN AnyCollTyp PIPELINED
IS
CURSOR columnCur (p_tableName IN user_tab_columns.table_name%TYPE)
IS
SELECT column_name, column_id
FROM user_tab_columns
WHERE table_name = p_tableName
ORDER BY column_id;
l_cur sys_refcursor;
l_rec ANYTYPE;
l_stmt VARCHAR2 (32767);
BEGIN
l_stmt := 'select ';
FOR columnRec IN columnCur (p_dest)
LOOP
l_stmt := l_stmt || CASE
WHEN columnRec.column_id > 1
THEN ','
ELSE ''
END || columnRec.column_name;
END LOOP;
l_stmt := l_stmt || ' from ' || p_source;
l_stmt := l_stmt || ' minus ';
l_stmt := l_stmt || ' select ';
FOR columnRec IN columnCur (p_dest)
LOOP
l_stmt := l_stmt || CASE
WHEN columnRec.column_id > 1
THEN ','
ELSE ''
END || columnRec.column_name;
END LOOP;
l_stmt := l_stmt || ' from ' || p_dest;
OPEN l_cur FOR l_stmt;
LOOP
FETCH l_cur
INTO l_rec;
PIPE ROW (l_rec);
EXIT WHEN l_cur%NOTFOUND;
END LOOP;
CLOSE l_cur;
RETURN;
END compareTables;
The pipelined function gets created without error. However, the testCompare procedure gets an error:
SQL> create or replace procedure testCompare is
begin
insert into c
select *
from (TABLE(CAST(compareTables('a','b') as cRowTabType)));
dbms_output.put_line(SQL%ROWCOUNT || ' rows inserted into c.');
end;
Warning: Procedure created with compilation errors.
SQL> show errors
Errors for PROCEDURE TESTCOMPARE:
LINE/COL ERROR
3/4 PL/SQL: SQL Statement ignored
5/47 PL/SQL: ORA-22800: invalid user-defined type
Does anyone know what I am doing wrong? Is there a better way to compare any two tables and get the resulting rows?904640 wrote:
Hi All,
Is it possible to post messages to weblogic JMS queue from pl/sql procedure/function?
From this Queue, message will be read by OSB interface.
Any help will be highly appreciated.
http://www.lmgtfy.com/?q=oracle+pl/sql+weblogic+jms+queue -
Pipelined function ignores DML changes on subqueries
Hello all,
I have a really specific issue when using a pipelined function used in a complex subquery where the function ignores the changes made on the current transaction. The problem is the hidden hint materialize sometimes used by the Oracle optimizer. I say sometimes because it depends mostly on the execution plan and the complexity of the query.
I can repeat the problem with a dummy scenario.
Let's say we have a dummy table with a simple record :
CREATE TABLE DUMMY ("NAME" VARCHAR2(50 BYTE));
INSERT INTO DUMMY VALUES('Original name');
We then create a package which will contain our pipelined function and its record object and collection:
CREATE OR REPLACE PACKAGE PKG_DUMMY AS
TYPE DUMMY_RECORD IS RECORD (NAME VARCHAR2(50 BYTE));
TYPE DUMMY_RECORDS IS TABLE OF DUMMY_RECORD;
FUNCTION FUNC_GET_DUMMY_NAME RETURN DUMMY_RECORDS PIPELINED;
END PKG_DUMMY;
CREATE OR REPLACE
PACKAGE BODY PKG_DUMMY AS
FUNCTION FUNC_GET_DUMMY_NAME RETURN DUMMY_RECORDS PIPELINED AS
BEGIN
FOR CUR IN ( SELECT * FROM DUMMY )
LOOP
PIPE ROW (CUR);
END LOOP;
END FUNC_GET_DUMMY_NAME;
END PKG_DUMMY;
With this SQL query, we can return the value of the table by the pipelined function :
WITH DUMMY_NAME AS
SELECT "NAME"
FROM TABLE(PKG_DUMMY.FUNC_GET_DUMMY_NAME())
SELECT "NAME"
FROM DUMMY_NAME
Result
Original name
If we modify the DUMMY table with a new name without a commit, and re-execute the query, we got the same result :
UPDATE DUMMY SET "NAME" = 'New name';
Result
New name
But if we add the materialize hint in the subquery (without doing a commit or rollback), we have the original value hence my issue :
WITH DUMMY_NAME AS
SELECT /*+ materialize */ "NAME"
FROM TABLE(PKG_DUMMY.FUNC_GET_DUMMY_NAME())
SELECT "NAME"
FROM DUMMY_NAME
Result
Original name
I know I can force my subquery to use an inline hint instead of the "materialize" hint chose by the optimizer but then the query lose a lot of performance. Is there a way to force Oracle to use current DML changes with the materialize hint on a pipelined funtion in a subquery?
This thread is also for this issue : http://stackoverflow.com/questions/1597467/is-using-a-select-inside-a-pipelined-pl-sql-table-function-allowedHi Eliante, Hi Dominic,
Very Interesting. Here what I can reproduce in Oracle Database 10g Enterprise Edition Release 10.2.0.4.0 - 64bi
sql > truncate table dummy;
Table truncated.
sql >INSERT INTO DUMMY VALUES('Original name');
1 row created.Please pay attention that I didn't commit
sql > with dummy_name as
2 (
3 select "NAME"
4 from table(pkg_dummy.func_get_dummy_name())
5 )
6 select "NAME"
7 from dummy_name;
NAME
Original name
sql> start c:\dispcursor
PLAN_TABLE_OUTPUT
SQL_ID 838mtur4m74j2, child number 0
with dummy_name as ( select "NAME" from table(pkg_dummy.func_get_dummy_name()) ) select "NAME"
from dummy_name
Plan hash value: 117055
| Id | Operation | Name | Starts | A-Rows | A-Time | Buffers |
| 1 | COLLECTION ITERATOR PICKLER FETCH| FUNC_GET_DUMMY_NAME | 1 | 1 |00:00:00.01 | 15 |
Note
- rule based optimizer used (consider using cbo)
17 rows selected.
sql > with dummy_name as
2 (
3 select /*+ materialize */ "NAME"
4 from table(pkg_dummy.func_get_dummy_name())
5 )
6 select "NAME"
7 from dummy_name;
no rows selected
sql >start c:\dispcursor
PLAN_TABLE_OUTPUT
SQL_ID 9frx3wjk992rd, child number 0
with dummy_name as ( select /*+ materialize */ "NAME" from table(pkg_dummy.func_get_dummy_name()) ) select "NAME" from dummy_name
Plan hash value: 1359790764
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers | OMem | 1Mem | Used-Mem |
| 1 | TEMP TABLE TRANSFORMATION | | 1 | | 0 |00:00:00.01 | 20 | | | |
| 2 | LOAD AS SELECT | | 1 | | 0 |00:00:00.01 | 19 | 1024 | 1024 | |
| 3 | COLLECTION ITERATOR PICKLER FETCH| FUNC_GET_DUMMY_NAME | 1 | | 0 |00:00:00.01 | 17 | | | |
| 4 | VIEW | | 1 | 8168 | 0 |00:00:00.01 | 0 | | | |
| 5 | TABLE ACCESS FULL | SYS_TEMP_0FD9D780C_BD7649E3 | 1 | 8168 | 0 |00:00:00.01 | 0 | | | |
16 rows selected.I can point out that the TABLE ACCESS FULL of the global temporary SYS_TEMP_0FD9D780C_BD7649E3 table created by Oracle in response to the -materialize hint is returning *0 rows* in operation 5.
Why?
It seems for me that the reason for that comes from the fact that the creation of this SYS_TEMP_0FD9D780C_BD7649E3 table is done via direct path read/direct path write and as far as
the insert of *'Original name'* has not been pushed yet into the disc then materializing the query will generate an empty temporary table (empty in this case).
This is why if I had committed I will not have seen such a kind of discrepancy between those two queries
What do you think?
Mohamed Houri
www.hourim.wordpress.com -
What exactly is parallelised in pipelined functions?
Hi All,
I have a slight confusion about pipelined table functions, which are parallelised (with PARALLEL_ENABLE clause).
Everywhere on the internet/documents it is mentioned that, we can use PARALLEL_ENABLE with pipelined table functions, I am not clear about exactly how this will work?
For example, I have a pipelines function, which is called by C# code to write data in file ( Oracle v11.2 on Linux 64bit). Function looks something like
FUNCTION extract_data (param1..., param2...., param3.... )
RETURN data_tab /* this data_tab is table of record type data_rec */
PIPELINED
IS
v_data_rec data_rec := data_rec ( null, null,....., null);
BEGIN
FOR i_rec IN ( select col1, col2, col3,.... FROM table1, table2 WHERE <all typical stuff here> )
LOOP
v_data_rec.col1 := i_rec.col1 ;
v_data_rec.col2 := i_rec.col2 ;
v_data_rec.col3 := i_rec.col3 ;
if v_data_rec.col1 = 'A' then
select col into v_data_rec.col4 from tablex where .... ;
elsif v_data_rec.col1 = 'B' then
select col into v_data_rec.col4 from tabley where .... ;
elsif v_data_rec.col1 = 'C' then
select col into v_data_rec.col4 from tablez where .... ;
elsif v_data_rec.col1 = 'D' then
select col into v_data_rec.col4 from tablet where .... ;
end if ;
/* some more bits of complex logic here */
PIPE ROW ( v_data_rec ) ;
END LOOP ;
END extract_data ;Now, if I add PARALLEL_ENABLE to my function definition, which bits will be parallelised? will anything be parallelised ?
Thoughts please.
Thanks in advance.i.e. this ( where the query might well be run in parallel, but the result processed serially by the pipelined function):
SQL> explain plan for
2 select *
3 from table(
4 f_serial_pipe
5 (cursor(select /*+ parallel (t1 4) */
6 *
7 from t1)));
Explained.
SQL>
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
Plan hash value: 1425181138
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
| 0 | SELECT STATEMENT | | 8168 | 1100K| 34 (3)| 00:00:01 |
| 1 | VIEW | | 8168 | 1100K| 34 (3)| 00:00:01 |
| 2 | COLLECTION ITERATOR PICKLER FETCH| F_SERIAL_PIPE | 8168 | | 34 (3)| 00:00:01 |
Note
- dynamic sampling used for this statement (level=4)
13 rows selected.
SQL> is different from thsi:
SQL> explain plan for
2 select *
3 from table(
4 f_parallel_pipe
5 (cursor(select /*+ parallel (t1 4) */
6 *
7 from t1)));
Explained.
SQL>
SQL> select * from table(dbms_xplan.display);
PLAN_TABLE_OUTPUT
Plan hash value: 2029647211
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time | TQ |IN-OUT| PQ Distrib |
| 0 | SELECT STATEMENT | | 8168 | 1100K| 34 (3)| 00:00:01 | | | |
| 1 | PX COORDINATOR | | | | | | | | |
| 2 | PX SEND QC (RANDOM) | :TQ10000 | 8168 | 1100K| 34 (3)| 00:00:01 | Q1,00 | P->S | QC (RAND) |
| 3 | VIEW | | 8168 | 1100K| 34 (3)| 00:00:01 | Q1,00 | PCWP | |
| 4 | COLLECTION ITERATOR PICKLER FETCH| F_PARALLEL_PIPE | 8168 | | 34 (3)| 00:00:01 | Q1,00 | PCWP | |
| 5 | PX BLOCK ITERATOR | | 798K| 97M| 2659 (1)| 00:00:02 | Q1,00 | PCWC | |
| 6 | TABLE ACCESS FULL | T1 | 798K| 97M| 2659 (1)| 00:00:02 | Q1,00 | PCWP | |
Note
- dynamic sampling used for this statement (level=4)
17 rows selected.
SQL> -
What is the role of the RETURN clause in a pipelined function?
I wrote several pipelined functions and they work just fine without the return clause. However in the oracle's documentation there are returns in the pipelined functions:
CREATE FUNCTION StockPivot(p refcur_pkg.refcur_t) RETURN TickerTypeSet
PIPELINED IS
out_rec TickerType := TickerType(NULL,NULL,NULL);
in_rec p%ROWTYPE;
BEGIN
LOOP
FETCH p INTO in_rec;
EXIT WHEN p%NOTFOUND;
-- first row
out_rec.ticker := in_rec.Ticker;
out_rec.PriceType := 'O';
out_rec.price := in_rec.OpenPrice;
PIPE ROW(out_rec);
-- second row
out_rec.PriceType := 'C';
out_rec.Price := in_rec.ClosePrice;
PIPE ROW(out_rec);
END LOOP;
CLOSE p;
RETURN;
END;
/http://docs.oracle.com/cd/E11882_01/appdev.112/e10765/pipe_paral_tbl.htm#CHDJEGHC
Moreover, at least in PL/SQL developer I recieve hints that my pipelined functions return no values, though as I said the functions work smoothly. So is there a need in the return clause in pipelined functions or it is redundant?
My oracle version is 11.2.0.2.0As already mentioned, in later versions of the database it doesn't appear to be necessary, however, it IS good programming practice (and necessary in non-pipelined functions) to always ensure a function has a RETURN statement in it. It could be a 'side effect' (read that as bug if you like) that it doesn't appear to be necessary, so you would be best to ensure you DO include a RETURN statement, as documented.
-
Record vs object vs globle table in pipelined function
i want to make pipeline function , i show it can be made in following ways
please suggest which one is better in performance and maintenance.
1)
create type my_tab_type is object
(prodid number, a varchar2(1), b varchar2(1),
c varchar2(1), d varchar2(1), e varchar2(1))
create type my_tab_type_coll is table of my_tab_type;
create or replace function get_some_data (p_val in number)
return my_tab_type_coll pipelined is
begin
FOR i in (select * from my_table where prodid=p_val) loop
pipe row(my_tab_type(i.prodid,i.a,i.b,i.c,i.d,i.e));
end loop;
return;
end;
SELECT * FROM table(get_Some_Data(3));
2)
one can create globle tem table "Tlb_3". then can make a package like fllowing
create or replace
PACKAGE pk1
AS
TYPE T_type IS TABLE OF Tlb_3%ROWTYPE;
END;
and rest of the thing will be same like first one.
3)
TYPE outrec_typ IS RECORD (
var_num NUMBER(6),
var_char1 VARCHAR2(30),
var_char2 VARCHAR2(30)
TYPE outrecset IS TABLE OF outrec_typ;
and rest of the thing will be same like first one
so main question is relating to declaretion of TABLE which is returned.
yours sincerely
Edited by: 944768 on Jan 2, 2013 4:23 AMDUPLICATE THREAD!
How many times do you intend to ask this question?
This is the same question that you ask, and got answered, six months ago in this thread?
how to write Function returing table or set of rows.
And you ask it again a week ago in this thread
object vs record in pipelined function.
Have you forgotten those answers already? Why didn't you take the advice given there and perform some tests?
And you don't seem to acknowledge any of the help you get to your questions by marking them ANSWERED when they have been.
Please revisit this 32 questions and mark them ANSWERED as appropriate - Total Questions: 73 (32 unresolved)
>
i want to make pipeline function , i show it can be made in following ways
please suggest which one is better in performance and maintenance.
>
Why didn't you take the advice given there and perform some tests?
Option #1, using SQL types is better, especially for maintenance. Also SQL types are required if the function is going to be called from SQL. You can define PL/SQL or %ROWTYPE package variables and use them but Oracle will silently create 'hidden' (in 11g) SQL types and use those.
See Solomon's explanation and sample code in this recent thread
Re: Pipe line function
There certainly isn't any need to create a global temp table just so you can create the %ROWTYPE variable; you can create one of those based on a CURSOR. -
Pipeline functions - what happens under the hood? (10g)
Hi all,
What happens when you call a pipelined function? (As opposed to a plain table-valued function.)
From what I understand, a pipelined function will return rows as they are needed. Let's say I have a really silly example of a pipelined function,
CREATE OR REPLACE PACKAGE BODY TEST_PACKAGE_1
AS
FUNCTION GET_DATA RETURN JUST_A_TABLE PIPELINED
IS
BEGIN
PIPE ROW (JUST_A_TYPE('HELLO'));
PIPE ROW (JUST_A_TYPE('WORLD'));
RETURN;
END;
END TEST_PACKAGE_1;
/Then let's say I were to SELECT * FROM TABLE(TEST_PACKAGE_1.GET_DATA) WHERE ROWNUM = 1, what happens to the second row? Does the code that returns the second row still get educated? (Obviously it's omitted from the query, but does it still get generated somewhere and just go nowhere?)
If I have a cursor on a PL/SQL block that selects from GET_DATA, will each row only be returned as the cursor references it? In that case, what happens to the rows that don't get selected? If there some resource that need to be closed out (say, just before the return statement), would it still be safe to close it out?
Thanks!
DonInteresting question, lets try a simple test and see we'll just take your example function and toss in a few dbms_output statements like so:
CREATE OR REPLACE PACKAGE BODY TEST_PACKAGE_1
AS
FUNCTION GET_DATA RETURN JUST_A_TABLE PIPELINED
IS
BEGIN
dbms_output.put_line('ONE');
PIPE ROW (JUST_A_TYPE('HELLO'));
dbms_output.put_line('TWO');
PIPE ROW (JUST_A_TYPE('WORLD'));
dbms_output.put_line('THREE');
RETURN;
END;
END TEST_PACKAGE_1;Now not forgetting to enable dbms_output call it three times like so:
SELECT * FROM TABLE(TEST_PACKAGE_1.GET_DATA) WHERE ROWNUM = 1;
SELECT * FROM TABLE(TEST_PACKAGE_1.GET_DATA) WHERE ROWNUM <= 2;
SELECT * FROM TABLE(TEST_PACKAGE_1.GET_DATA) WHERE ROWNUM <= 3;What I saw from my test was that with the first call I got 1 row of data from the pipelined function and only the first dbms_output statement was processed. For the second statement I got 2 rows of data from the function and the first two dbms_output statements were processed. For the final call I again got 2 rows of data from the function and all 3 dbms_output statements were processed.
My environment:
Oracle Database 10g Express Edition Release 10.2.0.1.0 - Product
PL/SQL Release 10.2.0.1.0 - Production
"CORE 10.2.0.1.0 Production"
TNS for 32-bit Windows: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 - Production
Maybe you are looking for
-
How to sort on category id using categorization schema in SAP CRM 7.0
All, Currently we are using categorization modeler within CRM7.0 for complaint transactions. It seems that the sortation with respect to the categories which have been defined within a categorization schema, is based on the date that the categories w
-
When will we be able to add free apps to this list? More like a favorite option.
-
How to upload video to YouTube
Have spent 24 hrs trying to figure out why I can't upload video from a brand new 1Phone 5 and iPad OS6 to YouTube. Really apple? help anyone?
-
I have a HP G50-133US notebook, it currently has a Atheros AR5007 802.11b/g WiFi Adapter. I am looking to upgrade it to a B/G/NWiFi Card. I can find plenty of Mini Pci-Express Wireless N cards but not sure if they are compatible. Does anyone know if
-
SHarepoint 2013 - Document Conversion issue
Hi All, I enabled Document conversion features in my SharePoint environment successfully and its working fine. i enabled word to html conversion option , it works fine when i try to convert the document with out any images in that document , i have s