I am trying to implement type inheritance in oracle 10g
Hereis my code:
create type stud_detail as object
(stud_id number(5),
stud_name varchar(8));
/
create type stud_result under stud_detail as
(status(P/F)? char(1));
/
I get this error:
ERROR at line 1: PLS-00103: Encountered the symbol "AS" when expecting
one of the following:
. ( not external JAVA_ BOUND_
1. create type stud_result under stud_detail as object
2. (status(P/F)? char(1));
There are two things you need to do:
Declare your stud_detail type as NOT FINAL. You can only inherit from a type that is NOT FINAL, and types are FINAL by default.
Lose the AS keyword in your create type stud_result under stud_detail... line.
Demonstration:
SQL> create type stud_detail as object (stud_id number(5), stud_name varchar2(8)) not final;
2 /
Type created.
SQL> create type stud_result under stud_detail ("status(P/F)?" char(1));
2 /
Type created.
SQL> desc stud_result;
stud_result extends LUKE.STUD_DETAIL
Name Null? Type
----------------------------------------- -------- ----------------------------
STUD_ID NUMBER(5)
STUD_NAME VARCHAR2(8)
status(P/F)? CHAR(1)
Note that I've changed varchar to varchar2, and put quotes around the name of the column status(P/F)?.
Related
I want to create a type with an attribute which should be expect three possible values. Something like following statement:
CREATE TYPE my_type AS OBJECT(
attrib1 VARCHAR2(30),
attrib2 VARCHAR2(30),
attrib3 VARCHAR2(30) -- this attribute should accept three possible values: val1, val2, or val3
);
Is there any way to do this, just like in the case of tables?
Thank you in advance.
You may use custom type constructor and perform this check inside PL/SQL code.
create type my_type as object(
attrib1 varchar2(30),
attrib2 varchar2(30),
attrib3 varchar2(30),
constructor function my_type (
attrib1 in varchar2,
attrib2 in varchar2,
attrib3 in varchar2
) return self as result
);
/
create type body my_type as
constructor function my_type (
attrib1 in varchar2,
attrib2 in varchar2,
attrib3 in varchar2
) return self as result
as
invalid_attr_value exception;
pragma exception_init(invalid_attr_value, -20001);
begin
if attrib3 not in ('val1', 'val2', 'val3') then
raise_application_error(-20001, 'Invalid attrib3 value supplied');
end if;
self.attrib1 := attrib1;
self.attrib2 := attrib2;
self.attrib3 := attrib3;
return;
end;
end;/
with a(col) as (
select my_type('a', 'b', 'val1')
from dual
)
select
a.col.attrib1,
a.col.attrib2,
a.col.attrib3
from a a
COL.ATTRIB1
COL.ATTRIB2
COL.ATTRIB3
a
b
val1
with a(col) as (
select my_type('a', 'b', 'val10')
from dual
)
select
a.col.attrib1,
a.col.attrib2,
a.col.attrib3
from a a
ORA-20001: Invalid attrib3 value supplied
ORA-06512: at "FIDDLE_INSFSVTZEJFLABZQAKDJ.MY_TYPE", line 12
fiddle
This is what you'd be happy with, but - unfortunately - it won't work:
SQL> create or replace type my_type as object
2 (attrib1 varchar2(30),
3 attrib2 varchar2(30),
4 attrib3 varchar2(30) check(attrib3 in ('A', 'B'))
5 );
6 /
create or replace type my_type as object
*
ERROR at line 1:
ORA-06545: PL/SQL: compilation error - compilation aborted
ORA-06550: line 4, column 23:
PLS-00103: Encountered the symbol "CHECK" when expecting one of the following:
:= ) , not null default external character
The symbol ":= was inserted before "CHECK" to continue.
ORA-06550: line 0, column 0:
PLS-00565: MY_TYPE must be completed as a potential REF target (object type)
Therefore, create the type as is ...
SQL> create or replace type my_type as object
2 (attrib1 varchar2(30),
3 attrib2 varchar2(30),
4 attrib3 varchar2(30)
5 );
6 /
Type created.
... and then apply check constraint on attrib3 while using that type in create table statement, e.g.
SQL> create table test of my_type
2 (attrib1 primary key,
3 attrib2 not null,
4 attrib3 default 'A' check (attrib3 in ('A', 'B'))
5 );
Table created.
SQL>
Is there any way to do this, just like in the case of tables?
No, you cannot apply a CHECK constraint to an OBJECT data-type.
From the CONSTRAINT documentation:
Constraint clauses can appear in the following statements:
CREATE TABLE (see CREATE TABLE)
ALTER TABLE (see ALTER TABLE)
CREATE VIEW (see CREATE VIEW)
ALTER VIEW (see ALTER VIEW)
So you cannot create a constraint in a CREATE TYPE or an ALTER TYPE statement.
Type definition:
CREATE TYPE INTERVENTO_TY AS OBJECT(
Testo VARCHAR2(20),
Timestmp DATE
) NOT FINAL;
CREATE TYPE COMMENTO_TY UNDER INTERVENTO_TY(
Ordine VARCHAR2(20)
);
CREATE TYPE POST_TY UNDER INTERVENTO_TY(
Titolo VARCHAR2(20),
MEMBER PROCEDURE AddCom(Ordine VARCHAR2, Testo VARCHAR2, Timestmp Date)
);
CREATE TYPE AUTORE_TY AS OBJECT(
Nome VARCHAR2(20),
Cognome VARCHAR2(20),
IdAutore INT
);
CREATE TYPE MEDIA_TY AS OBJECT(
Tipo VARCHAR2(20),
Nome VARCHAR2(20),
IdMedia INT,
Titolo VARCHAR2(20)
);
CREATE TYPE SCRIVE_INTERVENTO AS TABLE OF REF INTERVENTO_TY;
CREATE TYPE DI_AUTORE AS TABLE OF REF AUTORE_TY;
ALTER TYPE INTERVENTO_TY ADD ATTRIBUTE DI DI_AUTORE CASCADE;
ALTER TYPE AUTORE_TY ADD ATTRIBUTE SCRIVE SCRIVE_INTERVENTO CASCADE;
CREATE TYPE IN_INTERVENTO AS TABLE OF REF INTERVENTO_TY;
CREATE TYPE CONTIENE_MEDIA AS TABLE OF REF MEDIA_TY;
ALTER TYPE INTERVENTO_TY ADD ATTRIBUTE CONTIENE CONTIENE_MEDIA CASCADE;
ALTER TYPE MEDIA_TY ADD ATTRIBUTE IN_INT IN_INTERVENTO CASCADE;
CREATE TYPE COMMENTATO_POST AS TABLE OF REF COMMENTO_TY;
ALTER TYPE COMMENTO_TY ADD ATTRIBUTE A REF POST_TY CASCADE;
ALTER TYPE POST_TY ADD ATTRIBUTE COMMENTATO COMMENTATO_POST CASCADE;
CREATE TABLE AUTORE_TAB OF AUTORE_TY
NESTED TABLE SCRIVE STORE AS SCRIVE_NESTED;
CREATE TABLE INTERVENTO_TAB OF INTERVENTO_TY
NESTED TABLE DI STORE AS DI_NESTED
NESTED TABLE CONTIENE STORE AS CONTIENE_NESTED;
CREATE TABLE MEDIA_TAB OF MEDIA_TY
NESTED TABLE IN_INT STORE AS IN_INT_NESTED;
I'm trying to write an object procedure that creates a new instance of COMMENTO_TY, adds it to the COMMENTO_TAB table and the COMMENTATO nested table of POST_TY, but it gives me the following error:
CREATE OR REPLACE TYPE BODY Post_ty AS
MEMBER PROCEDURE addComm(commento VARCHAR2, ordine NUMBER, IdAut INTEGER) AS
NuovoCommento REF Commento_ty;
BEGIN
INSERT INTO Intervento_tab I
VALUES(Commento_ty(commento, SYSTIMESTAMP,
DI_AUTORE(
(SELECT REF(A) FROM AUTORE_TAB A WHERE IdAutore = IdAut)
),
CONTIENE_MEDIA(),
ordine,
(SELECT TREAT(REF(I) AS REF POST_TY)
FROM INTERVENTO_TAB I
WHERE VALUE(I) IS OF (POST_TY) AND
I.TIMESTMP = SELF.TIMESTMP)))
RETURNING REF(I) INTO NuovoCommento;
INSERT INTO TABLE(SELECT TREAT(VALUE(I) AS POST_TY).COMMENTATO
FROM INTERVENTO_TAB I
WHERE VALUE(I) IS OF (POST_TY)
AND I.TIMESTMP = SELF.TIMESTMP)
VALUES(NuovoCommento);
END addComm;
END;
/
PLS-00538: subprogram or cursor 'ADDCOM' is declared in an object type specification and must be defined in the object type body at line 3
PLS-00539: subprogram 'ADDCOMM' is declared in an object type body and must be defined in the object type specification at line 2
You have two errors:
PLS-00538: subprogram or cursor 'ADDCOM' is declared in an object type specification and must be defined in the object type body
and
PLS-00539: subprogram 'ADDCOMM' is declared in an object type body and must be defined in the object type specification
Notice how one is spelt ADDCOM and the other is ADDCOMM; you need to make sure the member procedure has the same name in the specification and the body.
I am trying to create a basic table using subtypes and insert some data into this in Oracle Express 11g.
My table is successfully created but i am having issues with inserting data.
The result of my insert statement always throws back an error 'SQL Error: ORA-00904: "BRANCH_PHONE": invalid identifier'.
The column which shows up in the error message is always the column which is at the end of the insert statement, despite the column existing in the table. I have tried the following code:
create type addressType as object(
street varchar2(20),
city varchar2(20),
postCode varchar2(8))
not final
/
create type branchType as object(
branchID int,
branch_address addressType,
branch_phone int(11))
not final
/
create table Branch of branchType(
constraint branch_pk primary key(branchID));
/
insert into Branch values (
branchID('2364'),
addressType('12 Rooster','Atlantis','A13 4UG'),
branch_phone('01316521311'));
I would really appreciate any ideas.
I made some changes, including changing the branch_phone to varchar2. A Phone number, while is "numbers" is not a data type of number. it is a string of characters. Also you were passing branchID as a string, but you are declaring it as a number, so changed that also. BranchID and branch_phone are primitive data types, so no constructor needed.
create type addressType as object(
street varchar2(20),
city varchar2(20),
postCode varchar2(8))
not final
/
create type branchType as object(
branchID int,
branch_address addressType,
branch_phone varchar2(11))
not final
/
create table Branch of branchType(
constraint branch_pk primary key(branchID));
/
insert into Branch values (
branchtype(2364,
addressType('12 Rooster','Atlantis','A13 4UG'),
'01316521311') )
I'm designing an object-relational model database. I have a supertype named "topico_t" and 4 subtypes of this supertype named "anotacao_t", "tarefa_t", "memo_t" and "contacto_t". See here the DDL snippet:
CREATE OR REPLACE TYPE categoria_t AS OBJECT(
nome VARCHAR2(25),
pai REF categoria_t
);
CREATE OR REPLACE TYPE categoria_tab_t AS TABLE OF REF categoria_t;
CREATE OR REPLACE TYPE topico_t AS OBJECT(
titulo VARCHAR2(100),
ultimaAlteracao DATE,
categorias categoria_tab_t
--referencias topico_tab_t
) NOT FINAL;
CREATE OR REPLACE TYPE topico_tab_t AS TABLE OF REF topico_t;
ALTER TYPE topico_t ADD ATTRIBUTE referencias topico_tab_t CASCADE;
CREATE OR REPLACE TYPE periodo_t AS OBJECT(
inicio DATE,
fim DATE
);
CREATE OR REPLACE TYPE repeticao_t AS OBJECT(
frequencia VARCHAR2(10),
duracao periodo_t
);
CREATE OR REPLACE TYPE anotacao_t UNDER topico_t(
periodo periodo_t,
repeticao repeticao_t
);
CREATE OR REPLACE TYPE telefone_t AS OBJECT(
numero VARCHAR2(25)
);
CREATE OR REPLACE TYPE telefone_tab_t AS TABLE OF telefone_t;
CREATE OR REPLACE TYPE morada_t AS OBJECT(
rua VARCHAR2(100),
localidade VARCHAR2(50),
codigoPostal VARCHAR2(10)
);
CREATE OR REPLACE TYPE morada_tab_t AS TABLE OF morada_t;
CREATE OR REPLACE TYPE contacto_t UNDER topico_t(
telefones telefone_tab_t,
moradas morada_tab_t,
email VARCHAR2(100),
url VARCHAR2(150)
);
CREATE OR REPLACE TYPE tarefa_t UNDER topico_t(
dataFim DATE,
completo NUMBER(1,0),
conteudo VARCHAR2(255)
);
CREATE OR REPLACE TYPE memo_t UNDER topico_t(
conteudo VARCHAR2(255)
);
CREATE TABLE categorias OF categoria_t;
CREATE TABLE topicos OF topico_t
NESTED TABLE categorias STORE AS categorias_nested
NESTED TABLE referencias STORE AS referencias_nested;
So, then I populate this table "topicos" with this:
INSERT INTO topicos VALUES (tarefa_t(
'Dissertacao',
TO_DATE('2018/02/13', 'YYYY/MM/DD'),
categoria_tab_t((select ref(c) from categorias c where nome='FEUP')),
topico_tab_t((select ref(t) from topicos t where titulo='Diogo Pereira'), -- which is an object of the subtype "contacto_t"
(select ref(t) from topicos t where titulo='Comecar a dissertacao'), -- which is an object of the subtype "memo_t"
(select ref(t) from topicos t where titulo='Apresentar Dissertacao'), -- which is an object of the subtype "tarefa_t"
(select ref(t) from topicos t where titulo='Reuniao com Orientador da Dissertacao')), -- which is an object of the subtype "anotacao_t"
TO_DATE('2018/08/13', 'YYYY/MM/DD'),
0,
'Dissertacao all over again'));
So, I have to build a query or even a PL/SQL block that returns me all the rows of the table "topicos" that contains at least, in the nested table "referencias", one instance object for each of this 4 subtypes mentioned above. Ideally this query would return me that row (mentioned in the above INSERT).
Best regards and hope you're having a good Worker's Day! ;)
You have a mistake in your DDL code. You are creating a base type topico_t and then some subtypes under that type, but you're creating a single table of base type objects only. The problem with this is that you're expecting that table to hold objects of any subtype, which will not be the case due to what is known as object slicing. The table you've created has only the columns which correspond to the fields you've defined for the base type.
Therefore, you need to create tables for all of the subtypes which you will eventually instantiate. You should only create a table for the base type if it makes sense for that type to be instantiated, that is, if an object of the base type which doesn't belong to any of the subtypes could exist.
After doing this, the query you're trying to write should use the function TREAT. Note that, according to the documentation, this function returns NULL when the expression is not of the type you're trying to cast to, so the query you need to write should be as simple as testing if there is at least one row with a non-null result field when selecting from the nested table and attempting to cast to each of the subtypes you've created. Check the example on the documentation to see how to use this function.
I have the error- the declaration of ... is incomplete or malformed coming from the last type- "Subscriber_T" but I don't see a problem with the syntax. These are the scripts:
CREATE OR REPLACE TYPE Surnames_T AS OBJECT (
Surname varchar (20)
);
/
CREATE OR REPLACE TYPE listSurnames_T
AS Varray(4) of Surnames_T;
/
CREATE OR REPLACE TYPE listTels as object(
Tel number (12)
);
/
CREATE OR REPLACE TYPE listTels_T as Varray(5) of listTels;
/
CREATE OR REPLACE TYPE ADDRESS_T AS OBJECT (
NUM number (6),
STREET varchar (20),
TOWN varchar (20)
);
/
CREATE or replace type TAddress
as table of Address_T;
/
create or replace type Subscriber_T as object(
num_s number(6),
sName varchar(30),
surname listSurnames_T,
Adds TAddress,
DateOfBirth date,
member function cal_Age return number,
phoneNo listTels_T
);
/
show error
I need a fix please!
You have to put member functions after all other fields; you can't sneak a field in at the end:
create or replace type Subscriber_T as object(
num_s number(6),
sName varchar(30),
surname listSurnames_T,
Adds TAddress,
DateOfBirth date,
phoneNo listTels_T,
member function cal_Age return number
);
/
TYPE SUBSCRIBER_T compiled
Obligatory SQL Fiddle.
This is shown in the syntax diagram in the documentation; you can have one or more attributes, and then one or more elements (including functions), but you can't mix them around. Notice which bits have loops, and where they loop back to.