Type created with compilation errors - oracle

Code:
CREATE OR REPLACE TYPE Address AS OBJECT (
city VARCHAR2(15),
state VARCHAR2(15),
pin NUMBER(6));
CREATE OR REPLACE TYPE Student AS OBJECT (
id NUMBER(3),
fName VARCHAR2(10),
lName VARCHAR2(10),
dob DATE,
phone NUMBER(10),
address Address
) NOT FINAL;
CREATE OR REPLACE TYPE Course UNDER Student (
dept VARCHAR2(20),
sem VARCHAR2(20));
Errors:
Error for Type Student:
Warning: Type created with compilation errors.
LINE/COL ERROR
-------- -----------------------------------------------------------------
0/0 PL/SQL: Compilation unit analysis terminated
7/9 PLS-00320: the declaration of the type of this expression is
incomplete or malformed
Error for Type Course:
Warning: Type created with compilation errors.
LINE/COL ERROR
-------- -----------------------------------------------------------------
0/0 PL/SQL: Compilation unit analysis terminated
1/19 PLS-00905: object SYS.STUDENT is invalid
I know the error in Type Course would be resolved after clearing the error in Type Student, but adding it just in case.

You can't have "address Address"... the property/column name conflicts with the type name. Rename it something else: "student_address Address", or rename the types so you can use "address addresstype" or something of that nature. E.g.:
CREATE OR REPLACE TYPE AddressType AS OBJECT (
city VARCHAR2(15),
state VARCHAR2(15),
pin NUMBER(6));
CREATE OR REPLACE TYPE StudentType AS OBJECT (
id NUMBER(3),
fName VARCHAR2(10),
lName VARCHAR2(10),
dob DATE,
phone NUMBER(10),
address AddressType -- avoids name conflict
) NOT FINAL;
CREATE OR REPLACE TYPE CourseType UNDER StudentType (
dept VARCHAR2(20),
sem VARCHAR2(20));

Related

ORA-00904: invalid identifier from PL/SQL code while the SQL part within works

When I defined a PL/SQL function in SQL developer and tried to run it, it returned "ORA-00904: "SYS"."FUNC1": invalid identifier;00904. 00000 - "%s: invalid identifier"", which isn't very helpful. I don't know what has gone wrong. The SQL part alone can run though.
the PL/SQL that return error
CREATE OR REPLACE FUNCTION func1 (
emp_id IN NUMBER
) RETURN NUMBER AS
emp_fname VARCHAR2(50);
BEGIN
SELECT
firstname
INTO emp_fname
FROM
employees
WHERE
employeeid = emp_id;
RETURN emp_fname;
END func1;
/
select sys.func1(9) from dual;
the SQL that run
SELECT
firstname
FROM
employees
WHERE
employeeid = 9;
Definition of Table Employees
Name Null? Type
--------------- -------- -------------
EMPLOYEEID NOT NULL NUMBER
LASTNAME NOT NULL VARCHAR2(20)
FIRSTNAME NOT NULL VARCHAR2(10)
TITLE VARCHAR2(30)
TITLEOFCOURTESY VARCHAR2(25)
BIRTHDATE DATE
HIREDATE DATE
ADDRESS VARCHAR2(60)
CITY VARCHAR2(15)
REGION VARCHAR2(15)
POSTALCODE VARCHAR2(10)
COUNTRY VARCHAR2(15)
HOMEPHONE VARCHAR2(24)
EXTENSION VARCHAR2(4)
PHOTO LONG RAW
NOTES VARCHAR2(600)
REPORTSTO NUMBER
PHOTOPATH VARCHAR2(255)
Please help!
Test environment:
OS: Oracle Linux 7.9
Oracle DB 21c Express Edition for Linux
SQL Developer for Linux 21.2.1.204 build 204.1703
Don't use SYS as a work area. If you mess with any of the system tables then you may make your database unusable.
Use the SYS user to create a new user and then work in that user's schema.
Your function compiles successfully; however, it will fail at runtime (except for those rare people who are known by numbers and not names) as the signature is RETURN NUMBER but it returns the firstname which is a string and you would get the exception:
ORA-06502: PL/SQL: numeric or value error: character to number conversion error
ORA-06512: at "FIDDLE_RAHCBFZAHWTUCSZNOWGB.FUNC1", line 14
You can fix it by making the return type the same as the firstname column and the simplest method is to use %TYPE. You also ought to handle a NO_DATA_FOUND exception:
CREATE OR REPLACE FUNCTION func1 (
emp_id IN EMPLOYEES.EMPLOYEEID%TYPE
) RETURN EMPLOYEES.FIRSTNAME%TYPE
AS
emp_fname VARCHAR2(50);
BEGIN
SELECT firstname
INTO emp_fname
FROM employees
WHERE employeeid = emp_id;
RETURN emp_fname;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN NULL;
END func1;
/
If you have the sample data:
INSERT INTO employees (employeeid, lastname, firstname)
VALUES (9, 'Abbots', 'Alice');
Then:
select func1(9) from dual;
Outputs:
FUNC1(9)
Alice
db<>fiddle here

