triggers in pl/sql throw errors - plsql

What I need to do is I want to create a trigger which raises an error if both the proficiencies of the programmer are equal. Please tell me the errors I have done.
SQL> get f:/sqlprog/trigger_3;
1 create or replace trigger t2 before insert or update on programmer for each
row
2 declare
3 cursor c1 is select prof1, prof2 from programmer;
4 begin
5 for r1 in c1 loop
6 if r1.pname=:new.pname then
7 if :new.prof1=: new.prof2 then
8 raise_application_error(-20091,'prof1 and prof2 should not be same');
9 end if;
10 end if;
11 end loop;
12* end;
SQL> /
Warning: Trigger created with compilation errors.
SQL> show errors
Errors for TRIGGER T2:
LINE/COL ERROR
-------- -----------------------------------------------------------------
4/1 PLS-00103: Encountered the symbol "FOR" when expecting one of the
following:
constant exception <an identifier>
<a double-quoted delimited-identifier> table long double ref
char time timestamp interval date binary national character
nchar
6/15 PLS-00103: Encountered the symbol ":" when expecting one of the
following:
( - + all case mod new null <an identifier>
<a double-quoted delimited-identifier> <a bind variable>
LINE/COL ERROR
-------- -----------------------------------------------------------------
continue any avg count current max min prior some sql stddev
sum variance execute forall merge time timestamp interval
date <a string literal with character set specification>
<a number> <a single-quoted SQL string> pipe
<an alternatively-quoted string literal with character set
specification>
<an alternative
these are the errors which i encountered and the table regarding programmer is given below
prof1=proficieny 1
prof2= proficieny 2
SQL> desc programmer;
Name Null? Type
----------------------------------------- -------- ----------------------------
PNAME VARCHAR2(20)
DOB DATE
DOJ DATE
SEX CHAR(1)
PROF1 VARCHAR2(10)
PROF2 VARCHAR2(10)
SALARY NUMBER(5)
I don't have any idea why I am getting them please help me out.
Thank you in advance.

Get rid of the cursor, lose the loop, and get rid of the first if statement. Only the innermost if statement makes sense
create or replace trigger t2
before insert or update on programmer
for each row
begin
if :new.prof1 = :new.prof2
then
raise_application_error(-20091,'prof1 and prof2 should not be same');
end if;
end;
In a row-level trigger, you generally cannot query the table that the trigger is defined on. You can only make decisions based on the data in the :new and :old pseudo-records.

Related

PLSQL Return Sequence.currval When Sequence Name Is Built Using Substitution Strings

I would like to use the same application in different instances so I need to specify the workspace and sequence ID.
Example query
BEGIN
INSERT INTO STEP (STEP_CHART_TITLE)
VALUES ('Action', 'Action');
RETURN '"'||:v_workspace||'"."'||:v_seqid||'".currval';
END;
If I use:
"FREEADMIN"."ISEQ$$_111997".currval;
in the return statement it works fine.
If I use the substitution strings, it will build the string correctly, but won't return the sequence number.
Is there a way to get the sequence number?
Thanks
"PL/SQL" as Oracle's procedural extension to SQL? Asking because I don't quite understand what "workspace" represents (we call it a "user" or a "schema" or even "owner" in Oracle).
If so, then you can't fetch current value unless you first fetch next sequence value (you didn't post whole code you use so I'm not sure whether you did that or not; also, insert statement is wrong - you're inserting 2 values into a single column).
SQL> select seq.currval from dual;
select seq.currval from dual
*
ERROR at line 1:
ORA-08002: sequence SEQ.CURRVAL is not yet defined in this session
SQL> select seq.nextval from dual;
NEXTVAL
----------
6
SQL> select seq.currval from dual;
CURRVAL
----------
6
SQL>
Therefore, the whole code might look like this - you'd use dynamic SQL. As this is SQL*Plus, I'm using substitution variables; you'd use bind variables (i.e. :v_workspace instead of '&v_workspace') (if that's what you're doing). This code just displays the value - you'd return it.
SQL> create table step (id number, step_chart_title varchar2(10));
Table created.
SQL> declare
2 l_str varchar2(200);
3 l_id number;
4 begin
5 l_str := 'select ' || '&v_workspace' ||'.'|| '&v_seqid' ||'.nextval from dual';
6 execute immediate l_str into l_id;
7
8 insert into step (id, step_chart_title) values (l_id, 'Action');
9
10 dbms_output.put_line(l_id); --> L_ID now contains CURRVAL
11 end;
12 /
Enter value for v_workspace: scott
Enter value for v_seqid: seq
8 --> here it is
PL/SQL procedure successfully completed.
SQL>

