views:

40

answers:

1

Building on Tony's answer on this question:

If I want to do something like this,

CREATE PROCEDURE A(tab IN VARCHAR2) IS
tab.col_name <column> --static declaration (column name always remains the same)
BEGIN
   EXECUTE IMMEDIATE 'INSERT INTO ' || tab(col_name) || 'VALUES(123)';
END A;

How can I use Dynamic SQL in the above case?

+2  A: 

This example passes in a table name and a column name:

CREATE PROCEDURE A
  ( tab IN VARCHAR2
  , col_name IN VARCHAR2
  ) IS
BEGIN
   EXECUTE IMMEDIATE 'INSERT INTO ' || tab || '(' || col_name || ') VALUES(123)';
END A;

You need to realise that everything after EXECUTE IMMEDIATE must be a string that contains some valid SQL. A good way to verify this is to set it up in a variable and print it to the screen:

CREATE PROCEDURE A
  ( tab IN VARCHAR2
  , col_name IN VARCHAR2
  ) IS
   v_sql VARCHAR2(2000);
BEGIN
   v_sql := 'INSERT INTO ' || tab || '(' || col_name || ') VALUES(123)';
   DBMS_OUTPUT.PUT_LINE('SQL='||v_sql);
   EXECUTE IMMEDIATE v_sql;
END A;

This should then display something like the following in SQL Plus:

SQL=INSERT INTO mytable(mycolumn) VALUES(123)

(provided server output is turned on).

EDIT: Since you want the column name to be a local variable that always has the same value, this could be done as:

CREATE PROCEDURE A (tab IN VARCHAR2)
IS
   col_name VARCHAR2(30) := 'MYCOLUMN';
   v_sql VARCHAR2(2000);
BEGIN
   v_sql := 'INSERT INTO ' || tab || '(' || col_name || ') VALUES(123)';
   DBMS_OUTPUT.PUT_LINE('SQL='||v_sql);
   EXECUTE IMMEDIATE v_sql;
END A;
Tony Andrews
@Tony Andrews: What if I do not want to pass a column name as parameter but instead want to **declare** it in the procedure. Is that possible?
Amoeba
Will the column name always be the same? If not, is your procedure supposed to somehow find out? Please explain further what you need.
Tony Andrews
@Tony: yes, the column name is always supposed to be the same.
Amoeba
OK, I will update my answer then.
Tony Andrews