Search code examples
sqloracleplsqldynamic-sql

How to properly call a PL/SQL function with dynamic SQL in it?


I wrote a PL/SQL function :-

CREATE OR REPLACE FUNCTION register_driver1(driver_name IN VARCHAR, pass_word IN VARCHAR) RETURN NUMBER AS
sql_stmt VARCHAR2(200);
driver_id NUMBER;
new_view_name VARCHAR(50);
BEGIN

    sql_stmt := 'CREATE USER '||driver_name||' identified by '||pass_word;

    EXECUTE IMMEDIATE sql_stmt;

    sql_stmt := 'grant create session to '||driver_name;

    EXECUTE IMMEDIATE sql_stmt;

    driver_id := driver_ids.nextval;
    new_view_name := 'vehicle_'||driver_name;

    sql_stmt := 'CREATE VIEW '||new_view_name|| ' AS SELECT Model, Seats, reg_no FROM Vehicle WHERE(d_id='||driver_id||')';

    EXECUTE IMMEDIATE sql_stmt;

    sql_stmt := 'CREATE OR REPLACE TRIGGER reg_vehicle 
                 INSTEAD OF INSERT ON '||new_view_name||
               ' FOR EACH ROW 
                 DECLARE 
                 vehicle_id NUMBER;
                 BEGIN
                 vehicle_id := vehicle_ids.nextval
                 INSERT INTO Vehicles VALUES(:NEW.Model, :NEW.Seats, :NEW.reg_no, vehicle_id, '||driver_id||');
                 END;';

    EXECUTE IMMEDIATE sql_stmt;

    sql_stmt := 'grant insert, update, select, delete on '||new_view_name||' to '||driver_name;  

    EXECUTE IMMEDIATE sql_stmt;

    sql_stmt := 'grant select on PENDING_REQUESTS to '||driver_name;

    EXECUTE IMMEDIATE sql_stmt;

    RETURN driver_id;

END register_driver1;
/

But, I am not able to figure how to call it? Calling within a select query doesn't work because the function has DML and DDL statements.

Calling using the following :-

BEGIN
  register_driver1('RoCK', 'wt893fdg$');
END;
/

shows the following error :-

Function REGISTER_DRIVER1 compiled

Elapsed: 00:00:00.009

ORA-06550: line 2, column 3: PLS-00221: 'REGISTER_DRIVER1' is not a procedure or is undefined ORA-06550: line 2, column 3: PL/SQL: Statement ignored

Both the call and function are executed in same worksheet and as ADMIN.. Yet, it shows that the procedure is undefined. Please help. SQL Developer Web of Oracle Cloud is used.


Solution

  • Your function returns a number. Call it in a pl/sql block where you assign the function to a variable of type number. The example below is a anonymous pl/sql block but you can also put this in a procedure of function.

    DECLARE
      l_driver_id NUMBER;
    BEGIN
      l_driver_id := register_driver1('RoCK', 'wt893fdg$');
      -- rest of code ... --
    END;