Fetch query result into cursor within procedure - sql

I'm migrating many procedures from MySQL to oracle and I've found some issues. This is what I've got so far:
CREATE OR REPLACE PROCEDURE PROCEDURE1(PROCEDURE_PARAM IN NUMBER)
IS
CURSOR C1 (CURSOR_PARAMETER IN NUMBER)
IS
SELECT COL1, COL2, MY_FUNCTION1(P1), SUM(COL3), MY_FUNCTION2(P1,P2)
COL4, MY_FUNCTION(P1,P2,P3,P4)
FROM TABLE_1
WHERE COL1 = CURSOR_PARAMETER -- How to reference it to 'Procedure_param' ?
GROUP BY COL1, COL2, COL4
ORDER BY COL2;
BEGIN
-- HOW TO FETCH RESULTS INTO CURSOR ??
END PROCEDURE1;
/
Those are an example of name columns and functions(user created functions). My concerns are how to tell the cursor that the parameter CURSOR_PARAMETER is the same of PROCEDURE_PARAM and also the most important, how to fetch the results into the cursor?
I'm stuck in this problem. Any help would be appreciated. With this example I could start converting all procedures I have to.
Best regards.

you'd fetch from the cursor like :
BEGIN
for r_row in C1(PROCEDURE_PARAM)
loop
dbms_output.put_line(r_row.col1);--or whatever you want to do here.
end loop;
end;
though i usually prefer to write these inline as
begin
for r_row in (SELECT COL1, COL2, MY_FUNCTION1(P1),
SUM(COL3), MY_FUNCTION2(P1,P2)
COL4, MY_FUNCTION(P1,P2,P3,P4)
FROM TABLE_1
WHERE COL1 = PROCEDURE_PARAM
GROUP BY COL1, COL2, COL4
ORDER BY COL2)
loop
...
end loop;
just so I don't have to scroll up to a cursor def to see what it was actually doing.

Related

How to convert sql query with in clauses into string

