Dynamic Procedure Execution - oracle

Hi I have to execute a remote call ...
DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO#DB_LINK()
... from a stored procedure.
As the value of DB_LINK is to be obtained during runtime. It should be executed dynamically. I tried to use
EXECUTE IMMEDIATE ' DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO#'||DB_LINK||'()';
But I get the following error
ORA-00900: invalid SQL statement
Can anyone advise me on how to execute the Stored Procedure dynamically?

The clue lies in the precise wording of the error message: invalid SQL statement. As the PL/SQL manual says, EXECUTE IMMEDIATE is for executing dynamic SQL statements.
You are executing a procedure call i.e. PL/SQL not SQL. So you need to pass an anonymous block to EXECUTE IMMEDIATE:
EXECUTE IMMEDIATE
'begin DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO#'||DB_LINK||'() ; end;'
;
DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO takes no parameters, so the empty brackets are optional. By all means include them if they make you feel happier.

EXECUTE IMMEDIATE 'DBMS_STATS.FLUSH_DATABASE_MONITORING_INFO#'||DB_LINK();
should work if DB_LINK is a global function returning a VARCHAR2 string.

Related

Variable not being replaced (learning Dynamic PL/SQL)

The below code returns error ORA-00942: table or view does not exist, I think may be because PL/SQL runtime engine(or something I don't know what) is trying to treat table_in as a Table but why would it do so, I have already table_in declared as variable.
The ex26011601 table exists with values in the same schema.
set serveroutput on
declare
function tabcount (table_in in varchar2)
return pls_integer
is
l_return pls_integer;
begin
select count(*) into l_return from table_in;
return l_return;
end;
begin
dbms_output.put_line(tabcount('ex26011601'));
end;
I understand EXECUTE IMMEDIATE would solve the purpose. What I am trying to get is why is it necessary and whats wrong with current statement that 'table_in' could not be treated as variable even after being declared in the scope. Or what is the reason why a variable is not expected there?
I understand EXECUTE IMMEDIATE would solve the purpose. What I am
trying to get is why is it necessary and whats wrong with current
statement that 'table_in' could not be treated as variable even after
being declared in the scope.
As per oracle documentation : Static SQL
A PL/SQL static SQL statement can have a PL/SQL identifier wherever its SQL counterpart can have a placeholder for a bind variable. The PL/SQL identifier must identify either a variable or a formal parameter.To use PL/SQL identifiers for table names, column names, and so on, use the EXECUTE IMMEDIATE statement
In PL/SQL, you need dynamic SQL to run when :
SQL whose text is unknown at compile time
For example, a SELECT statement that includes an identifier that is unknown at compile time (such as a table name) or a WHERE clause in
which the number of sub clauses is unknown at compile time.
SQL that is not supported as static SQL
Dynamic SQL
Yes, as you said oracle pl/sql syntax does not allowing that, pass table name by variable. As you also said you can do it only by dynamic sql and execute immediate:
execute immediate 'select count(*) from ' || table_in
into l_return;

Procedure is not working on Oracle database

I am trying to write a simple "Hello World" procedure .... but it is not working
Code :
CREATE OR REPLACE PROCEDURE greetings
AS
BEGIN
dbms_output.put_line('Hello World!');
END;
/
After that I executed it like this :
EXECUTE greetings;
but I get an error :
ORA-00900: invalid SQL statement
Images are here :
Please help out as soon as possible ...thanks :)
I believe EXECUTE is a SQL*Plus statement. It's not a valid SQL statement.
The error message being returned ORA-00900: invalid SQL statement makes it appear that the client you are using is not emulating the SQL*Plus EXEC statement.
The general form for executing a PL/SQL procedure is to execute an anonymous PL/SQL block.
BEGIN greetings(); END;
/

How to execute procedure in APEX SQL script?

I am trying to understand how to use multiple procedures in APEX SQL script. First I don't really need stored procedure, but not sure how to declare simple procedure in APEX SQL script. So this is my attempt:
create or replace procedure test1 as
begin
DBMS_OUTPUT.ENABLE;
dbms_output.put_line('test1');
end;
execute test1;
This gives me an error:
Error at line 7: PLS-00103: Encountered the symbol "EXECUTE"
So questions - how to create regular/not stored/ procedures in one SQL script and then call them. What is the entry point of execution in APEX SQL script?
UPD (At the first time I understood question totally wrong)
Correct version of a script:
create or replace procedure test1 as
begin
DBMS_OUTPUT.ENABLE;
dbms_output.put_line('test1');
end;
/
begin
test1;
end;
/
Documentation says, that script can contain inly SQL and PL/SQL commands. Commands of sqlplus will be ignored.
OLD VERSION (Let stay here)
In APEX pages you can use PL/SQL anonymous blocks. For example, you can create process (APEX has some types of them) or PL/SQL region, and use following:
declare
...
begin
some_proc(:P_MY_ITEM);
end;
Here you can invoke any procedure and do anything else that allowed by PL/SQL. Also you can use parameters like :P_ITEM_NAME to get and set values of page and application items.

