Passing a table to run in execute command in oracle - sql

I need to write multiple statements given below
EXECUTE ssc.iqv_calculation ('PWCD_PRODUCT_CATEGORY', 'PRODUCT_CATEGORY');
EXECUTE ssc.iqv_calculation ('PWCD_CONTRACTING_LOCATION', 'CONTRACTING_LOCATION');
EXECUTE ssc.iqv_calculation ('PWCD_CNTRY_INCORPORATION', 'CNTRY_INCORPORATION');
EXECUTE ssc.iqv_calculation ('PWCD_COUNTRY_OF_OPERATIONS', 'COUNTRY_OF_OPERATIONS');
EXECUTE ssc.iqv_calculation ('PWCD_XBORDER_ACTIVITY', 'XBORDER_ACTIVITY');
EXECUTE ssc.iqv_calculation ('PWCD_APPROVED_EXCHANGE', 'APPROVED_EXCHANGE');
EXECUTE ssc.iqv_calculation ('PWCD_LEGAL_STRUCTURE', 'LEGAL_STRUCTURE');
These are few but I need to write 100 such statements.
How can I send them in a loop given that I have a table containing two columns having the list of the two parameters.
One way is excel. How can I do it in Oracle itself.

begin
for rec in (select param1, param2 from your_table) loop
execute immediate 'begin ssc.iqv_calculation(:1, :2); end;'
using
in rec.param1,
in rec.param2;
end loop;
end;
/
Enjoy.

Related

Is it possible to run a stored procedure in Oracle for loop?

I have a question about a possibility. I have created a stored procedure in Oracle database version 12c. It takes one parameter in order to run. So that it runs correctly by passing the parameter as following:
EXEC My_Procedure_Name(parameter_value);
And everything goes well by running above code.
Now, I am going to run this procedure (in fact the above code) for two months on a daily basis. Therefore, I have wrote a script like this:
declare stmt varchar2(100);
begin
for i in (days of months)
loop
stmt:='EXEC My_Procedure_Name(parameter_value);';
EXECUTE IMMEDIATE stmt;
commit;
end loop;
end;
My question would be: is the mentioned script correct? And will it work? Is there any problem with my script?
Thanks
To call a procedure in a loop, the syntax is like this:
begin
for i in 1..5 loop
dbms_output.put_line(i);
end loop;
end;
I'm assuming that for i in (days of months) is pseudocode and you will actually use some valid construction to meet your requirement.
If you really need to use dynamic code, that can be done, but note that PL/SQL has no EXEC keyword. You would need something like:
begin
for i in 1..5 loop
execute immediate 'begin dbms_output.put_line(:i); end;' using i;
end loop;
end;
or
begin
for i in 1..5 loop
execute immediate 'call dbms_output.put_line(:i)' using i;
end loop;
end;
(Notice that PL/SQL has a ; statement terminator, but SQL does not.)
As you can see, dynamic code is more complicated so it is best to avoid it unless there is no other option.
Rather than this you may try below code without using execute immediate but just referring the loop variable -
declare stmt varchar2(100);
begin
for i in (days of months)
loop
My_Procedure_Name(i.parameter_value);
commit;
end loop;
end;

How to execute dynamic SQL statement inside Postgres sql script

Below is my script. I used Execute command to run the dynamic sql statement that i created but it doesn't run and give an output. It doesn't give an error either. How can I run this sql statement inside postgres sql script?
DO $$
DECLARE sqlCommand varchar(1000);
columnList varchar(75);
BEGIN
select '"BRANCH_NAME", "ADDRESS1"' into columnList;
select concat('SELECT ' , columnList , ' FROM "TESTSCHEMA"."BRANCH" ') into sqlCommand;
raise info 'COMMAND %', sqlCommand;
execute sqlCommand;
END $$;
Your example is safe, but if you are dealing with user input, always use the format function to construct the SQL string.
Anyway, your problem is that the EXECUTE statement has no INTO clause with a destination for the query results, si they are simply discarded.

Teradata stored procedure with dynamic parameters called from R script

