Dynamic call Store Procedure (execute immediate ) Out parameters Problems - oracle

I have problem Dynamic Call Store Procedure
v_sql := 'begin '|| p_procname || '(''test1'','' test2 '',:v_output2); end;';
execute immediate v_sql
using out v_output2 ;
dbms_output.put_line(v_output2 || ' ' );
In here ı can call procedure with execute immediate .
But my problem is dynamic bind variable . This values comes from log table then i parse for execute_immediate procedure
v_sql := 'begin '|| p_procname || '(''test1'','' test2'',:v_output2); end;';
v_sql1:= ||using|| 'out v_output2 ' ;
execute immediate v_sql
v_sql1;
It doesnt work like that . How can i make dynamic variables bind , because i call a lot of procedure and thats procedure has different in and out parameters.
I hope you can understand what problem i have .How can i pass this problems thx

here is simple procedure
create procedure test_proc(p_user varchar2, p_code varchar2, p_error varchar2) is
begin
p_error := p_user || p_code;
end;
calling code for same ..
Declare
v_test_proc varchar2(50) := 'test_proc';
p_user varchar2(50) := 'test_name';
p_code varchar2(50) := 'test_code';
p_error varchar2(100);
v_sql varchar2(2000);
begin
v_sql := 'begin ' || v_test_proc || '( :1 ,:2, :3 ); end;';
execute immediate v_sql
using p_user, p_code, out p_error;
dbms_output.put_line(p_error);
end;

Related

How to create new table and insert using function in plsql?

I want to create a function in plsql to create table dynamically
Create or replace procedure p_dynamic_table (p_table varchar2,
col_specs varchar2)
as
sql_stmt varchar2 (2000);
begin
sql_stmt := 'CREATE TABLE' || p_table || '(' || col_specs || ')';
EXECUTE IMMEDIATE sql_stmt;
end;
Put a space after TABLE and before the ending single quote.
Then your procedure will "work". It will not be a function, but a procedure. Also, it is a procedure that has no added value so I don't understand why you want to code it.
Best regards,
Stew Ashton
Are you want to create Procedure or Function?
You mentioned Function in Topics header but try to create Procedure (according the mentioned code by you).
If you don't want to create constraints & Indexes then your Procedure is okay without
SQL_STMT := 'CREATE TABLE' || P_TABLE || '(' || COL_SPECS || ')';
you must be put SPACE after 'CREATE TABLE' which is already mentioned in answer of Stew Ashton.
According to what I understood, I tried to mention the solution below.
PROCEDURE
CREATE OR REPLACE PROCEDURE P_DYNAMIC_TABLE (P_TABLE VARCHAR2,
COL_SPECS VARCHAR2)
AS
SQL_STMT VARCHAR2 (2000);
BEGIN
SQL_STMT := 'CREATE TABLE ' || P_TABLE || '(' || COL_SPECS || ')';
EXECUTE IMMEDIATE SQL_STMT;
END P_DYNAMIC_TABLE;
Execute Procedure
EXEC P_DYNAMIC_TABLE('TEST_TBL','COLUMN_1 NUMBER , COLUMN_2 VARCHAR2(100), COLUMN_3 DATE');
You can try this!
create or replace procedure f2
is
begin
execute immediate 'create table &nds_ddl(&c1 &datatype)';
end;
Then execute the procedure f2
i.e
exec f2;
Select * from table_name_you_entered;

How can I use bind variable in plsql function

