PL/SQL Trigger in Oracle errors - oracle

i don't know how to start !!
i have a work in oracle database,and it is all about triggers and constraints ...
the work is to create triggers and constraints on some tables of database of league of hokey ...
and since i'm new , and not familiar with triggers i have a lot of errs!!!
let's take these two tables as exemple :
1/ "equipe" (means team) table :
Name Null? Type
----------------------------------------- -------- ----------------------------
ID_EQ NOT NULL NUMBER(6)
NOM VARCHAR2(50)
ENREGISTRMENT VARCHAR2(50)
ID_LIG NUMBER(6)
ID_CAPITAINE NUMBER(6)
ID_ENT NUMBER(6)
2/ "joueur" (means player) :
Name Null? Type
----------------------------------------- -------- ----------------------------
ID_JOU NOT NULL NUMBER(6)
NUMERO NUMBER(4)
POSITION VARCHAR2(50)
ID_EQ NUMBER(6)
where :
"id_eq" and "id_jou" are primary keys.
"joueur.id_eq" is referenced to "equipe.id_eq".
"equipe.id_capitaine" is referenced to "joueur.id_jou".
i want to create a trigger that write a msg of err if the user insert in or update the table "equipe" where the "capitaine" is not a player in the team ("equipe") , i try a lot , buttt ... always the msg:
Warning: Trigger created with compilation errors.
This is one of the triggers , if someone can find the err and fix it , or suggest a better one :
CREATE OR REPLACE TRIGGER capitaine_in_equipe
before UPDATE OR INSERT ON equipe
FOR EACH ROW
DECLARE
id_p joueur.id_eq%TYPE;
BEGIN
if (:new.iq_capitaine is not null ) then
SELECT id_eq INTO id_p
FROM joueur
WHERE id_jou = :new.iq_capitaine;
IF ( id_p != :new.id_eq ) THEN
raise_application_error(-20100,' the captain is not a player of the team');
END IF;
END IF;
END;
and if you know some good references of triggers, pl/sql Oracle for biggeners put it, please!
thank you ;)

Surely, there are other way to implement your logic, but if you want to use your trigger, the following works for me
Create equipe:
CREATE TABLE equipe
( ID_EQ number(6) not null,
NOM varchar2(50),
ENREGIS number(6),
ID_CAPITAINE number(6),
ID_ENT number(6),
CONSTRAINT equipe_pk PRIMARY KEY (ID_EQ)
);
Create joueur:
create table joueur
(ID_JOU number(6) not null,
NUMERO number(4),
POSITION varchar2(50),
ID_EQ number(6),
CONSTRAINT joueur_pk PRIMARY KEY (id_jou)
);
Alter both with the foreign key:
alter table equipe add(CONSTRAINT fk_equipe
FOREIGN KEY (ID_CAPITAINE)
REFERENCES joueur(ID_JOU));
alter table joueur add(CONSTRAINT fk_joueur
FOREIGN KEY (id_eq)
REFERENCES equipe(ID_EQ));
Create your trigger:
CREATE OR REPLACE TRIGGER capitaine_in_equipe
before UPDATE OR INSERT ON equipe
FOR EACH ROW
DECLARE
id_p joueur.id_eq%TYPE;
BEGIN
if (:new.id_capitaine is not null ) then
SELECT id_eq INTO id_p
FROM joueur
WHERE id_jou = :new.id_capitaine;
IF ( id_p != :new.id_eq ) THEN
raise_application_error(-20100,' the captain is not a player of the team');
END IF;
END IF;
END;
Notice in your tables definition, you mentioned a column id_capitaine. In your trigger you used the name iq_capitaine. I'm not sure if that reflects your real code or just a typo here.

Related

Bad bind variable in procedure in oracle