I need to extract some data from Teradata to process in R. I have around 84 Dep/sec keys with most of them having a different time span so my thought was to create a stored procedure in Teradata that will accept the Dep, Sec and Dates as parameters. I could then loop over the list in R calling the SP each time to create my data set.
The SP I have created to test this idea is a very simple one but I can't get it to work.
CREATE PROCEDURE procTest4 (IntN integer)
BEGIN
CALL DBC.SysExecSQL('SELECT top' || IntN || '*
from TableName');
END;
Teradata does create the SP but I don't know how to execute it and pass the paramters to it. When I try:
Call procText4(10)
I get the following error:
5568: SQL statement is not supported within a stored procedure.
The only other option for me is to create the SQL string in R and then run it from there but there is multiple passes of SQL which create volatile tables and the RODBC package doesn't seem to like them, plus it's a very messy way of doing it.
Any help is much appreciated.
The syntax for returning a result set from a Stored Procedure using Dynamic SQL is a bit complex:
CREATE PROCEDURE procTest4 (IntN INTEGER)
DYNAMIC RESULT SETS 1
BEGIN
DECLARE SqlStr VARCHAR(1000);
DECLARE rslt CURSOR WITH RETURN ONLY FOR stmt;
SET SQLStr = 'SELECT top ' || IntN || ' * from TableName';
PREPARE stmt FROM SqlStr;
OPEN rslt;
END;
But you should double check if you can rewrite those loops...

Oracle Native Dynamic SQL PL/SQL statement without begin and end

I have the problem of creating a backup for a table by creating a series of insert statements.
The input is the table name and each table can have a different number of columns. It is assumed that data types can be varchar2, number, or date only
so I have this line of code:
execute immediate fetchStmt;
where fetchStmt can be:
fetch tableColCursor into valuesArray(1), valuesArray(2), ..., valuesArray(n)
This just fetches each row from the cursor and puts it into a varray, the statements itself works if it is not in an execute immediate statement.
I do know that an execute immediate can only process SQL queries or PL/SQL blocks.
The problems is how would I be able to make this work or what can be a similar solution to the problem?
Note that it is not known during compile time the table and its columns and their data types
EXECUTE IMMEDIATE can only process full statements, i-e: SQL statements or PLSQL blocks (with [DECLARE]..BEGIN..END).
Furthermore, a block executed this way won't see any variables from the calling block (they don't share the same scope), for instance this won't work:
DECLARE
l NUMBER := 1;
k NUMBER := 0;
BEGIN
EXECUTE IMMEDIATE 'BEGIN l := k; END;';
END;
The above code will produce an error because l and k are not defined in the sub-block. Instead you would need to use input/output variables:
DECLARE
l NUMBER := 1;
k NUMBER := 0;
BEGIN
EXECUTE IMMEDIATE 'BEGIN :P1 := :P2; END;' USING OUT l, k;
dbms_output.put_line(l); -- return 0
END;
In your case you don't know the number of variables so you won't be able to use EXECUTE IMMEDIATE. You could use DBMS_SQL but I think there are simpler methods: you could find already working code (it exists within Oracle APEX for instance), or you could program it yourself by running a SELECT that would produce the necessary INSERT string. For this method you would have to generate the SQL statement dynamically (dependent upon the table columns). The statement would look like this (for a table TEST(a,b,c) where all columns are integer [needs adapting for other datatypes]):
SELECT 'INSERT INTO test(a,b,c) VALUES ('||a||', '||b||', '||c||');'
FROM test

EXECUTE IMMEDIATE ' some commands '

Is it possible to execute some sql commands within one EXECUTE IMMEDIATE block?
What is wrong with this syntax:
declare
pragma autonomous_transaction;
begin
execute immediate
'begin
COMMENT ON TABLE t1 IS ''description1'';
COMMENT ON TABLE t2 IS ''description2'';
end;';
end;
For one SQL command it works fine:
declare
pragma autonomous_transaction;
begin
execute immediate ' COMMENT ON TABLE t1 IS ''description1'' ';
end;
The begin end within the string to execute immediate is going to be treated as a PL/SQL anonymous block. DDL, such as COMMENT is not allowed in PL/SQL. If it were you wouldn't need to use execute immediate. Oracle essentially works with either a block of PL/SQL statement or a single SQL statement at a time. Though there are APIs to batch SQL statements too.
So, to run COMMENT within a PL/SQL block or procedure, you will need to execute immediate statements.
Without more context I can not intelligently comment on whether that is the right approach, or if just having the two comment statements stand alone would be better.
Well, you could do this:
begin
execute immediate
'begin
execute immediate ''COMMENT ON TABLE t1 IS ''''description1'''' '';
execute immediate ''COMMENT ON TABLE t2 IS ''''description2'''' '';
end;';
end;
But there's not much point.