Invalid identifier error while running plsql block - sql

Since my school does not allow me to post the code, hence i had to come back home and put up an example to show the issue i am facing. My school asked me to do a homework on dynamic sql to create a table and later insert one dummy record to it. But while doing it I am facing the below issue. Please find the code below for your reference. Thank you.
Procedure:
create or replace procedure table_creation(table_name in varchar2,col1 varchar2,col2 varchar2)
is
l_stat varchar2(3000);
v_stat varchar2(1000);
a varchar2(10):='1';
b varchar2(10):='Dummy';
begin
l_stat:='create table '||table_name||' ("'||col1||'" varchar2(10),"'||col2||'" varchar2(10))';
execute immediate l_stat;
execute immediate 'insert into '||table_name||'('||col1||','||col2||') values (:x,:y)' using a,b;
end;
/
Plsql Block to call the procedure:
set serveroutput on;
declare
a varchar2(10);
b varchar2(10);
c varchar2(10);
begin
a:='Example';
b:='id';
c:='nm';
table_creation(a,b,c);
dbms_output.put_line('Yes');
end;
/
The procedure is getting created perfectly and while running the above block i am getting the below error .
declare
*
ERROR at line 1:
ORA-00904: "NM": invalid identifier
ORA-06512: at "SYS.TABLE_CREATION", line 9
ORA-06512: at line 9
But when I checked the created table. The table exists with 0 records. The structure of the table is as follows.
Name Null? Type
----------------------------------------- -------- ---------------
ID VARCHAR2(10)
NM VARCHAR2(10)
Any help from your end is much appreciated.

Nick,
Please note that the above procedure will create the column with a double qoutes ("ID","NM") hence the error occurred. Please find the updated code and check if the issue has resolved.
According to oracle=>
Oracle is case sensitive in column and table names. It just converts everything to upper case by default. But if you use names in double quotes, you tell Oracle to create the column in the exact spelling you provided (lower case in the CREATE statement).
Code:
create or replace procedure table_creation(table_name in varchar2,col1 varchar2,col2 varchar2)
is
l_stat varchar2(3000);
v_stat varchar2(1000);
a varchar2(10):='1';
b varchar2(10):='Dummy';
begin
l_stat:='create table '||table_name||' ('||col1||' varchar2(10),'||col2||' varchar2(10))';
execute immediate l_stat;
execute immediate 'insert into '||table_name||'('||col1||','||col2||') values (:x,:y)' using a,b;
end;
/
Note: I have not touched any other logic of the code. Please try and let us know the result.
Only change is
From :
l_stat:='create table '||table_name||' ("'||col1||'" varchar2(10),"'||col2||'" varchar2(10))';
to :
l_stat:='create table '||table_name||' ('||col1||' varchar2(10),'||col2||' varchar2(10))';

Related

Trying to declare a cursor, but I'm getting hit with end of file! (Oracle SQL)

I'm currently learning Oracle SQL and I am on cursors right now. I know it's a small problem, and probably easy to solve, but my declaration statement is pulling an end of file error. (PLS-00103)
Here is the statement:
declare cursor CustCursor is select * from Customers where cust_email is null;
Any help would be appreciated, it might also be worth knowing that I followed the Sams Teach Yourself SQL Book and am still getting these problems.
Thank you!
DECLARE can't exist alone in the Universe - it is part of a PL/SQL block which also requires at least dummy BEGIN-END part of it.
This is what you have:
SQL> declare cursor CustCursor is select * from Customers where cust_email is null;
2 /
declare cursor CustCursor is select * from Customers where cust_email is null;
*
ERROR at line 1:
ORA-06550: line 1, column 78:
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the
following:
begin function pragma procedure subtype type <an identifier>
<a double-quoted delimited-identifier> current cursor delete
exists prior
This is what you should have:
SQL> declare cursor CustCursor is select * from Customers where cust_email is null;
2 begin
3 null;
4 end;
5 /
PL/SQL procedure successfully completed.
SQL>
Or, as Ed Stevens says, to put everything where it belongs (although, the result will be just the same):
SQL> declare
2 cursor CustCursor is select * from Customers where cust_email is null;
3 begin
4 null;
5 end;
6 /
PL/SQL procedure successfully completed.
SQL>

How to execute a stored procedure with cursor and table OUT parameters through SQL Developer?