Hi I want to convert the sql statement into string for dynamic use. But I’m having trouble while concatenation
select
col1, col2
from
Table1
Where
Col3 in ( ‘cat’ , ‘dog’ );
I’m unable to figure out how to put quotes and || for the cat and dog
‘select
col1, col2
from
Table1
Where
Col3 in ( ‘||’‘cat’’ ||’, ‘’dog’ ‘||’)’ || Strcond;
One option is to use the q-quoting mechanism (see line #6), as it lets you use single quotes normally (also, your single quotes look fancy; if you planned to copy/paste from e.g. MS Word into your SQL client, that won't work).
Here's an example:
SQL> declare
2 l_str varchar2(500);
3 strcond varchar2(100) := ' and 1 = 1';
4 begin
5 l_str := 'select col1, col2 from table1 where col3 in ' ||
6 q'[('cat', 'dog')]' || strcond;
7 dbms_output.put_line(l_str);
8 end;
9 /
select col1, col2 from table1 where col3 in ('cat', 'dog') and 1 = 1
PL/SQL procedure successfully completed.
SQL>
One option it to use bind variables and put in as many bind variables as the maximum size of the IN list:
select col1, col2 from Table1 Where Col3 in ( :a001, :a002, :a003, :a004 )
Then:
you can use the same statement repeatedly and the SQL engine will not have to reparse it (after the first time).
you do not need to escape quotes in your list values in the dynamic SQL string.
your code is less vulnerable to SQL injection.
If you want to pass fewer values than the maximum then you can repeat values:
DECLARE
sql VARCHAR2(2000) := 'select col1, col2 from Table1 Where Col3 in ( :a001, :a002, :a003, :a004 )';
BEGIN
EXECUTE IMMEDIATE sql USING 'cat', 'dog', 'cat', 'cat';
END;
/
However, if you are going to do this then you can consider if you can eliminate dynamic SQL entirely:
DECLARE
a001 Table1.Col3%TYPE := 'cat';
a002 Table1.Col3%TYPE := 'dog';
a003 Table1.Col3%TYPE := a001;
a004 Table1.Col3%TYPE := a001;
col1_values SYS.ODCIVARCHAR2LIST;
col2_values SYS.ODCIVARCHAR2LIST;
BEGIN
select col1, col2
BULK COLLECT INTO col1_values, col2_values
from Table1
Where Col3 in ( a001, a002, a003, a004 );
END;
/

How to use variable in a Oracle scheduled job?

The following script ran in Oracle SQL developer. It will insert two rows into a table. However, when I put this script into a job under the scheduler tab in Oracle SQL developer, no row was inserted. When created the job, I used sys.Default_job_class, type of job is PL/SQL block.
Can someone help me to revise the script, so it can be run in a job? Thank you
define batchNo='123';
insert into TABLE_NAME (col1, col2, col3, col4) select col1, col2, col3, col4 from TABLE2 WHERE BATCH_NO = '&batchNo';
commit;
Change your code so it's a PL/SQL block:
DECLARE
batchNo VARCHAR2(3) := '123';
BEGIN
insert into TABLE_NAME (col1, col2, col3, col4)
select col1, col2, col3, col4
from TABLE2
WHERE BATCH_NO = batchNo;
commit;
END;
define and &varname are used in SQL*Plus, but are not valid PL/SQL.
Your syntax with "&batchNo" is specific to SQL*Plus. It will not work with PL/SQL.
PL/SQL would need something like this:
DECLARE
l_batchno number := 123;
BEGIN
insert into TABLE_NAME (col1, col2, col3, col4)
select col1, col2, col3, col4 from TABLE2 WHERE BATCH_NO = l_batchno;
commit;
END;
If you want to execute with parameter you must do:
sqlplus -s $USER/$PASSWD # script.sql <YOUR_PARAMETER>
Your SQL Script must contain:
INSERT INTO TABLE_NAME (col1, col2, col3, col4)
SELECT col1, col2, col3, col4 FROM TABLE2 WHERE BATCH_NO = '&1';
COMMIT;
If you want to use more than 1 parameter...
sqlplus -s $USER/$PASSWD # script.sql <PARAMETER_1> <PARAMETER_2> ... <PARAMETER_N>
You must put into script.sql
DECLARE
v_FIRST DATATYPE;
v_SECOND DATATYPE;
v_N DATATYPE;
BEGIN
v_FIRST := '&1';
v_SECOND := '&2';
v_N := '&N';
END;

oracle sql dynamically select columns using a parameter table

I have a table in oracle with 10 columns, say Table A with col_1, col_2, col_3 etc. I have another table, Table B with rows that has column names from table A co1_1, col_2, col_3. The rows in Table B can vary.
TABLE A
COL1 COL2 COL3 COL4 COL5 COL6 COL7 COL8 COL9 COL10
TABLE B
COL1
COL2
COL3
I want to write an oracle sql query which dynamically gets the select columns names based on the column names(rows) in table B.
If table B has 3 rows with corresponding column names then my query should look like this
select col_1, col_2, col_3 from A
If table B has 4 rows then my query should dynamically change to below
select col_1, col_2, col_3, col_4 from A
You need to use the dynamic query.
'SELECT '
|| (SELECT LISTAGG(COLNAME, ',') WITHIN GROUP (ORDER BY COLNAME) FROM TABLEB)
|| ' FROM TABLEA'
I think we should go to ALL_TAB_COLUMNS table for finding column names.
Like this.
SELECT
'SELECT '
||
(SELECT LISTAGG( y.COLNAME, ',') WITHIN GROUP (ORDER BY Y.COLNAME)
FROM TABLE_B x,ALL_TAB_COLUMNS y
where x.COLNAME=Y.COLUMN_NAME )
||
' FROM Table_A' script
FROM DUAL;
A ref cursor can be used to created dynamic columns. Many languages and applications support ref cursors, and if you add some details about your system someone may know exactly how to integrate them in your environment.
Below is a simple example of how to create a function that returns a ref cursor. How to call it depends on your system.
Sample Schema
--drop table a;
--drop table b;
create table a as
select 1 col1, 2 col2, 3 col3, 4 col4, 5 col5, 6 col6, 7 col7, 8 col8, 9 col9, 10 col10
from dual;
create table b as
select 'COL1' column_name from dual union all
select 'COL2' column_name from dual union all
select 'COL3' column_name from dual;
Function
create or replace function get_dynamic_results return sys_refcursor is
v_cursor sys_refcursor;
v_column_list varchar2(4000);
begin
--Split this into multiple SELECTS if you get an error like:
-- ORA-01489: result of string concatenation is too long error
select listagg(column_name, ',') within group (order by column_name) columns
into v_column_list
from b;
open v_cursor for 'select '||v_column_list||' from a';
return v_cursor;
end;
/

displaying multiple tables in a schema of db

I have a schema and it consists of n tables . now the thing is to display those multiple tables independently like
Table1
Col1 col2 col3 . . . col n
Table2
Col1 col 2 col3 .....col n
.
.
.
Table N
Col1 col2 col3 ..... Col n
And I have to implement this using pl/sql this is the code I am trying with
DECLARE
name varchar2(50);
s_query varchar2(500);
cursor c_demo is select table_name from user_tables;
BEGIN
open c_demo;
loop
fetch c_demo into name;
EXIT WHEN c_demo%notfound;
select * into s_query from #name;
dbms_output.put_line(s_query);
end loop;
close c_demo;
end;
Assuming that you are using MS SQL. If you know the table names try using UNION/ UNION ALL. If the table definitions doesn't match, use aliases in your SELECT query as shown below.
SELECT T1COL1 AS COL1,T1COL2 AS COL2,T1COL3 AS COL3 FROM TABLE1
UNION ALL
SELECT T2COL1 AS COL1,T2COL2 AS COL2,T2COL3 AS COL3 FROM TABLE2
....
SELECT TNCOL1 AS COL1,TNCOL2 AS COL2,TNCOL3 AS COL3 FROM TABLEN

Oracle select selected columns from a table whose column names are available in another table

Let me give an example :
Suppose I have a table TableA(Col1, Col2, Col3, Col4, Col5)
I have another table TableB where their are entries of the names of the columns of TableA that required to be fetched, for example Col2 and Col5
Now I want to write an SQL query that will only fetch the columns of TableA as defined in TableB .
Here is a start.
The idea is to build a concatenated list of column_names as a varchar
'col1, col2, col3, col4'
and to use it in a dynamic sql query.
declare
column_list xmltype;
column_names varchar(10000);
begin
SELECT
XMLAGG (XMLELEMENT (e, t1.column_name || ',')).EXTRACT ('//text()')
column_name
into column_list
FROM all_tab_cols t1
where t1.table_name = 'TABLEA'
and exists (select null
from TableB
where t1.column_name = <the field for the column_name in tableB>);
column_names := RTRIM(column_list.getClobVal(), ',');
--this will just display the sql query, you'll need to execute it to get your results with EXECUTE IMMEDIATE
dbms_output.put_line( 'SELECT '||column_names||' from TableA');
end;