ORA-00933: SQL command not properly ended? Enter Bind Variables? - sql

I am attempting to write out in my SQL commands for Oracle Apex 5, and I cannot see why I'm getting an error. Also, a popup window appears once I submit asking to 'Enter Bind Variables' for ':NEW'? Isn't it already declared?
drop table tmpcapacityguide cascade constraints;
drop table tmpcaravanpark cascade constraints;
create table tmpcaravanpark as select * from Caravan_park;
create table tmpcapacityguide
(mincap number(3),
maxcap number(3));
insert into tmpcapacityguide values(30, 150);
CREATE OR REPLACE TRIGGER "PARK_CAPACITY_CHECK"
before insert or update of capacity
on Caravan_park
for each row
when (:new.capacity < 30) DECLARE
mincapacity integer;
maxcapacity integer;
begin
select mincap, maxcap
into mincapacity, maxcapacity
from tmpcapacityguide
where capacity = :new.capacity;
if (new.capacity < mincapacity)
then raise_application_error(-20601, 'Capacity must be between 30 and 150');
end if;
end;

:new.capacity is input and has to be declared. For more info see here: http://www.akadia.com/services/ora_bind_variables.html

Try using slashes, and name of trigger after last end, and also You do not need ":" sign before new variable in IF statement:
drop table tmpcapacityguide cascade constraints;
drop table tmpcaravanpark cascade constraints;
create table tmpcaravanpark as select * from Caravan_park;
create table tmpcapacityguide (mincap number(3), maxcap number(3));
/
insert into tmpcapacityguide values(30, 150);
/
CREATE OR REPLACE TRIGGER PARK_CAPACITY_CHECK
before insert or update of capacity on caravan_park
for each row
when (new.capacity < 30)
declare
mincapacity integer;
maxcapacity integer;
begin
select mincap, maxcap
into mincapacity, maxcapacity
from tmpcapacityguide
where capacity = :new.capacity;
if (new.capacity < mincapacity)
then
raise_application_error(-20601, 'Capacity must be between 30 and 150');
end if;
end PARK_CAPACITY_CHECK;
/
Also, You should execute it as a script, not statement in SQL Developer. This can be done by pressing F9, not F5, as sstated here.
EDIT:
As for Your ORA-00904 error, You still do not have capacity column in Your tmpcapacityguide table. And You try to use it here:
select mincap, maxcap
into mincapacity, maxcapacity
from tmpcapacityguide
where capacity = :new.capacity;

Related

problem creating PL/SQL procedure and sequence

