I am building a procedure, where I`m first creating a select statement and store it in an VARCAHR variable.
I now want to execute that query and store the whole result set in an variable to loop through it or use directly in a for loop.
I only find examples where the Select is hard written in the for loop definition.
How do i exchange the Select statement with my variable that holds my select statement?
for r IN (SELECT ... FROM ...)
loop
--do sth;
end loop;
how i want to use it :
statement := 'SELECT .... FROM ...';
for r IN (statement) -- HOW TO DO THIS
loop
--do sth;
end loop;
For a dynamic ref cursor, you need to define everything explicitly:
declare
sqlstring long := 'select 123 as id, ''demo'' as somevalue from dual where dummy = :b1';
resultset sys_refcursor;
type demo_rectype is record
( id integer
, somevalue varchar2(30) );
demorec demo_rectype;
begin
open resultset for sqlstring using 'X';
loop
fetch resultset into demorec;
exit when resultset%notfound;
dbms_output.put_line('id=' || demorec.id || ' somevalue=' || demorec.somevalue);
end loop;
close resultset;
end;
You can parse the cursor and figure out the column names and datatypes with DBMS_SQL. Example here: www.williamrobertson.net/documents/refcursor-to-csv.shtml
Related
In ORACLE please.
Is it possible to have a variable in the 'ORDER BY' Statment?
So iam currenty creating a procedure in which I need to have a dynamic Order by.
Is there any way to do this ?
CREATE OR REPLACE PROCEDURE TEST1
vorder varchar(250);
...
vOrder := 'number';
FOR o IN (SELECT * FROM TABLENAME order by vOrder)
LOOP
-- Some stuff ---
END LOPP;
....
The only way to really have a dynamic order by clause instead of just having a list of predefined options as suggested by Alex, would be to use a dynamic sql cursor.
TYPE curType IS REF CURSOR;
vCur curType;
vRec tablename%ROWTYPE;
vOrd VARCHAR2(250) := 'column';
BEGIN
OPEN vCur FOR 'SELECT * FROM tablename ORDER BY '||vOrd';
LOOP
FETCH vCur INTO vRec;
EXIT WHEN cur%NOTFOUND;
END LOOP;
CLOSE vCur;
END;
/
I have a table TestTable with columns of col_test1, col_test2, col_test3 ...
and I want to create a loop that accesses each of these columns individually and find the max value and place it in the variable made in the declare block and simply dbms.out.put it.
Declare
my_array sys.dbms_debug_vc2coll := sys.dbms_debug_vc2coll('col_test1','col_test2','col_test2');
v_test number(8,0);
Begin
for r in my_array.first..my_array.last
loop
select max(my_array(r)) into v_test from TestTable;
dbms_output.put_line(v_test);
end loop;
End;
/
The output I get is just the string 'col_test1'which should be 50.
This is done through oracle SQL. Is there any way to achieve this?
You could use dynamic SQL for this
Declare
my_array sys.dbms_debug_vc2coll := sys.dbms_debug_vc2coll('col_test1','col_test2','col_test2');
v_test number(8,0);
Begin
for r in my_array.first..my_array.last
loop
execute immediate 'select max(' || my_array(r) || ') from TestTable'
into v_test;
dbms_output.put_line(v_test);
end loop;
End;
If you're going to resort to dynamic SQL, however, it would generally make more sense to build a single SQL statement that took that max of all three columns in one pass rather than potentially doing three separate table scans on the same table.
There is a table contains this kind of data: select to_char(sysdate,'day') from dual in a column. I want to get results of the every query that the table keeps.
My result set should be the result of select to_char(sysdate,'day') from dual query. So in this case it is a tuesday.
SO_SQL_BODY is Varchar2.
I wrote this code but it returns only table data.
CREATE or replace PROCEDURE a_proc
AS
CURSOR var_cur IS
select SO_SQL_BODY FROM SO_SUB_VARS group by SO_SQL_BODY;
var_t var_cur%ROWTYPE;
TYPE var_ntt IS TABLE OF var_t%TYPE;
var_names var_ntt;
BEGIN
OPEN var_cur;
FETCH var_cur BULK COLLECT INTO var_names;
CLOSE var_cur;
FOR indx IN 1..var_names.COUNT LOOP
DBMS_OUTPUT.PUT_LINE(var_names(indx).SO_SQL_BODY);
END LOOP;
END a_proc;
DECLARE
res varchar2(4000);
sql_str varchar2(1000);
BEGIN
FOR r IN
(select SO_SQL_BODY FROM SO_SUB_VARS WHERE SO_SQL_BODY IS NOT NULL
)
LOOP
sql_str := r.SO_SQL_BODY;
EXECUTE immediate sql_str INTO res;
dbms_output.put_line(sql_str);
dbms_output.put_line('***********************');
dbms_output.put_line(res);
dbms_output.put_line('***********************');
END LOOP;
END;
/
Try this - iterate to not null records - execute them and print the result.This script works supposing the fact that SO_SQL_BODY contains a query which projects only one column.Also if the projection is with more than two columns then try to use a refcursor and dbms_sql package
İf var_names(indx).SO_SQL_BODY output is a runnable sql text;
CREATE or replace PROCEDURE a_proc
AS
CURSOR var_cur IS
select SO_SQL_BODY FROM SO_SUB_VARS group by SO_SQL_BODY;
var_t var_cur%ROWTYPE;
TYPE var_ntt IS TABLE OF var_t%TYPE;
var_names var_ntt;
BEGIN
OPEN var_cur;
FETCH var_cur BULK COLLECT INTO var_names;
CLOSE var_cur;
FOR indx IN 1..var_names.COUNT LOOP
DBMS_OUTPUT.PUT_LINE(var_names(indx).SO_SQL_BODY);
EXECUTE IMMEDIATE var_names(indx).SO_SQL_BODY;
END LOOP;
END a_proc;
You don't need a full cursor for this example. An implicit one would make it a lot shorter.
create or replace procedure a_proc is
lReturnValue varchar2(250);
begin
for q in (select so_sql_body from so_sub_vars group by so_sql_body)
loop
execute immediate q.so_sql_body into lReturnValue;
dbms_output.put_line(lReturnValue);
end loop;
end a_proc;
You should add an exception handler that will care for cases where there is a bad SQL query in your table. Also note that executing querys saved in a database table is your entry point to SQL injection.
I want to a run a stored procedure for almost 1000 records (P_SHIPMENT_GID) in one go and below is the pseudo code.
DECLARE
P_SHIPMENT_GID VARCHAR2(200);
BEGIN
P_SHIPMENT_GID := NULL;
ULE_PKG_UNPLANNED_ICT_CALC.UNPLANNED_ICT_CALC(
P_SHIPMENT_GID => P_SHIPMENT_GID
);
END;
How can I achieve this with or without using cursors?
It is not all that clear what you want to do (where are the 1000 records from?) but here is a "pattern" I am pretty sure you can use :
BEGIN
FOR i IN (SELECT table_name, status FROM user_tables) LOOP
dbms_output.put_line('name : ' || i.table_name ||
' status : ' || i.status);
END LOOP;
END;
This creates a loop on an implicit cursor and allows you to use the returned rows/column in a readable way.
You can write this anonymous block for your requirement. Although its not clear from where you are storing your SHIPMENT_GID values which you wanted to pass to your procedure/pkg.
BEGIN
FOR rec IN ( --Assuming your shipmentid are stored in a table
SELECT SHIPMENT_GID
FROM Your_TABLE)
LOOP
ULE_PKG_UNPLANNED_ICT_CALC.UNPLANNED_ICT_CALC (
P_SHIPMENT_GID => rec.SHIPMENT_GID);
END LOOP;
END;
I want to select data from a table in a remote database which I have its database link in a variable, how I can do that?
My query is something like this:
select `table_column` form any_table#:any_variable_1 where any_column= :any_variable_2;
Note:
any_variable_1 is a string variable contains the name of the database link
any_variable_2 is a string variable contains the string for filtering
* this code is to be executed in function in powerbuilder 8 or 9
* the database which I am connecting to is oracle 11 g
Try this:
DECLARE
l_var number(10); -- data type you are expecting from the table_column column
l_cursor sys_refcursor;
l_any_variable_1 varchar2(50) := 'YOUR_DBLINK_HERE';
l_any_variable_2 varchar2(50);
BEIGN
open l_cursor for 'select table_column from any_table# '||
l_any_variable_1 ||
' where any_column = :any_variable_2'
using l_any_variable_2;
loop
fetch l_cursor into l_var;
exit when l_cursor%NOTFOUND;
DBMS_OUTPUT.put_line(l_var);
end loop;
close l_cursor;
END;
string ls_sql
ls_sql="Select column_name from table_name#"+var_db_link_name+""+&
" where column_name='"+var_value+"' and another_column_name='"+another_var+"'"
DECLARE var_cursor DYNAMIC CURSOR FOR SQLSA ;
PREPARE SQLSA FROM :ls_sql ;
OPEN DYNAMIC var_cursor ;
FETCH var_cursor INTO :another_var ;//another_var holds the result of the cursor
CLOSE var_cursor;