EXECUTE IMMEDIATE ' some commands ' - sql

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.

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;

Execute Oracle SQL command after PL/SQL block

I've an SQL file which has some PL/SQL scripts and some DML scripts, but I'm not able to run normal DML commands just after a PL/SQL block IN SQL Developer. For e.g.
BEGIN
-- Some Statements
END;
UPDATE TABLE TABLE_NAME SET FLD_NAME = SOMETHING;
Do I need to change anything here so that I can run these commands.
PS: I don't want to put everything in BEGIN ... END block.
try put / after anonymous block:
BEGIN
-- Some Statements
END;
/
UPDATE TABLE TABLE_NAME SET FLD_NAME = SOMETHING;

Trigger pl/sql insert data on table

i'm new in pl/sql. I'm trying to create a trigger that insert datas in specific tables.
I have datas that arrives in real-time on my table EV_48h. To know on which table I have to insert the data i have to know it Ref_equip (Ref_equip is on an other table named C_Equip).
I've made quickly this littre merise to be more understandable:
merise
As I said I have data that arrives on real-time on the table EV_48H and I have to put them automatically on the tables that are named 'EVV_'+Ref_equip.
So, here is my code. I don't have any error but it don't work. I know i missed of forget something but i don't know what.
TRIGGER "SIVO"."NEWtrigger3EV_48H"
BEFORE INSERT
ON SIVO.EV_48H
REFERENCING NEW AS NEW OLD AS OLD
FOR EACH ROW
declare
clef_var number(4,0);
ref_equip varchar2(40);
V_Nom_table varchar2(1000) ;
V_nom_seq Varchar2(2000) ;
stmt varchar2(200);
begin
SELECT clef_var
INTO :New.Clef_Var
FROM sivo.c_variable
WHERE Ref_Var= :new.Ref_Var;
-- Conversion des formats Date-Heure en DateHeure oracle
:New.EV_DATEAUTO := to_date(:New.EV_DATE || ' ' || :New.EV_HEURE, 'DD/MM/YY HH24:MI:SS');
stmt:='begin select clef_var into :New.Clef_Var From sivo.C_variable; end';
EXECUTE IMMEDIATE stmt using out clef_var;
IF clef_var is not null then
stmt :='begin select Ref_equip into :New.Ref_Equip FROM sivo.C_Equip WHERE Ref_var= :New.Ref_Var; end';
EXECUTE IMMEDIATE Stmt USING OUT Ref_Equip;
V_nom_table := 'EVV_'||Ref_Equip;
stmt :='insert into' ||V_nom_table || '(:New.Clef_Var, :New.Ev_DateAuto, :New.Ev_Valeur )';
EXECUTE IMMEDIATE stmt USING Ref_Equip;
ELSE
INSERT INTO SIVO.EV_48H_VAR_INCONNUES (REF_VAR, EV_DATE, EV_HEURE, EV_VALEUR)
VALUES ( :New.REF_VAR, :New.EV_DATE, :New.EV_HEURE, :New.EV_VALEUR);
end if;
END;
If someone can help me or put me on the right way. I don't know if I give all informations so tell me if I missed something.
Thanks
In your execute immediate you are missing the end of statement indicator colon after END
this should be
begin select clef_var into :New.Clef_Var From sivo.C_variable; end;
However there are other design choices that you should be aware of:
using execute immediate is handy but if you don't have to use it you shouldn't. The work can be done by a cursor or even a simple select statement if only one value will come back. In fact it appears you do the work twice. First you insert into the :new.clef_var then you do the same thing again with the execute immediate. Try commenting out the execute immediate.
by using execute immediate any errors are harder to track
using a trigger means the real time data source cannot end the transaction until the trigger completes. Why not run a scheduled job every minute to check for new data and process it? This breaks the transaction into two parts: data entry and data processing
is there any update of records that your process needs to capture?

Passing a table to run in execute command in oracle

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.

SQL - Oracle Functions using variables for schema names

I am writing some oracle stored procedures where we have conditional logic which effects which schema we are working from and I am not sure how to do this in the sql for the stored proc. If I am working with prepared statements then its fine but in the scenario where I am just executing a query to say populate another variable then I dont know how to do this. For example
PROCEDURE register (
incustomer_ref in VARCHAR2,
incustomer_type in VARCHAR2,
outreturn_code out VARCHAR2
)
IS
customer_schema varchar2(30);
record_exists number(1);
BEGIN
if incustomer_type='a' then
customer_schema:='schemaA';
elsif incustomer_type='b' then
customer_schema:='schemaB';
end if;
--This type of command I cant get to work
select count(*) into record_exists from **customer_schema**.customer_registration where customer_ref=incustomer_ref
--but a statement like this i know how to do
if record_exists = 0 then
execute immediate 'insert into '||customer_schema||'.customer_registration
values ('||incustomer_ref||','Y',sysdate)';
end if;
Can anyone shine some light on what I am missing here.
Cheers
you can use execute immediate also for select statment:
execute immediate 'select count(*) from '|| customer_schema
|| '.customer_registration where customer_ref= :b1'
into record_exists using incustomer_ref;