Here I have a question that I need to write a PL/SQL. The structure of the database is also linked. The question requires to use a sequence inside a procedure. I'm new to this and don't know if this works properly and my exec command doesn't seem working please help me out. Also is this how to look up the max shareholder_id that the sequence should start with, or can I a select inside create sequence?
Write a PL/SQL procedure called INSERT_DIRECT_HOLDER which will be used to insert new direct holders. Create a sequence to automatically generate shareholder_ids. Use this sequence in your procedure.
-Input parameters: first_name, last_name
DROP SEQUENCE shareholder_id_seq;
SELECT
MAX(shareholder_id)
FROM shareholder;
CREATE SEQUENCE shareholder_id_seq
INCREMENT BY 1
START WITH 25;
CREATE OR REPLACE PROCEDURE insert_direct_holder(
p_first_name in direct_holder.first_name%type,
p_last_name in direct_holder.last_name%type)
IS
v_shareholder_id NUMBER(6);
BEGIN
INSERT INTO DIRECT_HOLDER(direct_holder_id,first_name,last_name) values(shareholder_id_seq.nextval, p_first_name, p_last_name);
INSERT INTO shareholder (shareholder_id, type) VALUES (shareholder_id_seq.nextval,'Direct_Holder');
COMMIT;
END;
/
/* test command*/
exec insert_direct_holder( p_first_name, p_last_name );
You need to insert the record with same ID in both the tables.
also, you need to insert record into your parent table (shareholder) first and then child table(direct_holder).
CREATE OR REPLACE PROCEDURE insert_direct_holder(
p_first_name in direct_holder.first_name%type,
p_last_name in direct_holder.last_name%type)
IS
v_shareholder_id NUMBER(6);
BEGIN
v_shareholder_id := shareholder_id_seq.nextval;
INSERT INTO shareholder (shareholder_id, type) VALUES (v_shareholder_id,'Direct_Holder');
INSERT INTO DIRECT_HOLDER(direct_holder_id,first_name,last_name) values(v_shareholder_id, p_first_name, p_last_name);
COMMIT;
END;
/
/* test command*/
exec insert_direct_holder( p_first_name, p_last_name );
Sequence is created once to implement auto incrementing feature for any numeric column.
For the current use case it has to be created just once and left forever hopefully.Sequence can be modified in future if required.
If shareholder table has records in it already, then create the sequence with start value as SELECT MAX(shareholder_id) + 1 FROM shareholder; to avoid primary key constraint violation.
A slight modification is required for the stored procedure to use the same SHAREHOLDER.SHAREHOLDER_ID as the column has foreign key relationship with DIRECT_HOLDER.
Use INSERT ALL to insert to both the tables for the same sequence.nextval.
CREATE OR REPLACE PROCEDURE insert_direct_holder(
p_first_name in direct_holder.first_name%type,
p_last_name in direct_holder.last_name%type)
IS
BEGIN
INSERT ALL
INTO SHAREHOLDER
(shareholder_id, type) values(shareholder_id_seq.nextval,'Direct_Holder')
INTO DIRECT_HOLDER
(direct_holder_id,first_name,last_name) values
(shareholder_id_seq.nextval,p_first_name,p_last_name)
SELECT 'DUMMY' FROM dual;
COMMIT;
END;
/
dbfiddle demo with working code : https://dbfiddle.uk/?rdbms=oracle_18&fiddle=5d80488fb69d78d4b5087f06a5becf96

Mutating trigger in Oracle

I create the following tables:
create table lessons(
id number,
name_teacher varchar2(9),
name_student varchar2(40),
start_lesson date,
end_lesson date
);
I inserted the following datas:
insert into lessons values (001,'Peter','Thomas',to_date('2015-12-15','YYYY-MM-DD'),to_date('2015-12-22','YYYY-MM-DD'));
insert into lessons values (002,'Eli','Alice',to_date('2015-06-16','YYYY-MM-DD'),to_date('2015-06-23','YYYY-MM-DD'));
insert into lessons values (003,'Daniel','Thomas',to_date('2015-08-15','YYYY-MM-DD'),to_date('2015-08-20','YYYY-MM-DD'));
Data that you cant add by the trigger.
insert into lessons values (001,'Peter','Alice',to_date('2015-12-16','YYYY-MM-DD'),to_date('2015-12-25','YYYY-MM-DD'));
insert into lessons values (002,'Eli','Thomas',to_date('2015-06-13','YYYY-MM-DD'),to_date('2015-06-20','YYYY-MM-DD'));
The question is how to make a trigger that does not allow me to add students who have teachers who overlap in time, like "Peter" or "Eli".
--- My problem ---
Oracle returns me an error of mutants tables.
you neen an after insert / update Trigger that fire after the comlete insert or update and not after earch row:
create or replace trigger check_intersections_trg
on
lessons
after insert or update
declare
v_res NUMBER;
begin
select count(*)
into v_res
from lessons l1
join lessons l2 on l1.name_student = l2.name_student
and l1.start_lesson <= l2.end_lesson
and l2.start_lesson <= l1.end_lesson
;
if v_res > 0 than
raise_application_error( -20999, 'intersection found');
end if;
end;
/

ORA-24344: success with compilation error - Trigger APEX