I'm trying to create a procedure that inserts a new row in a table deposit/uttag, throws an exception if you are not authorized to do this transaction. I'm supposed to create a function that checks if someone is authorized or not, and then use that function in this procedure.
I keep getting this error which I don't get:
Errors: PROCEDURE DO_UTTAG
Line/Col: 18/22 PLS-00049: bad bind variable 'NEW.PNR'
Line/Col: 18/31 PLS-00049: bad bind variable 'NEW.KNR'
Quick translations:
Saldo=balance
konto= account
pnr= personal number
knr= customer number
belopp= amount
These are the main tables:
CREATE TABLE bankkund(
PNR VARCHAR2(11) PRIMARY KEY,
FNAMN VARCHAR2(25) NOT NULL,
ENAMN VARCHAR2(25) NOT NULL ,
PASSWD VARCHAR2(16) NOT NULL,
UNIQUE(PASSWD));
CREATE TABLE kontotyp(
KTNR NUMBER(6)PRIMARY KEY,
KTNAMN VARCHAR2(20)NOT NULL,
RÄNTA NUMBER(5,2) NOT NULL);
CREATE TABLE konto(
KNR NUMBER(8)PRIMARY KEY,
KTNR NUMBER(6)NOT NULL,
REGDATUM DATE NOT NULL,
SALDO NUMBER(10,2),
FOREIGN KEY(ktnr) REFERENCES kontotyp(ktnr));
CREATE TABLE uttag(
RADNR NUMBER(9) PRIMARY KEY,
PNR VARCHAR2(11)NOT NULL,
KNR NUMBER(8)NOT NULL,
BELOPP NUMBER(10,2),
DATUM DATE NOT NULL,
FOREIGN KEY(pnr) REFERENCES bankkund(pnr),
FOREIGN KEY(knr) REFERENCES konto(knr));
This is the procedure:
create or replace procedure do_uttag (
p_radnr kontoägare.radnr%TYPE,
p_pnr bankkund.pnr%TYPE,
p_knr konto.knr%TYPE,
p_belopp uttag.belopp%TYPE)
as
v_saldo konto.saldo%type;
begin
select saldo
into v_saldo
from konto;
insert into uttag(
radnr, pnr, knr, belopp, datum
) values (
p_radnr, p_pnr, p_knr, p_belopp, SYSDATE
);
if get_behörighet(:NEW.PNR,:NEW.KNR) = 0
then
raise_application_error(-20101, 'Du har inte behörigheten!');
else
update konto
set saldo = v_saldo - p_belopp;
dbms_output.put_line('Saldot är nu = ' ||(v_saldo - p_belopp));
end if;
end;
/
This is the function that I created for authorization:
create or replace function get_behörighet (
p_pnr in bankkund.pnr%type,
p_knr in konto.knr%type)
return number
is
v_pnr bankkund.pnr%type;
v_knr konto.knr%type;
begin
select bankkund.pnr, konto.knr
into v_pnr, v_knr
from bankkund, konto
where bankkund.pnr = p_pnr
and konto.knr = p_knr;
return 1;
exception
when others then
return 0;
end;
/
Would really appreciate the help!!
get_behörighet(:NEW.PNR,:NEW.KNR)
this is a form of addressing fields allowed in triggers

Insert data into a table from anothe table in Oracle

