PLS-00103 error with anonymous procedure - sql

I got an error
PLS-00103: Encountered the symbol "end-of-file" when expecting one of
the following: [...]
when running an anonymous procedure (with Oracle):
BEGIN
DECLARE
seq number(12);
pk number(12);
BEGIN
loop
select mod_sdemol.nextval into seq from dual;
select idn_demol into pk from demol where demol.idn_demol=seq;
exit when pk is null;
end loop;
INSERT INTO "T_MOD"."DEMOL" (IDN_DEMOL, COD_MOL, PATH, IND_BLOK) VALUES (seq, '13000501', 'V', 'S');
END;
What I am trying to do is iterate through a sequence to prevent conflicts with existing data.
According to the answers in this question, a PL/SQL procedure should do something with selected data, but all my SELECTs have INTOs.
What am I doing wrong or what am I missing?

You don't need the first BEGIN. Each BEGIN keyword must match an END keyword.

Related

Function - oracle (PLS-00103: Encountered the symbol "")

I'm trying to create a simple oracle function which loops over some records and then inserts records for each of those ..
CREATE OR REPLACE FUNCTION addNewRolesToAllGDP
return NUMBER
is dummy number;
BEGIN
FOR applicationId IN (SELECT APPID
FROM GRPAPPLICATIONINSTANCES
where GRPAPPID = (select GRPAPPID
from GRPAPPLICATIONS
where GRPNAME = 'DIGITAL_OFFICE')
AND APPID in (select APPID from APPLICATIONS where REGEXP_LIKE(APPNAME, '[[:digit:]]')))
LOOP
INSERT INTO ROLES (ROLID, ROLNAME, APPID)
VALUES (SEQROLES.nextval,
'INVENTORY_REQUESTER',
applicationId);
INSERT INTO ROLES (ROLID, ROLNAME, APPID)
VALUES (SEQROLES.nextval,
'INVENTORY_OWNER',
applicationId);
INSERT INTO ROLES (ROLID, ROLNAME, APPID)
VALUES (SEQROLES.nextval,
'INVENTORY_ADMIN',
applicationId);
END LOOP;
RETURN 1;
END;
alter function addNewRolesToAllGDP compile;
This statements gives me the following in USER_ERRORS:
PLS-00103: Encountered the symbol "" when expecting one of the following: ( return compress compiled wrapped
I'm not sure if this is the problem, but I notice that you do not have a slash following the END statement of the function. In Oracle tools, without that slash, the statement does not actually get terminated, and the ALTER command is included as part of the same statement. This can cause weird syntax errors.
If this is the problem, fundamentally this question is a duplicate of oracle SQL plus how to end command in SQL file?.
Edited to add As others have said in comments, the same code seems to compile fine for me when I cut-and-paste it from your post. Based on the error and the position where it is reported, my best guess is that at the end of the first line your original source has some invisible character that is causing the parser error.
Used to run this in Intellij which gave me the stated behaviour. After running it from sqlDeveloper it compiled fine.
I got a similar error message for a missing comma in the procedure definition and got compiled after adding the comma.
Procedure definition before fix
PROCEDURE CREATE_WO(p_wo_type IN NUMBER,
p_id IN NUMBER,
p_do_commit IN VARCHAR2 DEFAULT 'Y'
p_return_value OUT VARCHAR2)
IS
BEGIN
...
END;
Error Message
Cause: java.sql.SQLException: ORA-06550: line 8, column 9:
PLS-00103: Encountered the symbol "" when expecting one of the following:
) , * & = - + < / > at in is mod remainder not rem =>
<an exponent (**)> <> or != or ~= >= <= <> and or like like2
like4 likec between || multiset member submultiset
Procedure definition after fix, note the comma at the end of p_do_commit
PROCEDURE CREATE_WO(p_wo_type IN NUMBER,
p_id IN NUMBER,
p_do_commit IN VARCHAR2 DEFAULT 'Y',
p_return_value OUT VARCHAR2)
IS
BEGIN
...
END;

Issue with trigger for archiving