PLSQL declare date like result of query

I would like to set variable for date of first monday from sysdate and return this day in put_line but it's not working. I working on oracle database
SET serveroutput on;
DECLARE
first_monday DATE;
BEGIN
first_monday := select NEXT_DAY(sysdate, 'MONDAY') from dual;
DBMS_OUTPUT.PUT_LINE(first_monday);
END;
/
result should be 06-04-20
what is wrong?
my error below
ERROR at line 4:
ORA-06550: line 4, column 29:
PLS-00103: Encountered the symbol "SELECT" when expecting one of the following:
( - + case mod new not null <an identifier>
<a double-quoted delimited-identifier> <a bind variable>
continue avg count current exists max min prior sql stddev
sum variance execute forall merge time timestamp interval
date <a string literal with character set specification>
<a number> <a single-quoted SQL string> pipe
<an alternatively-quoted string literal with character set specification>
<an alternat
ORA-06550: line 4, column 73:
PLS-00103: Encountered the symbol ")" when expecting one of the following:
. , # ; for <an identifier>
<a double-quoted delimited-identifier> group having intersect
minus order partition start subpartition union where connect
ORA-06550: line 8, column 0:
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
You can directly call next_day in PL/SQL (no need for a query). This is desirable because it doesn't cause a context switch between the PL/SQL engine and the SQL engine. Most, but not all, scalar functions can be used this way.
If you need to use it as part of a query then INTO is used to send a query result value into a variable.
Here are both in action.
DECLARE
first_monday DATE;
BEGIN
first_monday := next_day(SYSDATE,
'MONDAY');
dbms_output.put_line(first_monday);
SELECT next_day(SYSDATE,
'MONDAY')
INTO first_monday
FROM dual;
dbms_output.put_line(first_monday);
END;
/
The way to assign the result of a single row query to a variable in PL/SQL is via the INTO keyword. You need to change your code as follows:
DECLARE
first_monday DATE;
BEGIN
select NEXT_DAY(sysdate, 'MONDAY')
INTO first_monday
from dual;
DBMS_OUTPUT.PUT_LINE(first_monday);
END;

How to write procedure delete 3 months old records from table and send old count and new count over mail

I have written below procedure to delete records from table and record old and new rowcount in another table.
create or replace procedure delete_old_records_job as
DECLARE
COUNTER PLS_INTEGER:=1;
drop table SIEBEL.RETAILORDER_DETAILS_COUNT;
CREATE TABLE SIEBEL.RETAILORDER_DETAILS_COUNT (TABLE_COUNT_OLD varchar(64) NOT NULL,TABLE_COUNT_NEW varchar(64) NOT NULL);
insert into SIEBEL.RETAILORDER_DETAILS_COUNT( TABLE_COUNT_OLD )SELECT COUNT(*) FROM SIEBEL.Z_VIEWS_BACKUP;
BEGIN
WHILE COUNTER>0 LOOP
DELETE FROM SIEBEL.Z_VIEWS_BACKUP WHERE LAST_UPD < add_months(sysdate, -3) AND ROWNUM<25000;
COUNTER:=SQL%ROWCOUNT;
COMMIT;
END LOOP
insert into SIEBEL.RETAILORDER_DETAILS_COUNT( TABLE_COUNT_NEW )
SELECT COUNT(*) FROM SIEBEL.Z_VIEWS_BACKUP;
END;
I am getting below error while executing
SQL> show errors procedure delete_old_records_job;
Errors for PROCEDURE DELETE_OLD_RECORDS_JOB:
LINE/COL ERROR
-------- -----------------------------------------------------------------
2/1 PLS-00103: Encountered the symbol "DECLARE" when expecting one of
the following:
begin function pragma procedure subtype type <an identifier>
<a double-quoted delimited-identifier> current cursor delete
exists prior external language
The symbol "begin" was substituted for "DECLARE" to continue.
4/1 PLS-00103: Encountered the symbol "DROP" when expecting one of
the following:
begin function pragma procedure subtype type <an identifier>
<a double-quoted delimited-identifier> current cursor delete
LINE/COL ERROR
-------- -----------------------------------------------------------------
exists prior

ORA-06550 & PLS-00103 Errors when setting Oracle APEX item's default value

I am trying to set the default value of an item in Oracle APEX 4.2 by selecting the first value in a table having the specified VIDEO_ID. In the item, under the Default section I have set Default Value Type = PL/SQL EXPRESSION, and in the Default Value block I have entered
SELECT UNIQUE_ALLEGATION_ID
FROM (
SELECT UNIQUE_ALLEGATION_ID
FROM TBL_UNIQUE_ALLEGATION
WHERE VIDEO_ID = :P2_VIDEO_SELECT) A
WHERE ROWNUM <= 1
ORDER BY ROWNUM;
This code works just fine in my Oracle editor (if I replace :P2_VIDEO_SELECT with a value; and I am positive that :P2_VIDEO_SELECT is properly set).
However, when I run the page, I get the following error:
ORA-06550: line 1, column 43: PLS-00103: Encountered the symbol "SELECT" when expecting one of the following:
( - + case mod new not null <an identifier> <a double-quoted delimited-identifier> <a bind variable>
continue avg count current exists max min prior sql stddev sum variance execute forall merge time timestamp interval date
pipe
Remember that Apex attributes that accept SQL or PL/SQL fragments must be executed by the Apex at runtime, and that these must necessarily be embedded in wrapping code that must compile and execute at runtime.
So, for example, a source that is of type "PL/SQL Expression" will probably be executed in something like this:
declare
temp_var varchar2(4000);
begin
temp_var := (
SELECT UNIQUE_ALLEGATION_ID
FROM (
SELECT UNIQUE_ALLEGATION_ID
FROM TBL_UNIQUE_ALLEGATION
WHERE VIDEO_ID = :P2_VIDEO_SELECT) A
WHERE ROWNUM <= 1
ORDER BY ROWNUM
);
--use temp_var somewhere
end;
Obviously, the above code is not expected to work, which is why you're seeing an error like ORA-06550.

create procedure keyword won't work

if i write procedure creating code like this
declare
salary number :=20000;
employee_id number :=36325;
procedure give_bonus(emp_id in number,bonus in number) is
begin
dbms_output.put_line(emp_id);
dbms_output.put_line(bonus);
end;
begin
case
when salary >=10000 and salary <=20000 then
give_bonus(employee_id,1500);
when salary >= 20000 and salary <=40000 then
give_bonus(employee_id,1000);
when salary>40000 then
give_bonus(employee_id,500);
else
give_bonus(employee_id,0);
end case ;
end;
it writes on output
anonymous block completed
but if i write a head of procedure word this one
create or replace procedure give_bonus ,it writes errors,please help me why?
error is this
Error starting at line 1 in command:
declare
salary number :=20000;
employee_id number :=36325;
create or replace procedure give_bonus(emp_id in number,bonus in number) is
begin
dbms_output.put_line(emp_id);
dbms_output.put_line(bonus);
end;
begin
case
when salary >=10000 and salary <=20000 then
give_bonus(employee_id,1500);
when salary >= 20000 and salary <=40000 then
give_bonus(employee_id,1000);
when salary>40000 then
give_bonus(employee_id,500);
else
give_bonus(employee_id,0);
end case ;
end;
Error report:
ORA-06550: line 4, column 3:
PLS-00103: Encountered the symbol "CREATE" when expecting one of the following:
begin function pragma procedure subtype type <an identifier>
<a double-quoted delimited-identifier> current cursor delete
exists prior
06550. 00000 - "line %s, column %s:\n%s"
*Cause: Usually a PL/SQL compilation error.
*Action:
CREATE OR REPLACE only works for top-level objects. If you are declaring a procedure inside of another PL/SQL block, there is, by definition, nothing to replace. You aren't creating a procedure that will exist once the anonymous block finishes so there is nothing to replace. You're simply declaring a procedure that has the same scope as a local variable.
You could create a standalone procedure
create or replace procedure give_bonus(emp_id in number,bonus in number)
is
begin
dbms_output.put_line(emp_id);
dbms_output.put_line(bonus);
end;
and then reference that procedure in your anonymous PL/SQL block
declare
salary number :=20000;
employee_id number :=36325;
begin
case
when salary >=10000 and salary <=20000 then
give_bonus(employee_id,1500);
when salary >= 20000 and salary <=40000 then
give_bonus(employee_id,1000);
when salary>40000 then
give_bonus(employee_id,500);
else
give_bonus(employee_id,0);
end case ;
end;

Resources