Reputation: 127
The following is the function definition I am using:
CREATE OR REPLACE FUNCTION MA_FACTSET.totalCustomers
RETURN number as
total INTEGER := 0;
FID VARCHAR2(30) := 'NT33H0-S-US';
stmt varchar2(1000);
BEGIN
execute immediate 'TRUNCATE TABLE MovingAverage';
execute immediate 'DROP TABLE MovingAverage';
execute immediate 'CREATE GLOBAL TEMPORARY TABLE MovingAverage
(ID INTEGER,
PDATE DATE,
PPRICE FLOAT,
MA1 FLOAT) ON COMMIT PRESERVE ROWS';
stmt := 'INSERT INTO MovingAverage (ID,PDATE,PPRICE) SELECT
ROWNUM,"DATE",P_PRICE FROM FP_BASIC_BD WHERE FS_PERM_SEC_ID = ''NT33H0-S-US''';
DBMS_OUTPUT.PUT_LINE(stmt);
execute immediate stmt;
dbms_output.put_line(SQL%ROWCOUNT);
commit;
execute immediate 'UPDATE MovingAverage A SET MA1 =(SELECT AVG(PPRICE)
FROM MovingAverage WHERE ID>=A.ID-5 AND ID<A.ID )' ;
dbms_output.put_line(SQL%ROWCOUNT);
commit;
execute immediate 'SELECT * FROM MovingAverage ORDER BY ID ASC';
dbms_output.put_line(SQL%ROWCOUNT);
commit;
dbms_output.put_line(total);
RETURN total;
END;
/
I have applied some checks to see whether the function is running properly or not, like getting SQL%ROWCOUNT
.
The following is the DBMS output of the function:
INSERT INTO MovingAverage (ID,PDATE,PPRICE) SELECT ROWNUM,"DATE",P_PRICE FROM FP_BASIC_BD WHERE FS_PERM_SEC_ID = 'NT33H0-S-US'
4114
4114
0
0
I want know why rowcount of "SELECT * FROM MovingAverage ORDER BY ID ASC
" is 0. And if there is any way to print complete table in Data Grid. I am using TOAD for Oracle.
Upvotes: 0
Views: 938
Reputation: 127
With collections and the table function, a function can return a table that can be queried in an SQL statement. This is demonstrated in the following example.
Create your record type variable first.
create or replace type t_record as object (i number,n varchar2(30));
Create table type variable which is based on record type variable.
create or replace type t_table as table of t_record;
Then we can proceed to create a function as follows.
create or replace function return_table return t_table as
v_ret t_table;
begin
--
-- Call constructor to create the returned
-- variable:
--
v_ret := t_table();
--
-- Add one record after another to the returned table.
-- Note: the »table« must be extended before adding
-- another record:
--
v_ret.extend; v_ret(v_ret.count) := t_record(1, 'one' );
v_ret.extend; v_ret(v_ret.count) := t_record(2, 'two' );
v_ret.extend; v_ret(v_ret.count) := t_record(3, 'three');
--
-- Return the record:
--
return v_ret;
end return_table;
For more details and further extension of work please refer following URL.
http://www.adp-gmbh.ch/ora/plsql/coll/return_table.html
Upvotes: 1
Reputation: 31648
I suggest you to rewrite your function removing dynamic sqls where not necessary. Also, If you have DDLs, DMLs don't use PL/SQL function, rather use procedure.
For select
Statements in EXECUTE IMMEDIATE
, it will work if you use BULK COLLECT INTO
CREATE OR REPLACE FUNCTION totalCustomers
RETURN NUMBER
AS
total INTEGER := 0;
FID VARCHAR2 (30) := 'NT33H0-S-US';
stmt VARCHAR2 (1000);
TYPE mrectype IS TABLE OF MovingAverage%ROWTYPE;
mrec mrectype;
BEGIN
EXECUTE IMMEDIATE 'TRUNCATE TABLE MovingAverage';
EXECUTE IMMEDIATE 'DROP TABLE MovingAverage';
EXECUTE IMMEDIATE 'CREATE GLOBAL TEMPORARY TABLE MovingAverage
(ID INTEGER,
PDATE DATE,
PPRICE FLOAT,
MA1 FLOAT) ON COMMIT PRESERVE ROWS';
stmt :=
'INSERT INTO MovingAverage (ID,PDATE,PPRICE) SELECT
ROWNUM,"DATE",P_PRICE FROM FP_BASIC_BD WHERE FS_PERM_SEC_ID = ''NT33H0-S-US''';
DBMS_OUTPUT.PUT_LINE (stmt);
EXECUTE IMMEDIATE stmt;
DBMS_OUTPUT.put_line (SQL%ROWCOUNT);
COMMIT;
EXECUTE IMMEDIATE 'UPDATE MovingAverage A SET MA1 =(SELECT AVG(PPRICE)
FROM MovingAverage WHERE ID>=A.ID-5 AND ID<A.ID )';
DBMS_OUTPUT.put_line (SQL%ROWCOUNT);
COMMIT;
EXECUTE IMMEDIATE 'SELECT * FROM MovingAverage ORDER BY ID ASC'
BULK COLLECT INTO mrec;
DBMS_OUTPUT.put_line (SQL%ROWCOUNT);
COMMIT;
DBMS_OUTPUT.put_line (total);
RETURN total;
END;
/
Call this function like this.
SET SERVEROUTPUT ON
DECLARE
x NUMBER;
BEGIN
x := totalCustomers;
END;
/
You cannot call the function in SQL select
Upvotes: 1