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

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.

Related

RTTI in Oracle Triggers

I have this dummy types :
create or replace type Service_TY as object(
code INTEGER,
visit_analysis char(1)
)FINAL;
/
create or replace type Employee_TY as object(
dummy varchar(30)
)NOT FINAL;
/
create or replace type Doctor_TY UNDER Employee_TY(
ID INTEGER
)FINAL;
/
create or replace type Assistant_TY UNDER Employee_TY(
ID INTEGER
)FINAL;
/
create or replace type Habilitation_TY as object(
employee ref Employee_TY,
service ref Service_TY
)FINAL;
/
And these dummy tables:
CREATE TABLE Service of Service_TY(
code primary key,
visit_analysis not null check (visit_analysis in ('v', 'a'))
);
/
CREATE TABLE Doctor of Doctor_TY(
ID primary key
);
/
CREATE TABLE Assistant of Assistant_TY(
ID primary key
);
/
CREATE TABLE Habilitation of Habilitation_TY;
/
I want to create a trigger that, when a new tuple is inserted in Habilitation, should check that, if the employee is an assistant (and not a doctor), the visit_analysis attribute is equal to 'a' to know if it is a legal tuple.
I don't know how to check the type of the Employee (if it is a doctor or an assistant).
I would do something like that:
create or replace
TRIGGER CHECK_HABILITATION
BEFORE INSERT ON HABILITATION
FOR EACH ROW
DECLARE
BEGIN
IF (:NEW.EMPLOYEE is of ASSISTANT_TY)
THEN
IF :NEW.SERVICE.visit_analysis = 'v'
THEN
raise_application_error(-10000, 'invalid tuple');
END IF;
END;
But it's not working.
How should I check that type?
The error I get is:
Error(14,4): PLS-00103: Encountered the symbol ";" when expecting one of the following: if
Try to put it into a variable, the following one should work.
create or replace
TRIGGER CHECK_HABILITATION
BEFORE INSERT ON HABILITATION
FOR EACH ROW
DECLARE
emp employee_TY;
ser service_TY;
BEGIN
select deref(:new.employee) into emp from dual;
if (emp is of (assistant_ty)) then
select deref(:new.service) into ser from dual;
if ser.visit_analysis = 'v' then
raise_application_error('-20001', 'invalid tuple');
end if;
end if;
END;
/
According to the documentation for the IS OF condition, you need to wrap the type in parentheses, like:
IF (:NEW.EMPLOYEE is of (ASSISTANT_TY) )
per https://docs.oracle.com/cd/B28359_01/server.111/b28286/conditions014.htm#SQLRF52157.
I'm not really familiar with using object types so there may be some other issue that I'm not seeing.

Problem with distributed query in procedure to populate data warehouse (Oracle)

I have a problem with a procedure that I will use to populate a table in the data warehouse.
I'll try to exemplify.
I have three types defined as follows:
create or replace type room_t as object(
ID INTEGER,
n_seats INTEGER,
cinema ref cinema_t
) not instantiable not final;
/
create or replace type film_screening_t as object (
screen_date TIMESTAMP,
room ref room_t,
);
/
create or replace type ticket_t as object(
film ref film_screening_t,
purchase_date DATE,
price FLOAT,
n_ticket INTEGER
);
/
And the associated tables:
create table rooms of room_t(
ID primary key
);
/
create table film_screenings of film_screening_t(
room NOT NULL
);
create table tickets of ticket_t(
n_ticket primary key,
film NOT NULL
)
/
I also created a database link in another database that I called:
op_db_link
When I use this database link to get the id of the rooms like in the query below, everything is ok:
select deref(deref(film).room).id from tickets#op_db_link;
but when I use it in a procedure, I obtain only null values. The procedure is:
create or replace
PROCEDURE prova_procedure AS
room_id integer;
cursor c is
select deref(deref(film).room).id from tickets#op_db_link;
BEGIN
open c;
loop
fetch c into room_id;
dbms_output.put_line(user_id);
exit when c%notfound;
end loop;
end;
How can I solve this problem? I need to solve this problem in order to create an ETL procedure to populate the data warehouse

Init REFs in constructor in Oracle database object

I have a problem with initialization of REF values in Oracle. When trying to set them in constructor I get errors, no matter how I try it. Is there any way to init them on construction in situation like that?
CREATE TYPE tSomething AS OBJECT (
Name Varchar(30)
);
CREATE TYPE tSomethingElse AS OBJECT (
Something REF tSomething
);
Ref is unique identifier of existing object. You have to create object table to get this unique identifier.
CREATE TYPE tSomething AS OBJECT (
Name Varchar(30)
);
create table tSomething_table of tSomething;
CREATE TYPE tSomethingElse AS OBJECT (
Something REF tSomething
);
declare
tSomethingElse_obj tSomethingElse;
tSomething_ref REF tSomething;
tSomething_obj tSomething;
begin
-- insert objects into tSomething_table
insert into tSomething_table values('abc');
insert into tSomething_table values('yyy');
-- get ref one object.
select ref(p) into tSomething_ref from tSomething_table p where p.name = 'abc';
-- initialize tSomethingElse_obj;
tSomethingElse_obj := new tSomethingElse(tSomething_ref);
-- extract get real tSomething object from ref
select deref(tSomething_ref) into tSomething_obj from dual;
end;

Create a TYPE in Oracle PL/SQL as "mirror" of existing table

Assume I have a table in my database called
CREATE TABLE EMPLOYEES ( id number, lname varchar2(10))
I know I can create a user defined TYPE as follows
create type t_EMP authid definer as object ( id number, lname varchar2(30))
But is there a way to DYNAMICALLY create type without having to specify all column names ( so that next time the table changes, all I have to do is drop/recreate the TYPE)
You don't need to create type
You can just create variable using your table like this
variable_name table_name%rowtype;
Then you can use it as you want
variable_name.id := 5;
variable_name.lname := 'some name';

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.

Resources