I’m having trouble testing, in SQL Developer 3.2.20.09, an Oracle stored procedure that contains 2 specificities:
a user defined "cursor type" output parameter
a user defined "TABLE OF VARCHAR type" output parameter.
Stored procedure signature:
TYPE ref_cursor_tst IS REF CURSOR;
TYPE arrWarningCode_tst IS TABLE OF VARCHAR2 (4000)
INDEX BY BINARY_INTEGER;
PROCEDURE SP_ITF_CU_DOCUMENT_Test (
p_projectNumber IN VARCHAR2,
p_tag IN VARCHAR2,
p_title IN VARCHAR2,
out_document_curs OUT ref_cursor_tst,
out_errorCode OUT VARCHAR2,
out_arrWarningCode OUT arrWarningCode_tst);
My actual best test code I could end up with:
set serveroutput on size 100000
DECLARE
docRef VARCHAR2(200);
outDocCurs PD360BADMIN.PKG_ITF_GENERAL_TST.ref_cursor_tst;
outErrorCode VARCHAR2(2000);
arrWarningCodes PD360BADMIN.PKG_ITF_GENERAL_TST.arrWarningCode_tst;
i PLS_INTEGER;
doc TBL_OBJECT%ROWTYPE;
BEGIN
dbms_output.put_line('debut de procedure');
docRef:= 'DOC-012';
arrWarningCodes.DELETE;
--call SP
PKG_ITF_GENERAL_TST.SP_ITF_CU_DOCUMENT_TEST (
p_projectNumber => 'XXX',
p_tag => docRef,
p_title => 'Doc title',
out_document_curs => outDocCurs,
out_errorCode => outErrorCode,
out_arrWarningCode => arrWarningCodes);
--print error code
dbms_output.put_line('out_errorCode=' || outErrorCode);
--print output cursor
--dbms_output.put_line(outDocCurs);
LOOP
FETCH outDocCurs INTO doc;
EXIT WHEN outDocCurs%NOTFOUND;
dbms_output.put_line(doc.OBJ_ID||','||doc.OBJ_TAG);
END LOOP;
--print warnings array
IF arrWarningCodes.count > 0 THEN
FOR i IN arrWarningCodes.FIRST .. arrWarningCodes.LAST LOOP
dbms_output.put_line('warning code=' || arrWarningCodes(i) );
END LOOP;
ENd IF;
dbms_output.put_line('fin de procedure');
END;
/
The error I get:
Error report:
ORA-06504: PL/SQL: Return types of Result Set variables or query do not match
ORA-06512: at line 30
06504. 00000 - "PL/SQL: Return types of Result Set variables or query do not match"
*Cause: Number and/or types of columns in a query does not match declared
return type of a result set variable, or declared types of two Result
Set variables do not match.
*Action: Change the program statement or declaration. Verify what query the variable
actually refers to during execution.
debut de procedure
out_errorCode=
I've been testing various solutions and syntaxes for days as well as digging the net and requiring help from different sources with no success.
Any clue would be much appreciated.
Assuming TBL_OBJECT is a table of some object type which has the two fields obj_id and obj_tag; and the procedure is currently doing something like:
open out_document_curs for select * from tbl_object;
... then there are two ways to make this work. The first is to change the variables you're fetching into to match the object fields, rather than the object itself:
DECLARE
...
-- doc TBL_OBJECT%ROWTYPE;
doc_obj_id TBL_OBJECT.OBJ_ID%TYPE;
doc_obj_tag TBL_OBJECT.OBJ_TAG%TYPE;
BEGIN
...
and then change the fetch and display:
LOOP
FETCH outDocCurs INTO doc_obj_id, doc_obj_tag;
EXIT WHEN outDocCurs%NOTFOUND;
dbms_output.put_line(doc_obj_id||','||doc_obj_tag);
END LOOP;
If the object has more fields then you'd need to define them all and specify them in the fetch too.
The other is to modify the procedure so that it returns an object type:
open out_document_curs for select value(t) from tbl_object t;
Then your calling anonymous block will work as it is, as the simple query will return the object itself rather than the fields within it.
Which you do will depend on how the procedure will really be used, rather than your test call.
With some dummy set-up:
create type doc_obj as object (obj_id number, obj_tag varchar2(10));
/
create table tbl_object of doc_obj;
insert into tbl_object values (doc_obj(1, 'Test'));
And a dummy package body with the procedure simplified as:
PROCEDURE SP_ITF_CU_DOCUMENT_Test (
p_projectNumber IN VARCHAR2,
p_tag IN VARCHAR2,
p_title IN VARCHAR2,
out_document_curs OUT ref_cursor_tst,
out_errorCode OUT VARCHAR2,
out_arrWarningCode OUT arrWarningCode_tst)
IS
BEGIN
open out_document_curs for select value(o) from tbl_object o;
out_errorCode := 'OK';
out_arrWarningCode(1) := 'Danger!';
END SP_ITF_CU_DOCUMENT_Test;
Then calling your code exactly as you have it in the question (minus the schema name) gives:
anonymous block completed
debut de procedure
out_errorCode=OK
1,Test
warning code=Danger!
fin de procedure
Using the other approach, with the individual variables for the object fields, gives the same result too.

How to create a table inside of a procedure in Oracle?