Oracle: What does 'execute immediate' mean?

What is the significance of execute immediate in PL/SQL when used with DML and DDL statements? Does execute immediate implicitly commit to a database like DDL statements do ?
The following is an example I have encountered:
SELECT 'TRUNCATE TABLE BD_BIDS_APPR_DET' INTO V_SQL1 FROM DUAL;
EXECUTE IMMEDIATE V_SQL1;
SELECT 'TRUNCATE TABLE BD_BIDS_SYS_DET' INTO V_SQL1 FROM DUAL;
EXECUTE IMMEDIATE V_SQL1;
SELECT 'TRUNCATE TABLE BD_BIDS_EXT_DET' INTO V_SQL1 FROM DUAL;
EXECUTE IMMEDIATE V_SQL1;
It is for running native dynamic SQL.
For DML you'd use it when running statements that you don't have available at compile time, e.g. if the column list is based on a selection from the user.
In your case it's being used because DDL cannot be run as static SQL from within PL/SQL. Only certain query, DML and TCL commands are valid. Anything else has to be treated as dynamic.
I'd say it's rare to need to use DDL from a PL/SQL block. TRUNCATE might be reasonable; if you find anything creating or dropping objects on the fly then that might be more of a concern as it can suggest a suboptimal data model.
EXECUTE IMMEDIATE itself does not automatically commit; but if you execute DDL then that will behave the same as if you ran it outside PL/SQL, so it will commit in your case, yes.
Incidentally, I'm not sure why your code is using an intermediate variable to hold the statement; that's useful if you want to display what it's going to run maybe, but you don't seem to be doing that. What you have could be done as:
EXECUTE IMMEDIATE 'TRUNCATE TABLE BD_BIDS_EXT_DET';
i.e. without using V_SQL_1 at all.
It provides end-to-end support when executing a dynamic SQL statement or an anonymous PL/SQL block. It substitutes the unknown values, executes the statement, returns the data, and then releases the resources.
EXECUTE IMMEDIATE [dynamic SQL string statement without terminator]
[INTO {define_variable [, define_variable] ... | record}]
[USING [IN|OUT|IN OUT] bind_argument [, [IN|OUT|IN OUT] bind_arguments] ];
define_variable is a PL/SQL variable or record that captures the result set of the SELECT query
Bind arguments are the actual values or local variables which would replace the bind variables in the SQL string statement.

Truncating a table in a stored procedure

When I run the following in an Oracle shell it works fine
truncate table table_name
But when I try to put it in a stored procedure
CREATE OR REPLACE PROCEDURE test IS
BEGIN
truncate table table_name;
END test;
/
it fails with
ERROR line 3, col 14, ending_line 3, ending_col 18, Found 'table', Expecting: # ROW or ( or . or ; :=
Why?
All DDL statements in Oracle PL/SQL should use Execute Immediate before the statement. Hence you should use:
execute immediate 'truncate table schema.tablename';
As well as execute immediate you can also use
DBMS_UTILITY.EXEC_DDL_STATEMENT('TRUNCATE TABLE tablename;');
The statement fails because the stored proc is executing DDL and some instances of DDL could invalidate the stored proc. By using the execute immediate or exec_ddl approaches the DDL is implemented through unparsed code.
When doing this you neeed to look out for the fact that DDL issues an implicit commit both before and after execution.
try the below code
execute immediate 'truncate table tablename' ;
You should know that it is not possible to directly run a DDL statement like you do for DML from a PL/SQL block because PL/SQL does not support late binding directly it only support compile time binding which is fine for DML. hence to overcome this type of problem oracle has provided a dynamic SQL approach which can be used to execute the DDL statements.The dynamic sql approach is about parsing and binding of sql string at the runtime.
Also you should rememder that DDL statements are by default auto commit hence you should be careful about any of the DDL statement using the dynamic SQL approach incase if you have some DML (which needs to be commited explicitly using TCL) before executing the DDL in the stored proc/function.
You can use any of the following dynamic sql approach to execute a DDL statement from a pl/sql block.
1) Execute immediate
2) DBMS_SQL package
3) DBMS_UTILITY.EXEC_DDL_STATEMENT (parse_string IN VARCHAR2);
Hope this answers your question with explanation.

Resources