Related
I am using Oracle database 19c for a project. I have created the alumni table as shown below:
CREATE TABLE Alumni (
ID NUMBER GENERATED ALWAYS AS IDENTITY ,
First_Name varchar2(20) NOT NULL,
Last_Name varchar2(20) NOT NULL,
Gender char(1) NOT NULL,
CHECK (Gender IN('M','F')),
Graduation_Year number NOT NULL,
check (Graduation_Year>=1980 AND Graduation_Year<=2020),
Degree_Course varchar2(255) not null,
Award_Nominated CHAR(1),
CHECK (Award_Nominated IN('Y','N')),
Award_Won CHAR(1),
CHECK (Award_Won IN('Y','N')),
Phone_Number VARCHAR2(15) not null,
Email_Address VARCHAR2(255) not null,
CONSTRAINT ALUM_PK PRIMARY KEY(ID)
);
Then I tried to define a function that will allow me to search by First or last name in a section of the table, shown below:
CREATE OR REPLACE TYPE alum_row_type is object(ID number,First_name varchar2(20),Last_Name
varchar2(20),Phone_number varchar2(15),Email_Address varchar2(255));
CREATE OR REPLACE TYPE t_alum_row_type as table of alum_row_type;
CREATE OR REPLACE FUNCTION Name_Search RETURN t_alum_row_type
IS
L_alum_row t_alum_row_type := t_alum_row_type();
X integer :=0;
BEGIN
FOR R IN (SELECT ID,First_Name, Last_Name,Phone_Number,Email_Address FROM alumni)
LOOP
L_alum_row.extend;
X:=X+1;
L_alum_row(X):= alum_row_type(X.ID,X.First_Name, X.Last_Name, X.Phone_Number, X.Email_Address);
END LOOP;
RETURN L_alum_row;
END;
After running this, I get this error:
LINE/COL ERROR
--------- -------------------------------------------------------------
10/9 PL/SQL: Statement ignored
10/41 PLS-00487: Invalid reference to variable 'X'
Errors: check compiler log
How can I resolve this issue. I am relatively new to PL\SQL, so please explain it simply.
This is not possible
L_alum_row(X):= alum_row_type(X.ID,X.First_Name, X.Last_Name, X.Phone_Number, X.Email_Address);
You are referencing X.ID, X.Phone_Number etc. . . but declared X as an integer. If you are trying to access the current loop record, try with
L_alum_row(X):= alum_row_type(R.ID,R.First_Name, R.Last_Name, R.Phone_Number, R.Email_Address);
As you declared the loop iterator as R for your cursor
FOR R IN (SELECT ID,First_Name, Last_Name,Phone_Number,Email_Address FROM alumni)
You can eliminate the loop altogether by using BULK COLLECT. Thereby reducing the function to basically a single select statement.
function name_search
return t_alum_row_type
is
l_alum_row t_alum_row_type := t_alum_row_type();
begin
select alum_row_type(id,first_name, last_name,phone_number,email_address)
bulk collect
into l_alum_row
from alumni;
return l_alum_row;
end;
Error code 4098, SQL state 42000: ORA-04098: trigger 'HR.TRGM_ID' is invalid and failed re-validation
I'm getting this problem. What should I do?
create table kids(
id integer primary key,
mbrand varchar(100) ,
mmodel varchar(100),
mprice integer,
mquantity integer,
mdescription varchar(100),
mphoto varchar(100)
);
CREATE SEQUENCE id_seq;
create trigger trgk_id
before insert on kids
for each row
begin
select id_seq.nextval
into :new.id
from dual;
It seems that you shouldn't do anything. Everything works OK, as far as code you posted is concerned (apart from the fact that END is missing).
On the other hand, Oracle complains about trigger whose name is TRGM_ID, while the one whose code we have is named TRGK_ID. Are we talking about the same trigger?
SQL> create table kids(
2 id integer primary key,
3 mbrand varchar(100) ,
4 mmodel varchar(100),
5 mprice integer,
6 mquantity integer,
7 mdescription varchar(100),
8 mphoto varchar(100)
9 );
Table created.
SQL> CREATE SEQUENCE id_seq;
Sequence created.
SQL> create trigger trgk_id
2 before insert on kids
3 for each row
4 begin
5 select id_seq.nextval
6 into :new.id
7 from dual;
8 end;
9 /
Trigger created.
SQL> insert into kids (mbrand) values ('Nike');
1 row created.
SQL> select id, mbrand from kids;
ID MBRAND
---------- ----------
1 Nike
SQL>
The problem is simply that your trigger is missing its END statement. Rewrite the trigger as
create OR REPLACE trigger trgk_id
before insert on kids
for each row
begin
select id_seq.nextval
into :new.id
from dual;
END TRGK_ID; -- added
and you should be good.
dbfiddle here
For Oracle11g no need to use currval and nextval pseudocolumns
within a SQL query statement, rather usable within a PL/SQL
expression.
So, avoid using :
select id_seq.nextval
into :new.id
from dual;
and use directly
:new.id := id_seq.nextval;
instead.
P.S. of course, do the above after fullfilling your main issue of adding an end clause at the end of the trigger.
The error say "TRGM_ID" (with "m"):
Error code 4098, SQL state 42000: ORA-04098: trigger 'HR.TRGM_ID' is invalid and failed re-validation
Your code say "TRGK_ID" (with "k"):
create trigger trgk_id
Check "TRGM_ID" code, or try recompile trigger:
alter trigger [nameOfTrigger] compile;
If you're using Oracle 12c or newer, you could use an identity column instead of manually creating a sequence and trigger. Much cleaner:
create table kids(
id integer generated always as identity primary key,
mbrand varchar(100) ,
mmodel varchar(100),
mprice integer,
mquantity integer,
mdescription varchar(100),
mphoto varchar(100)
);
https://oracle-base.com/articles/12c/identity-columns-in-oracle-12cr1
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;
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.
I have a stored procedure in Oracle 9i which inserts records in a table. The table has a primary key built to ensure duplicte rows doesnot exists.
I am trying to insert a record by calling this stored procedure and it works first time properly. I am again trying to insert a duplicate record and expecting unique constraint violation error. But I am getting
ORA-01401 inserted value too large for column
I knew its meaning but my query is , if the value inserted is really large then how it got successful in the first attempt.
Table is
CREATE TABLE KEY
(
ID VARCHAR2(25 BYTE),
KEY NUMBER(4) NOT NULL,
INSERT_DATE DATE,
WORK_KEY VARCHAR2(128 BYTE)
)
CREATE UNIQUE INDEX SACHINIDX ON KEY
(ID, KEY)
Call is
EXEC SQL EXECUTE
BEGIN
keyadd(:id, :key, :wkey);
END;
END-EXEC;
Stored Procedure is
PROCEDURE keyadd(id IN VARCHAR2, key IN NUMBER, wkey IN VARCHAR2)
{
BEGIN
INSERT INTO KEY
( ID,
KEY,
INSERT_DATE,
WORK_KEY)
VALUES
(
id,
key,
SYSDATE,
wkey
);
EXCEPTION
ROLLBACK;
COMMIT;
RETURN;
END;
}
First insert sqlca.sqlcode is [0]
Second insert sqlca.sqlcode is [-1401]
CREATE TABLE KEY
(
ID VARCHAR2(25 BYTE),
KEY NUMBER(4) NOT NULL,
INSERT_DATE DATE,
WORK_KEY VARCHAR2(128 BYTE)
);
CREATE UNIQUE INDEX SACHINIDX ON KEY
(ID, KEY);
create or replace PROCEDURE keyadd(id IN VARCHAR2, key IN NUMBER, wkey IN VARCHAR2)
is
BEGIN
INSERT INTO KEY
( ID,
KEY,
INSERT_DATE,
WORK_KEY)
VALUES
(
id,
key,
SYSDATE,
wkey
);
COMMIT;
-- EXCEPTION when others then
-- ROLLBACK;
end keyadd;
/
begin
keyadd('one', 1, '59FC9AD0FA5A8932836824B0489B73252C120301A2205154C096B4EB213FA983D5E500B62A469439');
keyadd('one', 1, '905BD61AAEC986ACF887DBA7C04D650B61A8818ABEBE1720D810B4A426EB9220558B530D5119315F');
end;
/
gives me the expected ORA-00001: Unique Constraint... error, not an ORA-01401. So, without further information its impossible to help.
I don't know the language the procedure was written in, but this part:
EXCEPTION
ROLLBACK;
COMMIT;
RETURN;
raises my eyebrows. Two questions:
What is this supposed to do?
Is your issue solved when you remove those lines?
My best guess is on your second try, you are providing a value for one of the other columns that is too large. Looks like this error will supersede the primary key violation.