I've been working around this trigger and when I run the script it tells me the previous error message. I can't seem to figure out why it won't compile correctly, every pl/sql trigger tutorial seems to have the structure my trigger has. Code is the following:
create
or replace trigger new_artist before insert
on
Artist referencing new as nvartist declare counter number;
begin select
count( * ) into
counter
from
Performer
where
Stage_name = nvartist.Stage_name;
if counter > 0 then signal sqlstate '45000';
else insert
into
Artist
values(
nvartist.Stage_name,
nvartist.Name
);
insert
into
Performer
values(nvartist.Stage_name);
end if;
end;
It checks if the new artist already exists in its supertype (Performer), if it does exist it gives an error if it doesn't it inserts both into artist(Stage_name varchar2, Name varchar2) and Performer(Stage_name). Another subtype of Performer (and sibling to Artist) is Band(Stage_name), which in turn has a relationship with Artist. Why does the compiler yell at me for this trigger?
Thanks in advance
You may want to try this variant (I slightly modified names of your tables).
Creating tables with sample data:
CREATE table test_artist(
stage_name varchar2(100)
, name varchar2(100)
);
create table test_performer(
stage_name varchar2(100)
);
/*inserting test performer on which trigger will rise an error*/
insert into test_performer
select 'performer_1' from dual;
Creating trigger:
create or replace trigger new_artist
before insert
on TEST_ARTIST
referencing new as nvartist
for each row
declare
counter number;
begin
select count(*)
into counter
from test_performer
where Stage_name = :nvartist.Stage_name;
if counter > 0 then
--signal sqlstate '45000' ;
raise_application_error( -20001, 'No insertion with existing Performer');
else
/*you cant update the same table, in other case you'll get
ora-04091 table mutating error.
But nevertheless this values will be inserted by sql triggered this trigger.*/
--insert into test_artist values(:nvartist.Stage_name, :nvartist.Name);
insert into test_performer values(:nvartist.Stage_name);
end if;
end new_artist;
After that this insert will work, cause the is no 'performer_2' in 'test_performer' table:
insert into test_artist
select 'performer_2', 'name_2' from dual;
And this will fail:
insert into test_artist
select 'performer_1', 'name_1' from dual;

Update Trigger PL/SQL in Oracle [duplicate]

I create the following tables:
create table products
(
code varchar(9),
group_code varchar(9),
price number,
CONSTRAINT pk_code PRIMARY KEY (code)
);
I created a trigger , for that the price per group of products does not exceed 100 dollars:
create or replace trigger nomore100
before insert or update on products
for each row
declare
cursor c_total is
select group_code, sum(price) as total_price
from products
where group_code=:new.group_code
group by group_code;
v_total c_total%rowtype;
begin
for v_total in c_total loop
if v_total.total_price+:new.price > 100 then
raise_application_error(-20150,'No more than 100 dollars');
end if;
end loop;
end nomore100;
/
The trigger works for inserts, but when i try to do a update:
update products set price=120 where code='PX1';
Oracle return:
"table %s.%s is mutating, trigger/function may not see it"
Thanks for any suggestions or answers, have a nice day!

Time constraint on a sql trigger

I have the following table called employees
create table employees
(
eno number(4) not null primary key,
ename varchar2(30),
zip number(5) references zipcodes,
hdate date
);
And I'm trying to set a trigger on the table that will fire before an update or delete that will check the system time first to see if the time is between 12:00-13:00, if it is it will allow the insertion, otherwise prevent it.
My guess is so far:
CREATE or REPLACE TRIGGER twelve_one
BEFORE INSERT or Update ON employees
BEGIN
IF
....
ELSE
....
END;
But that's how far I've gotten into unfortunately. Can someone please help me to retrieve the system time first? Then how can I set up that IF ELSE block? And finally How to abort the transaction/insertion/update?
I'm using Oracle SQL Developer 4.02.15
Many Thanks
I assume you must declare temporary variable to set time now, and then compare the temporary variable.
CREATE OR REPLACE TRIGGER TWELVE_ONE
BEFORE INSERT OR UPDATE
ON EMPLOYEES
FOR EACH ROW
DECLARE
V_DATE VARCHAR2 (10);
BEGIN
SELECT TO_CHAR (SYSDATE, 'hh24:mi:ss') INTO V_DATE FROM DUAL;
IF (V_DATE >= '12:00:01' AND V_DATE < '13:00:00')
THEN
INSERT INTO TABLE ..
ELSE
UPDATE TABLE...
END IF;
END;