I have two equal Oracle tables which have same column names.
1) DoctorProfile_New
2) DoctorProfile_Old
Both tables share the same structure as follows.
DOCREGNO NOT NULL VARCHAR2(10)
DOCCATOGARY NOT NULL VARCHAR2(10)
ANAME1 VARCHAR2(50)
ANAME2 VARCHAR2(50)
ANAME3 VARCHAR2(50)
ANAME4 VARCHAR2(50)
ANAME5 VARCHAR2(50)
ANAME6 VARCHAR2(50)
ANAME7 VARCHAR2(50)
ANAME8 VARCHAR2(50)
ANAME9 VARCHAR2(50)
AGENDER VARCHAR2(2)
ARESCTOWN VARCHAR2(100)
DOCRCODE NUMBER
What I need to do is insert all the data from table DoctorProfile_Old to DoctorProfile_New.
The only difference is for the column DOCREGNO, I have to insert new hard coded value.
insert into DoctorProfile_New
(
DOCREGNO,
DOCCATOGARY,
ANAME1,
ANAME2,
ANAME3,
ANAME4,
ANAME5,
ANAME6,
ANAME7,
ANAME8,
ANAME9,
AGENDER,
ARESCTOWN
)
values
('000081',
(
select
DOCCATOGARY,
ANAME1,
ANAME2,
ANAME3,
ANAME4,
ANAME5,
ANAME6,
ANAME7,
ANAME8,
ANAME9,
AGENDER,
ARESCTOWN
from DoctorProfile_Old WHERE DOCREGNO='T07004'
)
)
I tried the above query and it always gives the Oracle error
ORA-00947: not enough values
You can use insert select to do this;
insert into DoctorProfile_New (
DOCREGNO,
DOCCATOGARY,
ANAME1,
ANAME2,
ANAME3,
ANAME4,
ANAME5,
ANAME6,
ANAME7,
ANAME8,
ANAME9,
AGENDER,
ARESCTOWN
)
select
'000081',
DOCCATOGARY,
ANAME1,
ANAME2,
ANAME3,
ANAME4,
ANAME5,
ANAME6,
ANAME7,
ANAME8,
ANAME9,
AGENDER,
ARESCTOWN
from DoctorProfile_Old
WHERE DOCREGNO='T07004';
How about this?
insert into DoctorProfile_New
(DOCREGNO,DOCCATOGARY,ANAME1,ANAME2,ANAME3,ANAME4,ANAME5,ANAME6,ANAME7,ANAME8,ANAME9,AGENDER,ARESCTOWN)
select '000081' as DOCREGNO, DOCCATOGARY,ANAME1,ANAME2,ANAME3,ANAME4,ANAME5,ANAME6,ANAME7,ANAME8,ANAME9,AGENDER,ARESCTOWN from DoctorProfile_Old WHERE DOCREGNO='T07004';
If you want to insert DOCREGNO automatically instead of hard coated value, you should create trigger and use sequence value.
CREATE OR REPLACE TRIGGER DoctorProfile_New_TRG
BEFORE INSERT OR UPDATE ON DoctorProfile_New
REFERENCING OLD AS OLD NEW AS NEW
FOR EACH ROW
BEGIN
if :new.DOCREGNO is null then
select lpad(some_sequence.nextval, 6, '0') into :new.DOCREGNO from dual;
end if;
END;
Insert all data from DoctorProfile_Old
insert into DoctorProfile_New
(DOCREGNO,DOCCATOGARY,ANAME1,ANAME2,ANAME3,ANAME4,ANAME5,ANAME6,ANAME7,ANAME8,ANAME9,AGENDER,ARESCTOWN)
select null,DOCCATOGARY,ANAME1,ANAME2,ANAME3,ANAME4,ANAME5,ANAME6,ANAME7,ANAME8,ANAME9,AGENDER,ARESCTOWN from DoctorProfile_Old;

PL/SQL Error on trigger for auto_increment

I'm trying to auto_increment the cust_id field in the following table:
CREATE TABLE A113222813_CUSTOMERS (
CUST_ID NUMBER(10) PRIMARY KEY,
CUST_FNAME VARCHAR2(20),
CUST_SNAME VARCHAR2(20),
CUST_UNAME VARCHAR2(30) NOT NULL,
CUST_PASS VARCHAR2(40) NOT NULL
)
I create the following sequence and trigger to handle this:
CREATE SEQUENCE CUST_SEQ START WITH 1 INCREMENT BY 1 NOCYCLE;
CREATE OR REPLACE TRIGGER CUST_TRG
BEFORE INSERT ON A113222813_CUSTOMERS
FOR EACH ROW
BEGIN
:NEW.CUST_ID := CUST_SEQ.NEXTVAL;
END;
But it keeps throwing the following error:
Error(2,30): PLS-00357: Table,View Or Sequence reference 'CUST_SEQ.NEXTVAL' not allowed
in this context
Any idea what I am doing wrong?
This is not possible before 11g. You can use sequence_name.NEXTVAL in regular assignments from 11g not before that, and that by the following:
select CUST_SEQ.NEXTVAL into :NEW.CUST_ID from dual;

Create trigger with a cursor inside for multiple inserts