I want to create a table inside of a procedure. I tried to put the create query in a string then execute immediate the string. For example:
create or replace procedure hr.temp is
var1 varchar2(4000);
begin
var1:='create table hr.temp(
id number)';
execute immediate var1;
end temp;
But when I execute this procedure I get the error:
ORA-00911: invalid character
ORA-06512: at "SYS.TEMP", line 6
.
.
.
Is there any way I can do this?
Try this. It should work...
create or replace procedure hr.temp is
var1 varchar2(4000);
BEGIN
var1:='create table hr.temp2(
id number)';
EXECUTE IMMEDIATE var1;
end temp;
the answer of m.r 'a_horse_with_no_name' is right. The first point is I should not create a table in sys schema.
The second point is in a dynamic sql I should not use ; character in dynamic sql.

Displaying data through stored procedure

Create or replace procedure disp(pEMPLASTNAME varchar2)
IS
Row employee%rowtype;
begin
select * into row from employee where EMPLASTNAME=’pEMPLASTNAME’ ;
dbms_output.put_line('Name: '||Row.EMPID||' '|| Row.EMPNAME);
End;
/
BEGIN
disp(‘Mark’);
END;
/
Hello, I am trying to display data from a a table using stored procedures. The last name is passed as a parameter through the stored procedure and upon execution , the stored procedure should display all the rows which have the last name . Here is the error that i get; pls help! :-
SQL> BEGIN
disp('Mark');
END;
/
BEGIN
*
ERROR at line 1:
ORA-01403: no data found
ORA-06512: at "TEST.DISP", line 5
ORA-06512: at line 2
No need of the quotes:
select * into row from employee where EMPLASTNAME=pEMPLASTNAME;
However, you may not have any data for that variable's value anyway (i.e. one day, it may happen)
That's why I recommend you catch the exception and treat it (see EXCEPTION block)
pd: it is a good practice to not use reserved words such as row. I recommend you name your variable another way.
I would suggest using a cursor to select all rows and then looping through the cursor to print the result:
Create or replace procedure disp(pEMPLASTNAME varchar2)
IS
Cursor row_select is
select EMPID, EMPNAME from employee where emplastname = pEMPLASTNAME;
-- and whatever columns you need to print, using * isn't good practice
begin
for item in row_select loop
dbms_output.put_line('Name: '||item.EMPID||' '|| item.EMPNAME);
end loop;
End;
/
BEGIN
disp(‘Mark’);
END;
/

Error ORA-06502 in BLOB retrieval

I'm trying to develop a procedure which will read a BLOB field of a table and write an RTF document which will be used as template to another procedure but when the procedure fires up the select statemente, i got stuck with a ORA-06502 error.
This error, after reading the documentation, is caused by incompatibilities between fields (numeric or value error string)
But i've seen this example everywhere in the internet and i'm running out of ideas of what is causing it.
The source code of my procedure follows:
PROCEDURE p_transfer_db_client(pcPath IN VARCHAR2,
pnSequence IN NUMBER) IS
v_src_blob BLOB;
v_file UTL_FILE.FILE_TYPE;
v_offset INTEGER := 1;
v_amount BINARY_INTEGER := 32766;
v_binary_buffer RAW(32767);
BEGIN
SELECT model
INTO v_src_blob
FROM models
wHERE id = pnSequence;
v_file := UTL_FILE.FOPEN(pcPath, 'model.rtf', 'wb', v_amount);
LOOP
BEGIN
DBMS_LOB.READ(v_src_blob, v_amount, v_offset, v_binary_buffer);
UTL_FILE.PUT_RAW(v_file, v_binary_buffer);
v_offset := v_offset + v_amount;
EXCEPTION
WHEN NO_DATA_FOUND THEN
EXIT;
END;
END LOOP;
UTL_FILE.FFLUSH(v_file);
UTL_FILE.FCLOSE(v_file);
END p_transfer_db_client;
Edit: I hadn't seen that you had tagged this question as forms.
Your code won't work inside forms: UTL_FILE and DBMS_LOB run on the DB server, not the forms client so they should be in a PL/SQL procedure, not a Forms procedure.
I'm pretty sure the BLOB datatype is not managed like this in forms, in fact I'm surprised it even compiles!
Take a look at this example showing how to handle blobs inside forms for instance, and you will see that you need to define and query the blob inside a PLSQL procedure, not directly through forms.
I suggest you create the procedure inside the DB as a PLSQL package and call this package from your forms client.
There is something else going on, I can't see why the SELECT statement wouldn't work.
Do you still get the error if you comment out all variables declarations and all the following statements, i.e:
SQL> create table models (
2 inst_num_instituicao NUMBER(2) not null,
3 id NUMBER(3) not null,
4 model BLOB not null);
Table created.
SQL> insert into models values (1, 1, hextoraw('FFFF'));
1 row created.
SQL> declare
2 b blob;
3 begin
4 select model into b from models where id = 1;
5 end;
6 /
PL/SQL procedure successfully completed.