Trying to make a trigger that puts data into an archive table when a column called COMPLETION_STATUS goes from incomplete to complete, the dbms is a placeholder for the insert but I'm getting the following errors in the if statement
Error(6,1): PLS-00103: Encountered the symbol enter code here"SELECT" when expecting one of the following: begin function pragma procedure subtype type current cursor delete exists prior The symbol "begin" was substituted for "SELECT" to continue.
Error(9,1): PLS-00103: Encountered the symbol "IF" when expecting one of the following: * & - + ; / at for mod remainder rem and or group having intersect minus order start union where connect || multiset The symbol ";" was substituted for "IF" to continue.
Error(13,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 << continue close current delete fetch lock insert open rollback savepoint set sql execute commit forall merge pipe purge
Code:
create or replace TRIGGER ARCHIVING_TRIG
BEFORE UPDATE OF COMPLETION_STATUS ON PROJECT_DATA
BEGIN
DECLARE COMPLETION_STATUS1 VARCHAR2(9);
SELECT COMPLETION_STATUS into COMPLETION_STATUS1
FROM PROJECT_DATA WHERE COMPLETION_STATUS = 'complete'
IF COMPLETION_STATUS1 = 'complete'
THEN
DBMS.output('123');
END IF;
END;
The DECLARE block should be before the BEGIN block.
The SELECT ... statement needs to be terminated with a semicolon (;).
It's dbms_output.put_line() not dbms.output();
You're trying to assign the result of a query that potentially can return more than one row to a scalar variable.
The rows selected from project_data have no relation to the one(s) that triggered the trigger.
I suggest you use something like:
CREATE TRIGGER archiving_trig
AFTER UPDATE
ON project_data
FOR EACH ROW
WHEN (old.completion_status <> 'complete'
AND new.completion_status = 'complete')
BEGIN
dbms_output.put_line('Trigger fired for ID ' || :new.id);
END;
db<>fiddle
I think maybe AFTER is the better time, because you want to archive the row after the status was successfully changed.
Because of the WHEN the trigger will only fire if completion_status has been changed from something other than 'complete' to 'complete'. But you maybe also need to have a method of removing entries from the archive when the status changes from 'complete' to something else. That isn't covered here.
Declaring it as FOR EACH ROW let's you access the values of the updated row via :new. That way you don't need a query to select that nor a variable to select into.
I guess you need this:
create table PROJECT_DATA_NEW as select * from PROJECT_DATA where 1=2;
CREATE OR REPLACE TRIGGER ARCHIVING_TRIG
AFTER UPDATE
ON PROJECT_DATA
FOR EACH ROW
DECLARE
status number;
BEGIN
status:=0;
select 1 into status from PROJECT_DATA where
:new.COMPLETION_STATUS='complete' and
:old.COMPLETION_STATUS='incomplete'
if (status=1) then
insert into PROJECT_DATA_NEW values(:old.column1,
:old.column2,
:old.column3,
:old.column4,
:old.column5,....etc);
end if;
END;
/

Foreign key between two databases

I went through the previous answers to create a pseudo-foreign key to reference tables between two databases in Netbeans 8.1. This is the code I came up with,
DELIMITER //
CREATE OR REPLACE TRIGGER conf_track_FK
AFTER INSERT OR UPDATE on S26994437.track#FIT5148B
FOR EACH ROW
BEGIN
IF EXISTS(select * from inserted I where not exists (select * from
S1234567.conference#FIT5148A A where I.conf_id=A.conf_id))
RAISE_APPLICATION_ERROR(-20001,'Violation of pseudo-foreign key.');
ROLLBACK;
END IF;
END;
/
However, I encounter the following errors:
PLS-00103: Encountered the symbol ";" when expecting one of the following:
) with and or group having intersect minus start union where
connect
PLS-00103: Encountered the symbol "ROLLBACK" when expecting one of the following:
:= . ( % ;
The symbol ":=" was substituted for "ROLLBACK" to continue.
PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following:
end not pragma final instantiable order overriding static
member constructor map
Create Trigger dbo.MyTableTrigger ON dbo.MyTable, After Insert, Update
As
Begin
If NOT Exists(select PK from OtherDB.dbo.TableName where PK in (Select FK from inserted) BEGIN
-- Handle the Referential Error Here
END
END
Try the below illustrated snippet. Hope it helps. And also any TRANSACTIONS like COMMIT / ROLLBACK cant be placed INSIDE Trigger unless its an Autonomous transaction but that too not a good idea as parent transaction is hidden to the trigger transaction. So even the Parent transaction fails the Automnomous transaction will be done.
CREATE OR REPLACE TRIGGER conf_track_FK AFTER
INSERT OR
UPDATE ON S26994437.track#FIT5148B --Remove DB link as it cant be used in Trigger
FOR EACH ROW
DECLARE
lv_cnt PLS_INTEGER;
BEGIN
SELECT COUNT(1)
INTO lv_cnt
FROM inserted I
WHERE NOT EXISTS
(SELECT 1 FROM S1234567.conference#FIT5148A A WHERE I.conf_id=A.conf_id
);
IF lv_cnt > 0 THEN
RAISE_APPLICATION_ERROR(-20001,'Violation of pseudo-foreign key.');
END IF;
END;
/

Trigger in Oracle giving error

This is my sql code:
CREATE OR REPLACE TRIGGER PLACE_NO_TRIGGER
BEFORE INSERT or UPDATE ON UHA_LEASE
FOR EACH ROW BEGIN
INSERT INTO UHA_TEMPVAL SELECT PLACE_NO FROM UHA_RESHALL;
INSERT INTO UHA_TEMPVAL SELECT PLACE_NO FROM UHA_GENERAL;
IF(:NEW.PLACE_NO NOT IN UHA_TEMPVAL.TEMP_VALUE AND :NEW.PLACE_NO IS NOT NULL) THEN
RAISE_APPLICATION_ERROR(-10001, 'PLACE_NO MUST BE IN UHA_RESHALL OR IN UHA_GENERAL OR NULL');
END IF;
DELETE FROM UHA_TEMPVAL;
END;
This is giving these errors:
Error(4,27): PLS-00103: Encountered the symbol "UHA_TEMPVAL" when expecting one of the following: ( The symbol "(" was substituted for "UHA_TEMPVAL" to continue.
Error(4,69): PLS-00103: Encountered the symbol "THEN" when expecting one of the following: ) , and or as The symbol ")" was substituted for "THEN" to continue.
Can someone help me understand why these errors are occurring? It's especially odd because row 4 ends at column 60.
Thanks!
It looks like you're trying to enforce referential integrity from a child table to either of two parent tables. You don't really need to insert and delete from a temporary table; you can count how many rows match in either table:
CREATE OR REPLACE TRIGGER PLACE_NO_TRIGGER
BEFORE INSERT or UPDATE ON UHA_LEASE
FOR EACH ROW
DECLARE
CNT NUMBER;
BEGIN
SELECT COUNT(*)
INTO CNT
FROM (
SELECT PLACE_NO FROM UHA_RESHALL
WHERE PLACE_NO = :NEW.PLACE_NO
UNION ALL
SELECT PLACE_NO FROM UHA_GENERAL
WHERE PLACE_NO = :NEW.PLACE_NO
);
IF :NEW.PLACE_NO IS NOT NULL AND CNT = 0 THEN
RAISE_APPLICATION_ERROR(-10001,
'PLACE_NO MUST BE IN UHA_RESHALL OR IN UHA_GENERAL OR NULL');
END IF;
END;
/
You could choose to only run the query if the :NEW.PLACE_NO is not null but it probably won't make much difference if the columns are indexed.

PLS-00103: Encountered the symbol "end-of-file" when expecting one of the following: ;

I am running the following script -
BEGIN
select department_name
from egpl_department
where department_id in (select department_id
from egpl_casemgmt_activity);
END ;
And got the Error -
PLS-00103: Encountered the symbol "end-of-file" when
expecting one of the following:
;
In a PL/SQL block select statement should have an into clause:
DECLARE
v_department egpl_department.department_name%type;
BEGIN
select department_name
into v_department
from egpl_department
where department_id in (select department_id from egpl_casemgmt_activity);
-- Do something useful with v_department
END;
PLS-00103 always means the compiler has hurled because we have made a syntax error. It would be really neat if the message text said: You have made a syntax error, please check your code but alas it doesn't.
Anyway, in this case the error is that in PL/SQL select statements must populate a variable. This is different from the behaviour of say T-SQL. So you need to define a variable which matches the projection of your query and select INTO that variable.
Oracle's documentation is comprehensive and online. You can find the section on integrating SQL queries into PL/SQL here. I urge you to read it, to forestall your next question. Because once you have fixed the simple syntax bloomer you're going to hit TOO_MANY_ROWS (assuming you have more than one department).
In PL/SQL you cannot just select some data. Where is the result supposed to go?
Your options are:
Remove BEGIN and END and run the SELECT with SQL*plus or some other tool that can run a SQL statement and present the result somewhere.
Use SELECT department_name INTO dep_name to put the result into a PL/SQL variable (only works if your SELECT returns a single row)
Use SELECT department_name BULK COLLECT INTO dep_name_table to put the result into a PL/SQL table (works for several rows)
Or maybe you can describe what you're trying to achieve and in what environment you want to run the SQL or PL/SQL code.
To avoid the too_many_rows problem, you could use a cursor, something like this (I haven't tested this, but along these lines )
DECLARE
v_department egpl_department.department_name%type;
cursor c_dept IS
select department_name
into v_department
from egpl_department
where department_id in (select department_id from egpl_casemgmt_activity)
order by department_name;
BEGIN
OPEN c_dept;
FETCH c_dept INTO v_department;
CLOSE c_dept;
-- do something with v_department
END;
This will put the first value it finds in the table into v_department. Use the ORDER BY clause to make sure the row returned would be the one you required, assuming there was the possibility of 2 different values.
Most people would not consider the call to be the issue,
but here's an amusing bug in Oracle Sql Developer that may emulate the issue..
exec dbowner.sp1 ( p1, p2, p3); -- notes about the fields
Error report -
ORA-06550: line 1, column 362:
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
<< close current delete fetch lock insert
open rollback savepoint set sql execute commit forall merge
pipe
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
exec dbowner.sp1 ( p1, p2, p3);
-- notes about the fields
PL/SQL procedure successfully completed.
DECLARE is only used in anonymous PL/SQL blocks and nested PL/SQL blocks.
You do not need to use the DECLARE key word before you 'introduce' a new variable in a Procedure block, unless .... the procedure is a nested PL/SQL block.
This is an example of how you would declare a variable without the 'DECLARE' Key word below.
eg.;
CREATE OR REPLACE PROCEDURE EXAMPLE( A IN NUMBER, B OUT VARCHAR2 )
IS
num1 number;
BEGIN
num1:=1;
insert into a (year) values(7);
END;
This question/answer explains it better
create procedure in oracle