Well I have an dynamic variable
private_table_name VARCHAR2(100) := 'test';
test is the name of the table.
Now I want to insert into the table with this satatement.
INSERT INTO private_table_name VALUES (employee_rec.employee_id, concaternate_employee_name(employee_rec.employee_id), employee_rec.salary * 1.10);
It is dynamic SQL you should use. For example:
SQL> CREATE TABLE test
2 (
3 price NUMBER
4 );
Table created.
SQL> DECLARE
2 private_table_name VARCHAR2 (100) := 'test';
3 BEGIN
4 EXECUTE IMMEDIATE 'insert into '
5 || private_table_name
6 || ' (price) values (50)';
7 END;
8 /
PL/SQL procedure successfully completed.
SQL> SELECT * FROM test;
PRICE
----------
50
SQL>
Related
CREATE OR REPLACE PROCEDURE myStoredProcedure (idParam IN VARCHAR2,
outputParam OUT VARCHAR2)
AS
BEGIN
SELECT OUTPUTCOL INTO outputParam FROM MyTable WHERE ID = idParam;
END;
DECLARE
v_OutputResults VARCHAR2(20);
BEGIN
myStoredProcedure('123', v_OutputResults);
SELECT v_OutputResults AS ColumnResult FROM DUAL;
END;
If we understand your goal, you should be using a function, not a procedure:
First, we set up the example:
SQL> -- conn system/halftrack#pdb01
SQL> conn scott/tiger#pdb01
Connected.
SQL> --
SQL> CREATE TABLE my_table (
2 user_id number not null,
3 Name varchar2(10)
4 )
5 ;
Table created.
SQL> --
SQL> insert into my_table values (1,'Bob');
1 row created.
SQL> insert into my_table values (2,'Carol');
1 row created.
SQL> insert into my_table values (3,'Ted');
1 row created.
SQL> insert into my_table values (4,'Alice');
1 row created.
SQL> commit;
Commit complete.
SQL> select * from my_table;
USER_ID NAME
---------- ----------
1 Bob
2 Carol
3 Ted
4 Alice
4 rows selected.
Now we create the function, then use it:
SQL> --
SQL> create or replace function my_function (id_param number)
2 return varchar2
3 is
4 v_name varchar2(10);
5 begin
6 select name
7 into v_name
8 from my_table
9 where user_id = id_param
10 ;
11 --
12 return v_name;
13 end;
14 /
Function created.
SQL> show errors
No errors.
SQL> --
SQL> select my_function(1) from dual;
MY_FUNCTION(1)
--------------------------------------------------------------------------------
Bob
1 row selected.
And clean up our example:
SQL> --
SQL> drop table my_table purge;
Table dropped.
No but you can do so using a stored function.
I tried to write a PL/SQL function having as parameters a tablename and a column name, which returns the result of the query as a table.
Here's what I tried:
CREATE TYPE TABLE_RES_OBJ AS OBJECT (
employee_id number(30) ,
person_id number(30),
joined_year number(4),
salary number(20,2),
qualification varchar2(45),
department varchar2(45)
);
/
create TYPE table_ret as TABLE OF table_res_obj;
/
create or replace function select_custom(p_tablename varchar2, p_colname varchar2 ) return table_ret
is
ret table_ret;
query_txt varchar2(100) := 'SELECT :a from :b';
begin
execute immediate query_txt bulk collect into ret using p_colname, p_tablename;
return ret;
end select_custom;
As you can see, this is not that general as wanted, but still not working, it says the table doesn't exist, even when I try to run it with an existing table.
Exactly, it won't work that way. You'll have to concatenate table and column name into the select statement. For (simple) example:
SQL> create or replace type table_res_obj as object
2 (ename varchar2(20));
3 /
Type created.
SQL> create or replace type table_ret as table of table_res_obj;
2 /
Type created.
SQL> create or replace function select_custom
2 (p_tablename varchar2, p_colname varchar2 )
3 return table_ret
4 is
5 ret table_ret;
6 query_txt varchar2(100);
7 begin
8 query_txt := 'select table_res_obj(' || dbms_assert.simple_sql_name(p_colname) ||') from ' ||
9 dbms_assert.sql_object_name(p_tablename);
10 execute immediate query_txt bulk collect into ret;
11 return ret;
12 end select_custom;
13 /
Function created.
Does it work?
SQL> select select_custom('dept', 'deptno') from dual;
SELECT_CUSTOM('DEPT','DEPTNO')(ENAME)
--------------------------------------------------------------------------------
TABLE_RET(TABLE_RES_OBJ('10'), TABLE_RES_OBJ('20'), TABLE_RES_OBJ('30'), TABLE_R
ES_OBJ('40'))
SQL>
I am executing the below procedure from SQL DEVELPER, I get an option to insert the input values for z_id & i_type however i_data is greyed out.
can a procedure with input param as collection cannot be executed from SQL
DEVELOPER tool ?
What am I missing here ? The code gets compiled but unable to execute it through SQL Developer
below is what I have done but this gives compilation error on Oracle 19c
create or replace type my_type AS OBJECT (
p_id number,
p_text varchar2 (100),
p_details clob);
/
create or replace type tab1 is table of my_type;
/
create or replace procedure vehicle_det (z_id in varchar2, i_type in varchar2, i_data in tab1)
IS
BEGIN
for i in 1..i_data.count
LOOP
if (i_type ='BMW')
THEN
UPDATE STOCK_DATA
set stock_id=i_data(i).p_id, stock_des=i_data(i).p_text, clearance=i_data(i).p_details where s_id=z_id ;
end if;
end loop;
end vehicle_det;
Below is the error, please provide your wisdom::::
**ERROR --ORA-06531 Reference to uninitialized collection **
Here's code that actually works. See how it is done.
Types and sample table:
SQL> create or replace type my_type AS OBJECT (
2 p_id number,
3 p_text varchar2 (100),
4 p_details clob);
5 /
Type created.
SQL> create or replace type tab1 is table of my_type;
2 /
Type created.
SQL> create table stock_data
2 (s_id number,
3 stock_id number,
4 stock_des varchar2(20),
5 clearance clob);
Table created.
SQL> insert into stock_data
2 select 1 s_id, 1 stock_id, 'Description' stock_Des, null clearance
3 from dual;
1 row created.
SQL>
Procedure:
SQL> create or replace procedure vehicle_det
2 (z_id in varchar2, i_type in varchar2, i_data in tab1)
3 IS
4 BEGIN
5 for i in 1..i_data.count LOOP
6 if i_type = 'BMW' THEN
7 UPDATE STOCK_DATA
8 set stock_id = i_data(i).p_id,
9 stock_des = i_data(i).p_text,
10 clearance = i_data(i).p_details
11 where s_id = z_id ;
12 end if;
13 end loop;
14 end vehicle_det;
15 /
Procedure created.
Testing: current table contents / run the procedure / see the result:
SQL> select * from stock_data;
S_ID STOCK_ID STOCK_DES CLEARANCE
---------- ---------- -------------------- ------------------------------
1 1 Description
SQL> declare
2 l_data tab1 := tab1();
3 begin
4 l_data.extend;
5 l_data(1) := my_type(1, 'This is BMW', 'Oh yes, this IS a BMW!');
6
7 vehicle_det(1, 'BMW', l_data);
8 end;
9 /
PL/SQL procedure successfully completed.
SQL> select * from stock_data;
S_ID STOCK_ID STOCK_DES CLEARANCE
---------- ---------- -------------------- ------------------------------
1 1 This is BMW Oh yes, this IS a BMW!
SQL>
I have a stored procedure where a string parameter need to be passed to a create a view, I am facing difficulty to enclose the string in single quotes
EXECUTE IMMEDIATE
'CREATE VIEW view_Exec_Data as
Select * from Employees
where exec_id='''' ||To_NChar(EID)||''''; --EID is input parameter and value will be 9DE4D0106D1F390EE0
Above query is generated as
EXECUTE IMMEDIATE
'CREATE VIEW view_Exec_Data as
Select * from Employees
where exec_id='9DE4D0106D1F390EE0;
Single quote at the end is missing, not sure where I am doing wrong.
We lack some info; for example, I wonder why you used TO_NCHAR ... do you really need it?
Here's an example which presumes that employees table looks like this:
SQL> create table employees (exec_id varchar2(30), name varchar2(30));
Table created.
SQL> insert into employees values ('9DE4D0106D1F390EE0', 'Littlefoot');
1 row created.
SQL> select * From employees;
EXEC_ID NAME
------------------------------ ------------------------------
9DE4D0106D1F390EE0 Littlefoot
A procedure which creates a view. I'd suggest NOT to do that. Do you really really want to have zillion views, one per each EXEC_ID someone uses as a parameter? What's the purpose of doing that? Why don't you simply
select * from employees where exec_id = :par_eid;
Anyway, here you go: in order to make that many single quotes simpler, I used q-quoting mechanism.
SQL> create or replace procedure p_crv (par_eid in employees.exec_id%type)
2 is
3 l_str varchar2(200);
4 begin
5 l_str := q'[CREATE or replace VIEW view_Exec_Data as
6 Select * from Employees
7 where exec_id= to_nchar(']' || par_eid || q'[')]';
8
9 -- when using dynamic SQL, **ALWAYS** check whether command is properly written
10 dbms_output.put_line(l_str);
11
12 -- if it looks OK, then execute it
13 execute immediate l_str;
14 end;
15 /
Procedure created.
SQL> set serveroutput on
SQL> exec p_crv('9DE4D0106D1F390EE0');
CREATE or replace VIEW view_Exec_Data as
Select * from Employees
where exec_id= to_nchar('9DE4D0106D1F390EE0')
PL/SQL procedure successfully completed.
SQL> select * From view_exec_data;
EXEC_ID NAME
------------------------------ ------------------------------
9DE4D0106D1F390EE0 Littlefoot
SQL>
If you don't need to_nchar, it gets somewhat simpler:
SQL> create or replace procedure p_crv (par_eid in employees.exec_id%type)
2 is
3 l_str varchar2(200);
4 begin
5 l_str := q'[CREATE or replace VIEW view_Exec_Data as
6 Select * from Employees
7 where exec_id= ']' || par_eid || q'[']';
8
9 -- when using dynamic SQL, **ALWAYS** check whether command is properly written
10 dbms_output.put_line(l_str);
11
12 -- if it looks OK, then execute it
13 execute immediate l_str;
14 end;
15 /
Procedure created.
SQL> exec p_crv('9DE4D0106D1F390EE0');
CREATE or replace VIEW view_Exec_Data as
Select * from Employees
where exec_id= '9DE4D0106D1F390EE0'
PL/SQL procedure successfully completed.
SQL> select * From view_exec_data;
EXEC_ID NAME
------------------------------ ------------------------------
9DE4D0106D1F390EE0 Littlefoot
SQL>
You can use:
EXECUTE IMMEDIATE
'CREATE VIEW view_Exec_Data as
Select * from Employees
where exec_id=To_NChar(''' || EID ||''')';
-- ^ 3 (') ^ 3 + 1 (')
Update
Working for me. See this:
SQL> set serverout on
SQL> declare
2 EID varchar2(100) := '9DE4D0106D1F390EE0';
3 begin
4 DBMS_OUTPUT.PUT_LINE('CREATE VIEW view_Exec_Data as
5 Select * from Employees
6 where exec_id=To_NChar(''' || EID ||''')');
7 end;
8 /
CREATE VIEW view_Exec_Data as
Select * from Employees
where
exec_id=To_NChar('9DE4D0106D1F390EE0')
PL/SQL procedure successfully completed.
SQL>
In a stored procedure I am filtering out list of employees whose role is SUPER.ADMIN
In such a case I used like expression as below
Emp.Role_nm Like ''''||p_rolenm||''''
p_rolenm I have mentioned in stored procedure as VARCHAR2
When ever I pass a value to p_rolenm as SUPER.ADMIN it's throwing error as identifier SUPER.ADMIN is not declared.
How I can escape . (Dot) in PL/SQL statements?
Why do you use that many single quotes? You don't need any (at least, I think so):
Sample data:
SQL> create table test (id number, role varchar2(20));
Table created.
SQL> insert into test
2 select 1, 'CLERK' from dual union all
3 select 2, 'SUPER.ADMIN' from dual;
2 rows created.
SQL> select * from test;
ID ROLE
---------- --------------------
1 CLERK
2 SUPER.ADMIN
SQL> set serveroutput on;
Procedure (anonymous, though, but that doesn't matter):
SQL> declare
2 p_rolenm varchar2(20) := 'SUPER.ADMIN';
3 l_id number;
4 begin
5 select id into l_id
6 from test
7 where role = p_rolenm;
8
9 dbms_output.put_line('l_id = ' || l_id);
10 end;
11 /
l_id = 2
PL/SQL procedure successfully completed.
SQL>
If you need like, then
SQL> declare
2 p_rolenm varchar2(20) := 'PER.ADM'; --> I changed this ...
3 l_id number;
4 begin
5 select id into l_id
6 from test
7 where role like '%' || p_rolenm || '%'; --> ... and this
8
9 dbms_output.put_line('l_id = ' || l_id);
10 end;
11 /
l_id = 2
PL/SQL procedure successfully completed.
SQL>
If you used dynamic SQL, then
SQL> declare
2 p_rolenm varchar2(20) := 'PER.ADM';
3 l_id number;
4 l_str varchar2(200); --> new variable for execute immediate
5 begin
6 l_str := q'[select id from test where role like '%' || :a || '%']';
7 execute immediate l_str into l_id using p_rolenm;
8
9 dbms_output.put_line('l_id = ' || l_id);
10 end;
11 /
l_id = 2
PL/SQL procedure successfully completed.
SQL>
Shortly, I don't understand what you are doing. Try to follow my examples. If it still doesn't work, post your SQL*Plus session.