Oracle Function Select * from Query Not giving any Results - oracle

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.

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

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.
https://renenyffenegger.ch/notes/development/databases/Oracle/PL-SQL/collection-types/return-table-from-function/index
http://www.adp-gmbh.ch/ora/plsql/coll/return_table.html

Related

how to store and call a sql query from a table column?

Insert statement below holds details of another Table that has 3 columns (id,ins_dt,text_stuff)
INSERT INTO swpurge_config
(schema
,table_name
,table_alias
,driving_column
,deletion_predicate
,retention_period_type
,retention_period_value)
VALUES
('CUSTOMERS_OWNER'
,'LAST_NAMES'
,'LN'
,'ins_dt'
,'WHERE ln.ins_dt < SYSDATE - p_retention_period_value
AND ora_hash(ln.rowid, 8) = 1'
,'month'
,'6');
Aim:
I am essentially trying to add a delete predicate in a varchar2 column. The idea is to call this column in a Procedure which will delete records up to 1000 rows:
PROCEDURE delete_rows
(
p_schema IN VARCHAR2
,p_table_name IN VARCHAR2
,p_table_alias in varchar2
,p_retention_period_value IN VARCHAR2
,p_delete_predicate IN VARCHAR2
) IS
v_sql varchar2 (32000);
v_row_limit pls_integer (1000);
BEGIN
v_sql := 'delete from ' || p_schema ||'.'|| table_name ||p_table_alias
'older than '|| p_retention_period_value || p_delete_predicate;
dbms_output.put_line(v_sql);
END delete_rows;
Not sure about 2 things:
1. How to store the sql where clause in a table column?
2. How to execute the where clause as a statement in the procedure?
Thanks
you are talking about Dynamic SQL.
You can just store it inside VARCHAR2 in string format. then retrieve it
select deletion_predicate into v_sql from swpurge_config where ...
then
v_sql := "SELECT ...... FRom .... " || v_sql;
finally execute it
EXECUTE IMMEDIATE v_sql;
if your sql statement also includes parameters then
EXECUTE IMMEDIATE query_str
using param1;

Passing table name inside proc to store its row count into a variable

I want to write a simple pl/sql procedure which will take a table name as input and it will store the table row count into a variable . I have written the bellow code :
CREATE OR REPLACE procedure ATT_REP.proc_compare2(table_name IN varchar2)
is
cnt NUMBER(30);
begin
execute immediate 'select count(*) from '||table_name||' into '||cnt ;
dbms_output.put_line(cnt);
end;
/
while executing i am getting 'PLS-00357: Table,View Or Sequence reference 'CES_ODS.ENTITY' not allowed in this context' error.
Please suggest what am i doing wrong . How can i make it working .
Try the following:
CREATE OR REPLACE PROCEDURE ATT_REP.proc_compare2 (table_name IN VARCHAR2)
IS
cnt NUMBER (30);
sql_stmt VARCHAR2 (200);
BEGIN
sql_stmt := 'select count(*) from ' || table_name;
EXECUTE IMMEDIATE sql_stmt INTO cnt;
DBMS_OUTPUT.put_line (cnt);
END;
/

Create a table with oracle pl/sql

I get this error ORA-00933: SQL command not properly ended, but I cannot see what the problem is.
Creates the package:
CREATE OR REPLACE PACKAGE "TOOL_PKG" IS
PROCEDURE CREATE_ZTEMP_CLAIMS_TABLES;
END TOOL_PKG;
/
Create a procedure for the package. I get the error trying to run the procedure.
What I want to do is create a new table with an existing table. I need it dynamic because I'll be adding a lot more tables to the list.
CREATE OR REPLACE PACKAGE BODY CUBS_OWNER."TOOL_PKG" IS
PROCEDURE CREATE_NEW_TABLE IS
type array_t is table of varchar2(50) index by pls_integer;
my_table_t array_t;
elem varchar2(50);
c int;
BEGIN
my_table_t (1) := 'MY_TABLE';
elem := my_table_t.first;
while elem is not null loop
select count(*) into c from user_tables where table_name = upper('ZTEST_'||my_table_t(elem));
if c=0 then
Begin
execute immediate 'CREATE TABLE upper(NEWX_'||my_table_t(elem)||') AS SELECT * FROM upper('||my_table_t(elem)||') where rownum=0';
COMMIT;
DBMS_OUTPUT.put_line ('ZTEST_'||my_table_t(elem)||' created.');
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line (
'tool_pkg.create_new_table...failed creating table '
|| CHR (10)
|| SQLERRM);
END;
end if;
elem := my_table_t.next(elem);
end loop;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line (
'tool_pkg.create_new_table...failed creating table '
|| CHR (10)
|| SQLERRM);
END;
END tool_pkg;
/
I had to make sure the methods upper were outside the quotes.
Instead of this
execute immediate 'CREATE TABLE upper(NEWX_'||my_table_t(elem)||') AS SELECT * FROM upper('||my_table_t(elem)||') where rownum=0';
It had to be in this form
execute immediate 'CREATE TABLE '||upper('NEWX_'||my_table_t(elem))||' AS SELECT * FROM '||upper(my_table_t(elem))||' where rownum=0';

