ORA-00917: Missing Comma in PLSQL - sql

I have written a PL SQL script to add values stored in an array into a temp table. I have used Execute immediate to execute the insert query inside a loop.
I have checked the number of single quotes and the number of commas and they are closed. Still, I'm getting the error code
ORA-00917: missing comma.
declare
type post_CODS IS VARRAY(34) OF VARCHAR2(20);
type locality_ID IS VARRAY(34) OF NUMBER(9);
pc post_CODS;
Y varchar2(1);
lid locality_ID;
total integer;
begin
Y := 'Y';
lid := locality_ID(2380,3785,8710,17895,20345,24630,26814,28525,29130,31025,31265,32445,36940,40590,54290,83775,83780,83785,83790,83795,88483,93480,94560,96670,1000524,1000628,1000738,1000857,1000988,1001103,1001466,1001575,1001707,1001744);
pc := post_CODS(2822,2739,2822,2372,2817,4314,4300,4726,4300,4884,4314,4314,4300,5719,3026,4314,4314,4314,4314,4314,873,2582,2817,4314,5723,5440,2083,2575,873,2372,5440,5440,5715,5440);
total := lid.count;
FOR i in 1 .. total LOOP
execute immediate 'insert into tmp_ref_lc_pc_cods values('||lid(i)||','||pc(i)||','||Y||',89987,'||sysdate||')';
END LOOP;
END;
This is the error I am getting
Error report:
ORA-00917: missing comma
ORA-06512: at line 14
00917. 00000 - "missing comma"
I'm working on an oracle machine.

Wrap your insert statement in q'[]' and try
execute immediate q'[insert into tmp_ref_lc_pc_cods values('||lid(i)||','||pc(i)||','||Y||',89987,'||sysdate||')]';
Update
It is recommended to use bind variable. You can try the below. It is working for me and inserting the data.
declare
type post_CODS IS VARRAY(34) OF NUMBER(20);
type locality_ID IS VARRAY(34) OF NUMBER(9);
pc post_CODS;
Y varchar2(1);
lid locality_ID;
total integer;
begin
Y := 'Y';
lid := locality_ID(2380,3785,8710,17895,20345,24630,26814,28525,29130,31025,31265,32445,36940,40590,54290,83775,83780,83785,83790,83795,88483,93480,94560,96670,1000524,1000628,1000738,1000857,1000988,1001103,1001466,1001575,1001707,1001744);
pc := post_CODS(2822,2739,2822,2372,2817,4314,4300,4726,4300,4884,4314,4314,4300,5719,3026,4314,4314,4314,4314,4314,873,2582,2817,4314,5723,5440,2083,2575,873,2372,5440,5440,5715,5440);
total := lid.count;
FOR i in 1 .. total LOOP
execute immediate q'[insert into tmp_ref_lc_pc_cods values(:var1,:var2,'Y',89987,sysdate)]' using lid(i),pc(i);
END LOOP;
END;