How can I deal with PL-SQL package error PLS-00103: Encountered the symbol "(" when expecting one of the following: := )

There is a similar answer for the problem I have, but it seems that this answer is for procedure issue.
I supposed to make a pl sql package which has 3 procedures inside. It's gonna be like that:
CREATE OR REPLACE PACKAGE Count_num AS
PROCEDURE count_emps(dno IN number);
PROCEDURE count_deps(empssn IN char(9));
PROCEDURE delete_deps(empssn IN char(9), dname IN varchar2(15));
END;
/
show errors
CREATE OR REPLACE PACKAGE BODY Count_num AS
PROCEDURE count_emps(dno IN number)
AS
cnt number;
BEGIN
SELECT COUNT(*) INTO cnt
WHERE Department.dnumber = Employee.dno
AND Department.dnumber = dno;
dbms_output.put_line('Number of Employee is ' || cnt);
END;
PROCEDURE count_deps(empssn IN char(9))
AS
cnt2 number;
BEGIN
SELECT COUNT(*) INTO cnt2
WHERE Dependent.essn = Employee.ssn
AND Department.essn = empssn;
dbms_output.put_line('Number of dependent is ' || cnt2);
END;
PROCEDURE delete_deps(empssn IN char(9), dname IN varchar2(15))
AS
BEGIN
DELETE *
FROM Dependent
WHERE Dependent.essn = Employee.ssn
AND Dependent.essn = empssn
AND Dependent.dependent_name = dname;
SELECT *
FROM Dependent
WHERE Dependent.essn = Employee.ssn
AND Dependent.essn = empssn
AND Dependent.dependent_name = dname;
END;
END;
/
show errors
EXEC Count_num.count_emps(5);
EXEC Count_num.count_deps('333445555');
EXEC Count_num.delete_deps('333445555', 'Alice')
show errors
count_emps counts the number of employees for a department,
count_deps counts the number of dependents for a valid employee,
delete_deps deletes a specific depdendent. It's creation query is like below:
drop table Employee cascade constraints;
commit;
create table Employee
(
fname varchar2(15),
minit varchar2(1), -- can be char
lname varchar2(15),
ssn char(9),
bdate date,
address varchar2(50),
sex varchar2(1) CHECK(Sex = 'M' or Sex = 'F'),
salary number, -- need to put check on salary
superssn char(9),
dno number DEFAULT 0,
constraint EMPPK
primary key(ssn),
constraint EMPSUPERVRFK
foreign key(superssn) references Employee(ssn)
ON DELETE SET NULL
);
drop table Department cascade constraints;
commit;
create table Department
(
dname varchar2(15) NOT NULL,
dnumber number,
mgr_ssn char(9) DEFAULT '000000000',
mgr_start_date date,
constraint DEPTPK
primary key(dnumber),
constraint DEPTMGRFK
foreign key(mgr_ssn) references Employee(ssn)
ON DELETE SET NULL
);
drop table Dependent cascade constraints;
commit;
create table Dependent
(
Essn char(9),
Dependent_name varchar2(15),
Sex varchar2(15),
Bdate date,
Relationship varchar2(15),
constraint DEPENDPK
primary key (Essn, Dependent_name),
constraint DEPENDFK
foreign key(Essn) references Employee(Ssn)
);
When I execute package queries, it gives me an error like below:
SQL> CREATE OR REPLACE PACKAGE Count_num AS
2 PROCEDURE count_emps(dno IN number);
3 PROCEDURE count_deps(empssn IN char(9));
4 PROCEDURE delete_deps(empssn IN char(9), dname IN varchar2(15));
5 END;
6 /
Warning: Package created with compilation errors.
Elapsed: 00:00:00.02
SQL> show errors
Errors for PACKAGE COUNT_NUM:
LINE/COL ERROR
-------- -----------------------------------------------------------------
3/37 PLS-00103: Encountered the symbol "(" when expecting one of the
following:
:= ) , default varying character large
The symbol ":=" was substituted for "(" to continue.
4/38 PLS-00103: Encountered the symbol "(" when expecting one of the
following:
:= ) , default varying character large
The symbol ":=" was substituted for "(" to continue.
4/60 PLS-00103: Encountered the symbol "(" when expecting one of the
LINE/COL ERROR
-------- -----------------------------------------------------------------
following:
:= . ) , # % default character
The symbol ":=" was substituted for "(" to continue.
I can't recognize what this error is, so anyone can explain what this error is, and how can I handle this issue?
Remove the length specified for the data types in the arguments.
Also, better to specify the column data type than hard-coding it.
CREATE OR REPLACE PACKAGE Count_num AS
PROCEDURE count_emps(i_dno IN employee.dno%TYPE);
PROCEDURE count_deps(i_empssn IN employee.ssn%TYPE);
PROCEDURE delete_deps(i_empssn IN employee.ssn%TYPE,
i_dname IN department.dname%TYPE
);
END;
/

PL/SQL Trigger in Oracle errors

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.

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