Can I use with clause while opening a CURSOR - oracle

Can I use WITH clause while using cursor
OPEN CURSOR_NAME FOR
WITH view1 as (Select v_name from tablename),
view2 as (Select p_name from tablename2)
Select * from view1, view2;

Yes it is possible to use with clause in cursor. Check the below example.
DECLARE
l_cur sys_refcursor;
l_val VARCHAR2 (1000);
BEGIN
DBMS_OUTPUT.ENABLE;
OPEN l_cur FOR
WITH tab AS
(SELECT 'hello'
FROM DUAL)
SELECT *
FROM tab;
FETCH l_cur
INTO l_val;
CLOSE l_cur;
DBMS_OUTPUT.put_line (l_val);
END;
Output: hello

Related

How to execute the output result for execute immediate statment

From the below query i am getting the output as below. but i am expecting the output result like the output select query to be executed again and provide the result .
Also, i want to remove the UNION ALL from last line of the output like this
select A from Table1 Union all
Select A from table2 Union All
Select A from table3 Union all
Select A from table4;
Query :
SET SERVEROUTPUT ON
Declare
v_sql varchar2(500);
v_sql2 varchar2(500);
v_prj_id varchar2(4000):='ProjectA,ProjectB,ProjectC,ProjectD';
BEGIN
Dbms_Output.Put_Line('v_prj_id='||v_prj_id);
--
FOR i IN (SELECT trim(regexp_substr(v_prj_id, '[^,]+', 1, LEVEL)) l
FROM dual
CONNECT BY LEVEL <= regexp_count(v_prj_id, ',') + 1
) LOOP
v_sql := 'select '''|| i.l ||''' AS "PRJ_ID", EVENT, email,modified_by,modified from ' || i.l ||
'.Table UNION ALL';
Dbms_Output.Put_Line (v_sql);
--
END LOOP;
EXECUTE IMMEDIATE v_sql ;
v_sql2 := RTRIM (v_sql, 'UNION ALL');
EXECUTE IMMEDIATE v_sql2 ;
Dbms_Output.Put_Line (v_sql2);
END;
/
Output :
select 'ProjectA' AS "PRJ_ID", EVENT, email,modified_by,modified from ProjectA.event UNION ALL
select 'ProjectB' AS "PRJ_ID", EVENT, email,modified_by,modified from ProjectB.event UNION ALL
select 'ProjectC' AS "PRJ_ID", EVENT, email,modified_by,modified from ProjectC.event UNION ALL
select 'ProjectD' AS "PRJ_ID", EVENT, email,modified_by,modified from ProjectD.event UNION ALL
EXECUTE IMMEDIATE will not provide you the SELECT statement results.
From Oracle Docs
If dynamic_sql_statement is a SELECT statement, and you omit both into_clause and bulk_collect_into_clause, then execute_immediate_statement never executes.
You have use SELECT INTO clause or BULK_COLLECT_INTO_CLAUSE and assign the values to some variable if you want to see the results of EXECUTE IMMEDIATE select values.
Something like below for single row
SET SERVEROUTPUT ON
DECLARE
L_RESULT VARCHAR2(20);
BEGIN
VSQL:= --YOUR LOGIC
EXECUTE IMMEDIATE VSQL INTO L_RESULT;
DBMS_OUTPUT.PUT_LINE(L_RESULT);
END;
/
For Multiple rows
DECLARE
TYPE T IS TABLE OF MYTABLE.ID%TYPE INDEX BY PLS_INTEGER;
MYROW T;
BEGIN
VSQL:= --YOUR LOGIC
EXECUTE IMMEDIATE VSQL BULK COLLECT INTO MYROW;
DBMS_OUTPUT.PUT_LINE(MYROW.XXX);
END;
/
You are doing everything right except concatenating the v_sql with original string -
SET SERVEROUTPUT ON
Declare
v_sql varchar2(500);
v_sql2 varchar2(500);
v_prj_id varchar2(4000):='ProjectA,ProjectB,ProjectC,ProjectD';
BEGIN
Dbms_Output.Put_Line('v_prj_id='||v_prj_id);
--
FOR i IN (SELECT trim(regexp_substr(v_prj_id, '[^,]+', 1, LEVEL)) l
FROM dual
CONNECT BY LEVEL <= regexp_count(v_prj_id, ',') + 1
) LOOP
v_sql := v_sql || ' select '''|| i.l ||''' AS "PRJ_ID", EVENT, email, modified_by, modified from ' || i.l ||
'.Table UNION ALL';
Dbms_Output.Put_Line (v_sql);
--
END LOOP;
EXECUTE IMMEDIATE v_sql ;
v_sql2 := RTRIM (v_sql, 'UNION ALL');
EXECUTE IMMEDIATE v_sql2 ;
Dbms_Output.Put_Line (v_sql2);
END;
/

oracle out ref cursor to a loop

How to pass the 'values' of the output cursor o_cur to a further loop?
CREATE OR REPLACE PROCEDURE dyn_cursor (o_cur OUT SYS_REFCURSOR)
IS
script VARCHAR2 (4000);
BEGIN
script := 'select sysdate-1 notnow, sysdate today from dual union all select sysdate+1 notnow, sysdate today from dual';
OPEN o_cur FOR script;
-- the question is related to this block:
for i in o_cur
loop
DBMS_OUTPUT.PUT_LINE(i.notnow);
end loop;
-----------------------
END;
FETCH is usually handled outside the procedure when the refcursor is an OUT variable
CREATE OR REPLACE PROCEDURE dyn_cursor (o_cur OUT SYS_REFCURSOR)
IS
script VARCHAR2 (4000);
BEGIN
script := 'select sysdate-1 notnow, sysdate today from dual union all select sysdate+1 notnow, sysdate today from dual';
OPEN o_cur FOR script;
END;
/
SET SERVEROUTPUT ON
DECLARE
v_cur SYS_REFCURSOR;
v_notnow DATE;
v_today DATE;
BEGIN
dyn_cursor(v_cur);
LOOP
FETCH v_cur INTO
v_notnow,
v_today;
EXIT WHEN v_cur%notfound;
dbms_output.put_line(v_notnow);
END LOOP;
END;
/
02-10-18
04-10-18
PL/SQL procedure successfully completed.
This seems a strange construct. I would create a view you can reuse at different places.
CREATE OR REPLACE VIEW VW_Times AS
SELECT sysdate-1 notnow, sysdate today FROM dual
UNION ALL
SELECT sysdate+1 notnow, sysdate today FROM dual;
and
CREATE OR REPLACE PROCEDURE OutputTime ()
IS
CURSOR o_cur IS
SELECT * FROM VW_Times;
BEGIN
FOR i IN o_cur
LOOP
DBMS_OUTPUT.PUT_LINE(i.notnow);
END LOOP;
END;
Tanks to post of Kaushik Nayak, I found the acceptable solution:
CREATE OR REPLACE PROCEDURE dyn_cursor (o_cur OUT SYS_REFCURSOR)
IS
script VARCHAR2 (4000);
type array is table of VARCHAR2(20) index by binary_integer;
l_datapoint1 array;
l_datapoint2 array;
BEGIN
script := 'select sysdate-1 notnow, sysdate today from dual union all select sysdate+1 notnow, sysdate today from dual';
OPEN o_cur FOR script;
LOOP
FETCH o_cur bulk collect into l_datapoint1, l_datapoint2;
for i in 1 .. l_datapoint1.count
loop
DBMS_OUTPUT.PUT_LINE( l_datapoint1(i) || ', ' || l_datapoint2(i) );
end loop;
exit when o_cur%notfound;
end loop;
close o_cur;
END;

Getting inconsistent data type error while fetching bulk collect from ref cursor

I am getting inconsistent data type error while fetching bulk collect from ref cursor
Here's my code
create or replace function test_func(c in int) return number as
v_stmt varchar2(4000);
v_insert varchar2(4000);
k_col_name varchar2(50);
v_gs_tab_name varchar2(100);
min_k_val varchar2(50);
max_k_val varchar2(50);
mid_k_val varchar2(50);
nxt_mid_k_val varchar2(50);
type l_cursor_type is ref cursor;
l_cursor l_cursor_type;
type t_source is table of rec_source;
m_source t_source:=t_source();
dat_typ varchar2(50);
begin
select DISTINCT data_type INTO dat_typ from all_tab_cols where column_name
in (SELECT cols.column_name FROM all_constraints cons, all_cons_columns
cols
WHERE cons.constraint_type='P' and cols.table_name=+v_tab_name AND
CONS.OWNER='SOURCE'
AND cons.constraint_name = cols.constraint_name AND cons.owner =
cols.owner);
dml_str:='create or replace type dwbi_land.rec_source as object (id '||dat_typ||')';
dbms_output.put_line(dml_str);
execute immediate dml_str;
dml_str:='create or replace type dwbi_land.t_source as table of rec_source';
dbms_output.put_line(dml_str);
execute immediate dml_str;
begin
select 'select * from '||v_gs_tab_name
||' where '||k_col_name||' between ('||min_k_val||') and
('||mid_k_val||')'
into v_stmt
from dual;
dbms_output.put_line(v_stmt);
execute immediate v_stmt bulk collect into m_source;
v_insert:='insert into '||v_tab_name||' values '||v_stmt||'';
dbms_output.put_line(v_insert);
open l_cursor for v_stmt;
loop
fetch l_cursor bulk collect into m_source;
exit when l_cursor%NOTFOUND;
m_source.extend;
forall i in 1..m_source.count
execute immediate v_insert using m_source(i).id;
commit;
exit when m_source.count=0;
end loop;
select 'select * from '||v_gs_tab_name
||' where '||k_col_name||' between ('||nxt_mid_k_val||') and ('||max_k_val||')'
into v_stmt
from dual;
dbms_output.put_line(v_stmt);
v_insert:='insert into '||v_tab_name||' values '||v_stmt||'';
dbms_output.put_line(v_insert);
open l_cursor for v_stmt using 1;
loop
fetch l_cursor bulk collect into m_source;
forall i in 1..m_source.count
execute immediate v_insert using m_source(i).id;
commit;
exit when m_source.count=0;
end loop;
end;
In fetch l_cursor bulk collect into m_source part am getting
Ora-00932:Inconsistent datatypes: expected - got -
Any suggestions are welcome
Previously i wasn't able to post the whole code, now i've posted the whole code
You are missing the declaration of variables but it appears you could simplify it to:
begin
v_stmt := 'insert into ' || v_tab_name
|| ' select id from '||v_gs_tab_name
|| ' where '||k_col_name||' between :1 and :2;
dbms_output.put_line(v_stmt);
execute immediate v_stmt using min_k_val, mid_k_val;
execute immediate v_stmt using nxt_mid_k_val, max_k_val;
END;
can you plz expand ur coding...
wats the datatype for v_stmt ?
Sample code :
begin
v_stmt:= 'select * from ''||v_gs_tab_name||'' where ''||k_col_name||'' between (''||nxt_mid_k_val||'') and (''||max_k_val||'')'' into v_stmt from dual'
Dbms_output.put_line(v_stmt);
V_insert:='insert into '||v_tab_name||' values '||v_stmt||'';
dbms_output.put_line(v_insert);
open l_cursor for v_stmt using 1; loop fetch l_cursor bulk collect into m_source;
forall i in 1..m_source.count
execute immediate v_insert using m_source(i).id;
commit;
exit when m_source.count=0;
end loop;
end;

How to fetch a ref_cursor into Oracle's WITH CLAUSE

Is it possible to use a ref_cursor with ORACLE WITH CLAUSE. For example, I have the following scenario. First I have a procedure which returns a ref_cursor
PROCEDURE p_return_cursor(p_id IN NUMBER, io_cursor OUT t_cursor)
AS
BEGIN
OPEN io_cursor FOR
SELECT col1, col2
FROM Table1 t
WHERE t.id = p_id;
END;
Second, I have another procedure on which I make a call to p_return_cursor:
PROCEDURE p_test(p_cid IN NUMBER)
AS
l_cursor t_cursor;
l_rec Table1%ROWTYPE;
BEGIN
p_return_cursor(p_id => p_cid, io_cursor => l_cursor);
-- CODE GOES HERE
...
Now, my question is, can I make a temp table using the Oracle's WITH CLAUSE using the cursor; something like:
...
WITH data AS (
LOOP
FETCH l_cursor INTO l_rec;
EXIT WHEN l_cursor%NOTFOUND;
SELECT l_rec.col1, l_rec.col2 FROM DUAL;
END LOOP;
CLOSE l_cursor;
)
You cannot do it directly. You can, however, BULK COLLECT your cursor into a PL/SQL table variable and use that in a WITH clause.
Be careful of memory usage if the cursor contains many rows.
Full example:
CREATE TABLE table1 ( col1 NUMBER, col2 NUMBER );
INSERT INTO table1 ( col1, col2 ) SELECT rownum, 100+rownum FROM DUAL CONNECT BY ROWNUM <= 15;
COMMIT;
CREATE OR REPLACE PACKAGE se_example AS
TYPE t_cursor IS REF CURSOR
RETURN table1%ROWTYPE;
TYPE l_rec_tab IS TABLE OF table1%ROWTYPE;
PROCEDURE p_test (p_cid IN NUMBER);
END se_example;
CREATE OR REPLACE PACKAGE BODY se_example AS
-- private
PROCEDURE p_return_cursor (p_id IN NUMBER, io_cursor OUT t_cursor) AS
BEGIN
OPEN io_cursor FOR
SELECT col1,
col2
FROM table1 t;
--WHERE t.id = p_id; -- I didn't put "id" column in my sample table, sorry...
END p_return_cursor;
PROCEDURE p_test (p_cid IN NUMBER) IS
l_cursor t_cursor;
l_tab l_rec_tab;
l_dummy NUMBER;
BEGIN
p_return_cursor (p_id => p_cid, io_cursor => l_cursor);
FETCH l_cursor BULK COLLECT INTO l_tab;
-- *** instead of this
-- WITH data AS (
-- LOOP
-- FETCH l_cursor INTO l_rec;
-- EXIT WHEN l_cursor%NOTFOUND;
-- SELECT l_rec.col1, l_rec.col2 FROM DUAL;
-- END LOOP;
-- CLOSE l_cursor;
-- )
-- '
--
-- *** do this
WITH data AS
( SELECT col1, col2 FROM TABLE(l_tab) )
SELECT sum(col1 * col2) INTO l_dummy
FROM data;
dbms_output.put_line('result is ' || l_dummy);
END p_test;
END se_example;
begin
se_example.p_test(100);
end;

Comma separated values to IN function in oracle

I am trying to execute below query, but not getting any result.
Could some one tell what wrong I am doing?.
DECLARE
object_types VARCHAR2(200);
v_object_types VARCHAR2(200);
l_count number;
BEGIN
object_types :='TABLE,VIEW';
select ''''||regexp_replace(object_types, '( )*(,)( )*',''',''')||''''
into v_object_types from dual;
dbms_output.put_line(to_char(v_object_types));
SELECT count(*) into l_count
FROM all_objects o where o.object_type IN ('||v_object_types||');
dbms_output.put_line(l_count);
END;
WHERE variable IN (1,2,3)
is different to what you are sending now
WHERE variable IN ('1,2,3') or
WHERE variable IN ('||v_object_types||')
You are trying to build the SQL dynamically but instead you are using a single string literal '||v_object_types||' in the IN clause.
You can do it using a collection:
Oracle Setup:
CREATE TYPE stringlist IS TABLE OF VARCHAR2(200);
/
PL/SQL:
DECLARE
object_types VARCHAR2(200) := 'TABLE,VIEW';
v_object_types stringlist;
BEGIN
SELECT TRIM( BOTH FROM REGEXP_SUBSTR( object_types, '[^,]+', 1, LEVEL ) )
BULK COLLECT INTO v_object_types
FROM DUAL
CONNECT BY LEVEL <= REGEXP_COUNT( object_types, '[^,]+' );
FOR i IN 1 .. v_object_types.COUNT LOOP
dbms_output.put_line( v_object_types(i) );
END LOOP;
SELECT count(*)
INTO l_count
FROM all_objects
WHERE object_type MEMBER OF v_object_types;
dbms_output.put_line(l_count);
END;
/
or using dynamic sql:
DECLARE
object_types VARCHAR2(200) := 'TABLE,VIEW';
v_sql VARCHAR2(200);
l_count INTEGER;
BEGIN
v_sql := 'SELECT count(*) FROM all_objects WHERE object_type IN ('
|| REGEXP_REPLACE( object_types, ' *(.+?) *(,|$)', '''\1''\2' )
|| ')';
EXECUTE IMMEDIATE v_sql INTO l_count;
dbms_output.put_line(l_count);
END;
/

Resources