I want to create a trigger on every insert to the USERS table that will insert several entries to the BALANCES table, one entry for every coin id that exists in the SQL_COINS_VIEW view (hope i'm clear enough). The idea is that every time an account is created, it gets a balance 0 for each available coin in the list.
I tried this -
CREATE or REPLACE TRIGGER update_balances
AFTER INSERT
ON USERS
FOR EACH ROW
DECLARE
v_userid number(8);
cursor coinlist_cur is
select ID from SQL_COINS_VIEW;
BEGIN
select ID into v_userid from USERS;
For coinid in coinlist_cur
loop
insert into balances
(BALANCES_ID_SEQ.NEXTVAL,v_userid,coinid,0);
end loop;
END;
But i get an error -
Error(10,1): PL/SQL: SQL Statement ignored
Error(11,42): PL/SQL: ORA-01747: invalid user.table.column, table.column, or column specification
The tables are structures this way -
SQL> desc SQL_COINS_VIEW;
Name Null? Type
----------------------------------------- -------- ----------------------------
ID NOT NULL NUMBER(10)
NAME NOT NULL VARCHAR2(50)
VALUE NOT NULL NUMBER(18,6)
UPDATETIME NVARCHAR2(10)
SQL>
SQL> desc USERS;
Name Null? Type
----------------------------------------- -------- ----------------------------
ID NOT NULL NUMBER(8)
LOGINNAME NOT NULL VARCHAR2(12)
PASSWORD NOT NULL VARCHAR2(12)
EMAIL NOT NULL VARCHAR2(50)
PHONENUMBER VARCHAR2(25)
SQL>
SQL> desc BALANCES;
Name Null? Type
----------------------------------------- -------- ----------------------------
ID NOT NULL NUMBER(12)
USERID NOT NULL NUMBER(8)
COINID NOT NULL NUMBER(10)
AMOUNT NOT NULL NUMBER(30)
How can i properly create this trigger?
Thanks in advance.
Your insert is missing the values keyword; the error is from it trying to interpret the values as column names. And coinid is a record, so you need to refer to a field within that, which is id in the cursor declaration:
insert into balances
values (BALANCES_ID_SEQ.NEXTVAL,v_userid,coinid.id,0);
It's good practice to list the columns too though.

"cannot INSERT object view REF or user-defined REF"

I have a C_table and M_table and there is a m to 1 relationship between C_table and M_table, also I have L_table which Is A C_table type, , I'm trying to use OODBMS using oracle SQL Developer. I have the following types and tables:
create type C_table as object
(
se number(10),
sp number(10),
pr number(15),
me number(3),
ste S_type,
name ref M_type
)not final;
create type m_type as object
(
name varchar2(25),
add varchar(25)
);
type L_type under computer_type
(
w number(5)
);
and I have created their tables, as well, now I'm trying to insert into thhe L_table as follow and I'm getting the following error:
insert into l_tab select 500,2,1600,4, S_type('Ms','Me'), REF(d),1.5 from m_tab d where
d.name= 'Int';
SQL Error: ORA-22979: cannot INSERT object view REF or user-defined REF
22979. 00000 - "cannot INSERT object view REF or user-defined REF"
*Cause: Attempt to insert an object view REF or user-defined REF in a
REF column created to store system generated REF values"
*Action: Make sure the REF to be inserted is not from an object view
or from a user-defined REF column
I'm sorry I can't load the full script because of the confidential rights. But I'm happy to share the solution to this problem.
create type C_table as object
(
se number(10),
sp number(10),
pr number(15),
me number(3),
ste S_type,
name ref M_type
)not final;
create type m_type as object
(
name varchar2(25),
add varchar(25)
);
type L_type under computer_type
(
w number(5)
);
Based on ERD we have already knew that L_type Is-A C_type, and we know C_type has a reference to M_type. When I created the table out of these types, I did't know I have to define a foreign key from M_table in L_table as well, and I was thinking since L_table derived from C_table, if I define the foreign key in the C_table is enough, but it was not enough and I had to define a foreign key from M_table in L_table as well like this
create table C_table of C_type
(foreign key (name) references M_table)
object id primary key
and also :
create table l_table of l_type
(foreign key (name) references M_table)
object id primary key
now if I use this query I won't have any problem or error:
insert into l_tab select 500,2,1600,4, S_type('Ms','Me'), REF(d),1.5 from m_tab d where
d.name= 'Int';
also I read in some blogs that we have to be careful to don't use system names, and predefined name as an attribute in a table, like in this example I used name in M_table, which is not a good way, so finally I changed it to M_name instead of name.

Resources