I have a function like this:
create or replace function params
(
p_pr varchar2,
p_qu_id varchar2,
p_date date := sysdate,
p_param varchar2 := null
)
return varchar2
as
...
sql_stmt varchar2(4000);
rc sys_refcursor;
...
BEGIN
sql_stmt := 'select parameter_name, parameter_value from ' || p_pr | '.v_view where query_id = ''' || p_qu_id || '''';
IF p_param IS NOT NULL
THEN
sql_stmt := sql_stmt || ' and parameter_value=''' || p_param || '''';
END IF;
OPEN rc FOR sql_stmt;
LOOP
FETCH rc
INTO v_param_name, v_param_value;
EXIT WHEN rc%NOTFOUND;
EXIT WHEN v_param_value is NULL;
....
DBA said this function using hard parse, I must use bind variable in this function. How can I do that?
Thanks.
I must use bind variable in this function.
The solution is to use a placeholder in the template SQL ...
sql_stmt := sql_stmt || ' and parameter_value= :p1';
... then pass the actual value with the USING clause when you open the ref cursor.
Things are slightly tricky because you are executing different statements depending on whether the parameter is populated. So you need to do something like this instead:
sql_stmt := 'select parameter_name, parameter_value from ' || p_pr
|| '.v_view where query_id =:p1';
IF p_param IS NOT NULL
THEN
sql_stmt := sql_stmt || ' and parameter_value= :p2';
OPEN rc FOR sql_stmt using p_qu_id, p_param;
else
OPEN rc FOR sql_stmt using p_qu_id;
END IF;
LOOP
Note that p_pr - a schema name - cannot be replaced with a bind variable.

DBMS_SQL.TO_REFCURSOR equivalent in Oracle 10g

I have the following code :
procedure Replace(sUser in Varchar2,sNomTable in varchar2,sColonne in varchar2,sID in Varchar2,nbCharAlterer IN NUMBER) is
l_cursor NUMBER;
l_return NUMBER;
l_ref_cursor SYS_REFCURSOR;
TYPE t_tab IS TABLE OF VARCHAR2(4000);
l_tab t_tab;
l_tab_Id t_tab;
sChaine VARCHAR2(4000 CHAR);
sqlReq CONSTANT VARCHAR2(1000):= 'select ' || sId || ',' || sColonne || ' from ' || sUser || '.' || sNomTable ;
begin
--
l_cursor := DBMS_SQL.open_cursor;
DBMS_SQL.parse(l_cursor, sqlReq, DBMS_SQL.NATIVE);
l_return := DBMS_SQL.EXECUTE(l_cursor);
-- Connvert from DBMS_SQL to a REF CURSOR.
l_ref_cursor := DBMS_SQL.to_refcursor(l_cursor);
Here I am getting the following error :
pls 00302 component 'TO_REFCURSOR' must be declared
since my oracle version is 10g.
Any idea of how to do the equivalent in Oracle 10g?
Here's how you could use native dynamic sql:
PROCEDURE p_replace(suser IN VARCHAR2,
snomtable IN VARCHAR2,
scolonne IN VARCHAR2,
sid IN VARCHAR2,
nbcharalterer IN NUMBER) IS
v_validate_sid_col_name VARCHAR2(32);
v_validate_scolonne_col_name VARCHAR2(32);
v_validate_suser VARCHAR2(32);
v_validate_snomtable VARCHAR2(32);
sqlreq VARCHAR2(2000);
refcur sys_refcur;
BEGIN
-- Check the input values are valid identifiers (to avoid sql injection)
-- N.B. this does not check they are valid object names!
v_validate_sid_col_name := dbms_assert.qualified_sql_name(sid);
v_validate_scolonne_col_name := dbms_assert.qualified_sql_name(scolonne);
v_validate_suser := dbms_assert.qualified_sql_name(suser);
v_validate_snomtable := dbms_assert.qualified_sql_name(scolonne);
sqlReq := 'select ' || v_validate_sid_col_name || ',' ||
v_validate_scolonne_col_name ||
' from ' || v_validate_suser || '.' || v_validate_snomtable;
-- or maybe you want to use execute immediate to bulk collect into arrays?
OPEN refcur FOR sqlreq;
...
END p_replace;
Note that I've changed the name of the procedure since "replace" is the name of a pre-existing built-in function, and therefore not a very good name to use.
You don't mention what it is you're going to do with the results of your query, so I wasn't sure if opening a ref cursor is what you actually need, or whether bulk collecting via execute immediate would work better for you.

How to assign a table name to a variable and using the same inside immediate execute statement

I am trying to assign table name to a variable and to use the same inside execute immediate statement , please help me with the syntax inside execute statement
scenario is
I am trying to pass a table name as parameter in the procedure and am using them inside execute immediate to write into some other table .
please suggest me the syntax for in parameters and for the execute immediate statement.
My Procedure:
CREATE OR REPLACE PROCEDURE tep
AS
v_sql VARCHAR2(1024) ;
a NUMBER;
b VARCHAR2(30) :='t_stg1_non_silicon_purchace_re';
BEGIN
v_sql := q'[SELECT COUNT(*) FROM b ]';
EXECUTE immediate v_sql INTO a;
DBMS_OUTPUT.PUT_LINE( TO_CHAR(v_sql));
DBMS_OUTPUT.PUT_LINE( TO_CHAR(a));
END;
/
You haven't specified what exactly you want to do with the table name in the execute immediate so see example below of how to "CREATE" a table.
DECLARE
vTableName VARCHAR2(40 CHAR);
vSQL VARCHAR2(1000 CHAR);
BEGIN
vTableName:='MY_TABLE_NAME';
vSQL:='CREATE TABLE ' || vTableName || ' (COL1 NUMBER, COL2 NUMBER)';
EXECUTE IMMEDIATE vSQL;
END;
/
This query may satisfy your requirement. Thanks
CREATE OR REPLACE PROCEDURE tep
AS
v_sql VARCHAR2(1024) ;
a NUMBER;
b VARCHAR2(30) :='t_stg1_non_silicon_purchace_re';
BEGIN
v_sql := 'SELECT COUNT(*) FROM'||' '||b;
EXECUTE immediate v_sql INTO a;
DBMS_OUTPUT.PUT_LINE( TO_CHAR(v_sql));
DBMS_OUTPUT.PUT_LINE( TO_CHAR(a));
END;

Print bind variables when using execute immediate

i'm trying to print out the vSQL variable after the execute immediate statement.
i know the execute immediate statement ll give ORA-00903 because u can not bind variables to tables etc.i just want to print that string after using
statement.
here is my code :
DECLARE
vSQL VARCHAR2(100);
vOwner VARCHAR2(100);
vTableName VARCHAR2(100);
vPartition VARCHAR2(100);
BEGIN
vOwner := 'STG';
vTableName := 'TEMP';
vSQL := 'ALTER TABLE :1.:2 TRUNCATE PARTITION(:3)';
EXECUTE IMMEDIATE vSQL USING vOwner,vTableName,vPartition;
--DBMS_OUTPUT.PUT_LINE(vSQL); -- Something like this
END;
thx for ideas...
As the commenters wrote you can bind only data to fields, you can't bind library object's names/etc.
So I think you can do it only without binding:
DECLARE
vSQL VARCHAR2(100);
vOwner VARCHAR2(100);
vTableName VARCHAR2(100);
vPartition VARCHAR2(100);
BEGIN
vOwner := 'STG';
vTableName := 'TEMP';
vSQL := 'ALTER TABLE ' || vOwner || '.' || vTableName || ' TRUNCATE PARTITION('||vPartition||')';
EXECUTE IMMEDIATE vSQL;
DBMS_OUTPUT.PUT_LINE(vSQL);
END;
If you know an error is going to happen, catch it and then print.
DECLARE
vSQL VARCHAR2(100);
vOwner VARCHAR2(100);
vTableName VARCHAR2(100);
vPartition VARCHAR2(100);
BEGIN
vOwner := 'STG';
vTableName := 'TEMP';
vSQL := 'ALTER TABLE :1.:2 TRUNCATE PARTITION(:3)';
EXECUTE IMMEDIATE vSQL USING vOwner,vTableName,vPartition;
EXCEPTION --The error will get catched here.
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE(vSQL); --This will print exactly 'ALTER TABLE :1.:2 TRUNCATE PARTITION(:3)'
--If you want to print it with the variables do something like:
DBMS_OUTPUT.PUT_LINE('ALTER TABLE ' || vOwner || ', ' || vTableName || ', ' || vPartition;
END;

Resources