A good trick when trying to execute immediate is making sure that the statements created are formatted correctly, printing the code you've written reveals that the Y is not inside of apostrophes
insert into tmp_ref_lc_pc_cods values(2380,2822,Y,89987,23-APR-19)
So when dynamically creating code make sure that all strings created have the right amount of apostrophes.
dbms_output.put_line('insert into tmp_ref_lc_pc_cods values('||lid(i)||','||pc(i)||','''||Y||''',89987,'||sysdate||')');

Related

how to select into an array in pl/sql?

I'm trying to add some ids into an array:
CREATE OR REPLACE TYPE array_of_numbers AS VARRAY(10)OF NUMBER(10);
declare
student_ids array_of_numbers;
begin
select nrleg BULK COLLECT into student_ids from student where nrleg = 123458;
FOR i IN 1..student_ids.COUNT LOOP
DBMS_OUTPUT.PUT_LINE(student_ids(i));
END LOOP;
end;
but I get the following errors:
--------- -------------------------------------------------------------
3/1 PLS-00103: Encountered the symbol "DECLARE"
10/4 PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following: ( begin case declare end exception exit for goto if loop mod null pragma raise return select update while with <an identifier> <a double-quoted delimited-identifier> <a bind variable> << continue close current delete fetch lock insert open rollback savepoint set sql execute commit forall merge pipe purge json_exists json_value json_query json_object json_array
Errors: check compiler log
Could someone explain what I did wrong?
Some DDL needs to be terminated with a /; a type can have a PL/SQL body so this is one of them. To run that all at once as a script do:
CREATE OR REPLACE TYPE array_of_numbers AS VARRAY(10)OF NUMBER(10);
/
declare
student_ids array_of_numbers;
begin
select nrleg BULK COLLECT into student_ids from student where nrleg = 123458;
FOR i IN 1..student_ids.COUNT LOOP
DBMS_OUTPUT.PUT_LINE(student_ids(i));
END LOOP;
end;
/
You don't need the semicolon on the end of the CREATE here, but it doesn't hurt; but for some other commands (including other DDL like create table) having both would cause it to try to execute the statement twice, which could cause an error.
SQL Developer won't complain about the lack of a / after the last PL/SQL block in a script, but other tools will, so it's better to always include that one too.
db<>fiddle
Incidentally, another way to see the contents of the array in SQL Developer is with a ref cursor:
var rc refcursor
declare
student_ids array_of_numbers;
begin
select nrleg BULK COLLECT into student_ids from student where nrleg = 123458;
open :rc for select * from table(student_ids);
end;
/
print rc
... but then you might as well just select directly from the table, without any PL/SQL.

How to use dynamic where clause in EXECUTE IMMEDIATE

I have a table with columns insert,select,where clause,dynamic where clause,group by clause.
Using procedure i need to execute insert into statement and also use dynamic where clause.
I tried the following one however it is giving me an error missing expression.
create or replace PROCEDURE dynamicWhereClause(Datee IN DATE,processId IN NUMBER)
IS
processName VARCHAR2(100);
tablePrefix CONFIG_DETAILS.SOURCE_TABLE%Type;
sourceTableType CONFIG_DETAILS.SOURCE_TABLE_TYPE%Type;
insertClause CONFIG_DETAILS.INSERT_CLAUSE%Type;
selectClause CONFIG_DETAILS.SELECT_CLAUSE%Type;
whereClause CONFIG_DETAILS.WHERE_CLAUSE%Type;
onUpdateClause CONFIG_DETAILS.ON_UPDATE_CLAUSE%Type;
groupByClause CONFIG_DETAILS.GROUP_BY_CLAUSE%Type;
orderByClause CONFIG_DETAILS.ORDER_BY_CLAUSE%Type;
isDynamicWhereClause CONFIG_DETAILS.IS_DYNAMIC_WHERE_CLAUSE%Type;
tableName VARCHAR2(50);
Process_Date DATE;
processQuery VARCHAR2(6000 BYTE);
CURSOR Process_Report IS
select NAME,SOURCE_TABLE,SOURCE_TABLE_TYPE,INSERT_CLAUSE,SELECT_CLAUSE,WHERE_CLAUSE,ON_UPDATE_CLAUSE,GROUP_BY_CLAUSE,ORDER_BY_CLAUSE,IS_DYNAMIC_WHERE_CLAUSE FROM
CONFIG_DETAILS where ID=processId;
BEGIN
OPEN Process_Report;
LOOP
FETCH Process_Report INTO processName,tablePrefix,sourceTableType,insertClause,selectClause,whereClause,onUpdateClause,groupByClause,orderByClause,isDynamicWhereClause;
EXIT when Process_Report%NOTFOUND;
tableName := getSourceTableName(tablePrefix,sourceTableType,processDate);
Process_Date := processDate;
processQuery := insertClause || selectClause ||' from ' || tableName ||' ' ||
nvl(whereClause,'') ||''||nvl(groupByClause,'') ||''||nvl(orderByClause,'') ||''||nvl(onUpdateClause,'');
dbms_output.put_line(processQuery);
IF isDynamicWhereClause = 'Y'
THEN
dbms_output.put_line(processQuery);
EXECUTE IMMEDIATE processQuery USING Process_Date;
ELSE
EXECUTE IMMEDIATE processQuery;
END IF;
END LOOP;
CLOSE Process_Report;
END;
While executing the proc it is giving me the below error.
Error report -
ORA-00936: missing expression
ORA-06512: at "Mytest.dynamicWhereClause", line 44
ORA-06512: at line 1
00936. 00000 - "missing expression"
Please assist me further
Thanks
Your questions is not 100% clear . you saying after DATEE is being empty, are you assigning a variable after date ? the below is example of how using execute immediate with a variable. Note how is the bind variable :i is showing in the print.
set serveroutput on size 1000
/
declare t number(4) :=10;
txt varchar2(100);
begin
txt :='INSERT INTO TAB (ID) values (:i)';
dbms_output.put_line(t || ' ' || txt);
execute immediate txt using T;
end;
/
PL/SQL procedure successfully completed
10 INSERT INTO TAB (ID) values (:i)

PLS-00103: Encountered the symbol "&" when expecting one of the following

PLS-00103: Encountered the symbol "&" when expecting one of the following...
code:
Declare
num number;
Begin
num := &num;
if num > 0 then
dbms_output.put_line(‘Hello’);
end if;
end;
/
I'm not sure why I'm getting this message when I'm not seeing anything wrong.
Oracle Live SQL is a tool for trying out SQL and PL/SQL but it doesn't support substitution variable syntax (&var.).
Instead, you can create tables, populate them with data, then run SQL or PL/SQL using them, e.g.:
create table inputs (num number);
insert into inputs values (10);
Declare
num number;
Begin
select num into num from inputs;
if num > 0 then
dbms_output.put_line('Hello');
end if;
end;
/
(p.s. I had to fix the quotes around 'Hello' for this to work)
Oracle live does not support & for get value.
Instead you can initialize the Variable
Declare
num number := 10;
Begin
if num > 0 then
dbms_output.put_line(‘Hello’);
end if;
end;
/

procedure using loop in oracle

I used oracle
I want to declare a procedure that allows me to make insertion in a table
I try with this code without success
CREATE OR REPLACE PROCEDURE ADDSTEP(nbrStep character varying)
is
i integer :=0;
BEGIN
FOR i IN 0..nbrStep LOOP
INSERT INTO mytabletest
VALUES (i);
END LOOP;
END;
I have this error :
PROCEDURE ADDSTEP compiled
Errors: check compiler log
There are multiple issues with your code:
nbrStep character varying
There is no such data type called "character varying" in Oracle. For string you would use VARCHAR2. However, since you want to use it later in the loop for iteration, you need it to be NUMBER.
FOR i IN 0..nbrStep LOOP
You need to iterate from 1 till the boundary.
i integer :=0;
Not needed.
Modify the procedure as:
CREATE OR REPLACE PROCEDURE ADDSTEP(nbrStep NUMBER)
is
i integer :=0;
BEGIN
FOR i IN 0..nbrStep LOOP
INSERT INTO mytabletest
VALUES (i);
END LOOP;
END;
/
Anyway, you entire procedure could be done in a single INSERT SQL. It is called row generator method.
Try,
INSERT INTO mytabletest
SELECT LEVEL FROM DUAL CONNECT BY LEVEL <= 100;
Above, in place of 100, you could use the value of your choice which is the value you are passing as parameter **nbrStep ** in the above procedure.
Strange syntax of input variables. Corrected for Oracle -
CREATE OR REPLACE PROCEDURE addstep(nbrstep IN NUMBER)
IS
BEGIN
FOR i IN 0.. nbrstep
LOOP
INSERT INTO mytabletest
VALUES (i);
END LOOP;
END;

'insert into' in 'execute immediate' clause

Can you check this and tell me why I've got an error, please? How should it look? I have no idea what's wrong here. I need to create a table in a function, and in the same function insert data into this table:
create or replace
function new_tab ( pyt IN varchar2) return number
IS
a number;
b varchar2(20);
begin
a:= ROUND(dbms_random.value(1, 3));
b:='example';
-- This works perfect
execute immediate 'CREATE TABLE create_tmp_table'|| a ||'(i VARCHAR2(50))';
-- Here`s the problem
execute immediate 'insert into create_tmp_table'||a|| 'values ('|| b ||')';
exception
when others then
dbms_output.put_line('ERROR-'||SQLERRM);
return 0;
end;
My result is:
ERROR-ORA-00926: missing VALUES keyword. Process exited.
Where is the mistake?
As you are creating a dynamic insert command you have to create it as is. So you are missing the single quotes for the value that is varchar:
execute immediate
'insert into create_tmp_table'||a|| ' values ('''|| b ||''');';
^here ^and here
And a good suggestion for this type of error is to do some debug. On your case you could create a varchar2 variable and put your insert on it then you use the dbms_output.put_line to this variable. Then you will have your sql command that you can test direct on your database. Something like:
declare
sqlCommand varchar2(1000);
--define a and b
begin
--put some values in a and b
sqlCommand := 'insert into create_tmp_table'||a|| ' values ('''|| b ||''');';
dbms_output.put_line(sqlCommand);
end;
Then you will know what is wrong with the dynamic command.
execute immediate 'insert into TABLE'||a||' (COLUMN_NAME) values (:val)' using b;
This way you don't have to bother with escaping your values (SQL-injection hack) and correctly casting the type.
http://docs.oracle.com/cd/B13789_01/appdev.101/b10807/13_elems017.htm