Reputation: 71
I was trying to check if a table exists, if it doesn't then it must be created BUT i'm getting an error below when I try to insert data into it when supposedly it is already created. Here is my script:
PROCEDURE CREAR_CLAVES
AS
VERIFACION INTEGER;
BEGIN
SELECT COUNT(TNAME) INTO VERIFACION FROM TAB WHERE TNAME = 'CLAVES';
IF VERIFACION = 0 THEN
EXECUTE IMMEDIATE 'CREATE TABLE CLAVES (IDESTUDIANTE NUMBER(5) PRIMARY KEY, USUARIO VARCHAR2(1000), CONTRASENA VARCHAR2(1000))';
EXECUTE IMMEDIATE 'ALTER TABLE CLAVES ADD CONSTRAINT FK_IDESTUDIANTE FOREIGN KEY (IDESTUDIANTE) REFERENCES ESTUDIANTES(ID)';
ELSE
DBMS_OUTPUT.PUT_LINE('LA TABLA YA EXISTE');
END IF;
END CREAR_CLAVES;
PROCEDURE IDENTIFICAR_ESTUDIANTES
AS
VESTUDIANTES SYS_REFCURSOR;
ACTUAL ESTUDIANTES%ROWTYPE;
CONSULTA VARCHAR2(1000);
BEGIN
CONSULTA := 'SELECT ID, NOMBRE, APELLIDO FROM ESTUDIANTES';
OPEN VESTUDIANTES FOR CONSULTA;
FETCH VESTUDIANTES INTO ACTUAL;
WHILE VESTUDIANTES%FOUND
LOOP
INSERT
INTO CLAVES VALUES
(
ACTUAL.ID,
LOWER(ACTUAL.APELLIDO)
||LOWER(ACTUAL.NOMBRE),
LOWER(ACTUAL.NOMBRE)
||DBMS_RANDOM.VALUE(100, 999)
);
FETCH VESTUDIANTES INTO ACTUAL;
END LOOP;
CLOSE VESTUDIANTES;
END IDENTIFICAR_ESTUDIANTES;
I get the table or view doesn't exist error. Any idea how can I solve it?
Upvotes: 0
Views: 315
Reputation: 121
Most probably the problem is that the CLAVES does not exist when the procedure is compiled. It does not even get to the point where it checks its existence and creates it.
You can solve it by putting the 'INSERT INTO CLAVES...' statement into an execute immediate. Use bind variables there to avoid any possibility of sql injection:
CREATE or replace PROCEDURE IDENTIFICAR_ESTUDIANTES
AS
VESTUDIANTES SYS_REFCURSOR;
ACTUAL ESTUDIANTES%ROWTYPE;
CONSULTA VARCHAR2(1000);
BEGIN
CONSULTA := 'SELECT ID, NOMBRE, APELLIDO FROM ESTUDIANTES';
OPEN VESTUDIANTES FOR CONSULTA;
FETCH VESTUDIANTES
INTO ACTUAL;
WHILE VESTUDIANTES%FOUND LOOP
execute immediate 'INSERT INTO CLAVES VALUES (:IDESTUDIANTE, :USUARIO, :CONTRASENA)'
using ACTUAL.ID, LOWER(ACTUAL.APELLIDO)||LOWER(ACTUAL.NOMBRE), LOWER(ACTUAL.NOMBRE)||DBMS_RANDOM.VALUE(100, 999);
FETCH VESTUDIANTES
INTO ACTUAL;
END LOOP;
CLOSE VESTUDIANTES;
END IDENTIFICAR_ESTUDIANTES;
/
BTW, I also disourage the creation of the CLAVES on-the-fly. Moreover, it would be better to implement the cursor loop and row-by-row (slow-by-slow) insert in a single 'insert as select' statment, unless you have a very specific, procedural-heavy logic here that transforms the ESTUDIATES rows into CLAVES.
Upvotes: 1