Plsql - Evaluate a dynamic string

I need to build a process that creates tables dynamically.
I have this:
declare
type array is table of varchar2(30) index by binary_integer;
a array;
expression varchar2(2000);
RESUME_create LONG;
procedure createTables ( texto in VARCHAR2 ) is
begin
dbms_output.put_line('the parameter is: ' || texto);
expression := 'begin ' || texto || '; end;';
dbms_output.put_line(expression);
execute immediate expression;
end;
RESUME_create := 'CREATE TABLE RESUME (
R_Resume_date DATE DEFAULT SYSDATE NOT NULL ,
R_Resume_source CHAR(3) DEFAULT ''001'' NOT NULL ,
R_Resume_channel CHAR(3) DEFAULT ''001'' NOT NULL )';
createTables('RESUME_create');
end;
/
So this is just an example.
So imagine that I need to declare multiples CREATE TABLEs and call the createTable into a loop passing multiples string that the function has to evaluate and execute.
If I un understand well, you need to run a set of DDL statements stored in a collection. If so, you can use something like:
declare
type tArray is table of varchar2(1000) index by pls_integer;
vArray tArray ;
begin
vArray(1) := 'create table firstTab ( a number, b number)';
vArray(2) := 'create table secondTab ( c number, d varchar2(10))';
--
for i in vArray.first .. vArray.last loop
execute immediate vArray(i);
end loop;
end;
/

temporary storage in Oracle?

I need to store output of a query(which returns multiple rows) temporarily in Oracle. One of the ways to do this is using temporary table and I am using that currently. But the problem with them is that they stay around and cannot be created and dropped in a procedure willy nilly. Is there another object that I can use to temporarily store the output of a query to be able to use in the stored procedure ?
Here is my stored procedure for reference:
create or replace PROCEDURE procPrintOutput
IS
l_stmt VARCHAR2(512) := '';
create_table_stmt VARCHAR2(512) := 'create GLOBAL TEMPORARY TABLE temp(matViewLogQuery CLOB) ON COMMIT DELETE ROWS';
drop_mat_view_logs_stmt VARCHAR2(100) := 'DROP MATERIALIZED VIEW LOG ON ';
drop_temp_table VARCHAR2(512) := 'DROP TABLE temp';
ref_cursor SYS_REFCURSOR;
BEGIN
EXECUTE IMMEDIATE(create_table_stmt);
DBMS_OUTPUT.PUT_LINE('created temp table');
DECLARE
CURSOR LIST_OF_MVL IS SELECT * FROM USER_MVIEW_LOGS;
CURSOR CREATE_MVL IS SELECT * FROM temp;
BEGIN
FOR TEST IN LIST_OF_MVL
LOOP
BEGIN
DBMS_OUTPUT.PUT_LINE('owner : ' || TEST.OWNER || ' - name : ' || TEST.MASTER);
l_stmt := 'insert into temp SELECT SYS.DBMS_METADATA.get_dependent_ddl (''MATERIALIZED_VIEW_LOG'', '''||TEST.MASTER||''', '''||TEST.LOG_OWNER||''') from dual';
EXECUTE IMMEDIATE (l_stmt);
EXECUTE IMMEDIATE (drop_mat_view_logs_stmt || TEST.MASTER);
DBMS_OUTPUT.PUT_LINE('view dropped ... ');
END;
END LOOP;
FOR CREATE_SCRIPT IN CREATE_MVL
LOOP
BEGIN
DBMS_OUTPUT.PUT_LINE('SCRIPT : ' || CREATE_SCRIPT.matViewLogQuery);
EXECUTE IMMEDIATE(CREATE_SCRIPT.matViewLogQuery);
DBMS_OUTPUT.PUT_LINE('view recreated ... ');
END;
END LOOP;
END;
EXECUTE IMMEDIATE(drop_temp_table);
DBMS_OUTPUT.PUT_LINE('Done! Table dropped');
ROLLBACK;
END;
Thanks
instead of of temp table you can use collection in pl/sql and store all information that you need into the collection by BULK COLLECT
here small example
in my example I collect all DDLs for matviews and name of the views, then in simple cycle we can do any operations...
DECLARE
TYPE tDDL IS record (name varchar2(30), ddl CLOB);
TYPE tblDDL IS TABLE OF tDDL INDEX BY PLS_INTEGER;
l_ddls tblDDL;
BEGIN
SELECT object_name, dbms_metadata.get_ddl('MATERIALIZED_VIEW', object_name)
BULK COLLECT INTO l_ddls
from user_objects
where object_type= 'MATERIALIZED VIEW';
FOR indx IN 1 .. l_ddls.COUNT
LOOP
--do what you need with collected DDLs
DBMS_OUTPUT.PUT_LINE('view dropped ... ');
--your complex execute immediate logic here
dbms_output.put(l_ddls(indx).name);
dbms_output.put(' : ');
dbms_output.put_line(substr(l_ddls(indx).ddl, 100));
DBMS_OUTPUT.PUT_LINE('view recreated ... ');
END LOOP;
END;

Resources