How cast few atributes from relational table into varray on creating view - sql

I need to create VIEW with VARRAY casted from 3 atributes in relational table.
I tried many ways, but I didn't get a positive result.
Also can't find a solution in the oracle documentation.
CREATE TABLE Client (
ID_Client NUMBER(7,0),
Phone1 VARCHAR2(9),
Phone2 VARCHAR2(9),
Phone3 VARCHAR2(9),
CONSTRAINT Client_PK
PRIMARY KEY (ID_Client)
);
/
CREATE TYPE phone_vartyp IS VARRAY(3) OF VARCHAR2(9);
/
CREATE TYPE client_objtyp AS OBJECT (
ID_Client NUMBER(7,0),
Phones phone_vartyp
);
/
CREATE VIEW client_objv OF client_objtyp
WITH OBJECT IDENTIFIER (ID_Client)
AS SELECT c.ID_Client,
CAST(MULTISET(SELECT c.Phone1, c.Phone2, c.Phone3
FROM Client c) AS phone_vartyp)
FROM Client c; -- ORA-00932
/
CREATE VIEW client_objv OF client_objtyp
WITH OBJECT IDENTIFIER (ID_Client)
AS SELECT c.ID_Client,
(SELECT CAST(c.Phone1, c.Phone2, c.Phone3) AS phone_vartyp FROM Client c) as phone_vartyp
FROM Client c; -- ORA-00905
/
DROP TABLE Client;
DROP TYPE client_objtyp;
DROP TYPE phone_vartyp;

It seems you're overthinking this one. There's no need to use CAST or MULTISET or a subquery. The easiest way to create a VARRAY from a number of values is just to use the type as if it were a function and pass all of the elements as arguments.
The following appears to work:
CREATE OR REPLACE VIEW client_objv OF client_objtyp
WITH OBJECT IDENTIFIER (ID_Client)
AS SELECT c.ID_Client,
phone_vartyp(c.Phone1, c.Phone2, c.Phone3)
FROM Client c;

Related

Oracle OR - how to guarantee that a nested table has references to all the subtypes of a supertype

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.

Oracle - How to get a number from an object in a sql query?

I have this object:
CREATE TYPE CarType AS OBJECT(
price_id NUMBER,
quantity NUMBER.
MAP MEMBER FUNCTION get_price_id RETURN NUMBER
);
and this table:
CREATE TABLE Cars(
carid NUMBER PRIMARY KEY,
carinfo cartype,
CONSTRAINT car_fk FOREIGN KEY(carinfo.price_id) REFERENCES prices(price_id)
);
and I want to get the carid,price_id from Cars table with a sql query.
You must remember about aliasing your table and accessing columns with object type using alias, otherwise you will get ORA-00904 invalid identifier error.
This query will work:
SELECT C.CARID, C.CARINFO.PRICE_ID, C.CARINFO.QUANTITY FROM CARS C;
But this will not:
SELECT CARS.CARID, CARS.CARINFO.PRICE_ID, CARS.CARINFO.QUANTITY FROM CARS;

Create a table of two types in PostgreSQL

I have created two types:
Create Type info_typ_1 AS (
Prod_id integer,
category integer);
Create Type movie_typ AS(
title varchar(50),
actor varchar(50),
price float);
And I want to create a table that consists of these two types. I know that for a table that consists of one type, it's:
CREATE TABLE Table1 of type1
(
primary key(prod_id)
);
Is there any way to do that for the two types I created above?
What I tried doing(which is wrong), is creating a third type that contains the first two:
Create Type info_ AS (
info info_typ_1,
movie movie_typ);
and then creating the table:
CREATE TABLE table1 of info_
(
primary key(Prod_id)
);
But it doesn't work. I get this error:
ERROR: column "prod_id" named in key does not exist
LINE 3: primary key(Prod_id)
^
********** Error **********
ERROR: column "prod_id" named in key does not exist
SQL state: 42703
Character: 43
You cannot make prod_id the primary key of table1 because the only columns are the two composite types info and movie. You cannot access the base types of these composite types in a PRIMARY KEY clause.
What you were trying to do works with a pk constraint on info or movie.
Except, it's probably not what you were looking for, which is not possible this way.
You could implement something like this with ...
Inheritance
Here you can inherit from multiple parent tables (substitute for your types). Example:
CREATE TABLE info (
prod_id integer
,category integer
);
CREATE TABLE movie (
title text
,actor text
,price float
);
CREATE TABLE movie_info (
PRIMARY KEY(prod_id) -- now we can use the base column!
)
INHERITS (info, movie);
INSERT INTO movie_info (prod_id, category, title, actor, price)
VALUES (1, 2, 'who donnit?', 'James Dean', '15.90');
SELECT * FROM movie_info;
-> SQLfiddle demonstrating both.
Be sure to read about limitations of inheritance in the manual.

error: ORA-01730: invalid number of column names specified

Please help. I want to create an object view from the ffl tables but i keep getting the above error and can't find any solution.
create table COPY_BOOK (
NUM number(4,0),
DATE_Purchase date,
PRICE number(5,2),
LOAN_code varchar2(20) ,
STATUS varchar2(15) check (STATUS in ('GOOD','DAMAGED')),
CONSTRAINT CP_PK primary key (num) ,
constraint Loan_code_D check (LOAN_CODE in ('NO', 'LOAN'))
);
create or replace type copy_book_t as object(
num number(4, 0),
loan_code varchar2 (20)
);
/
create or replace view Vcopy_book of copy_book_t
with object oid (num)
as select cb.num, cb.date_purchase, cb.price, cb.loan_code, cb.status
from copy_book cb;
/
Is there a problem with the type definition?
From the documentation:
The procedure for defining an object view is:
Define an object type, where each attribute of the type corresponds to an existing column in a relational table.
Write a query that specifies how to extract the data from the relational table. Specify the columns in the same order as the
attributes in the object type.
You have created your object type with two attributes, but you're trying to populate it with five columns from your relational table.
You either need to change your object type to have the same five attributes (demo), or only select the num and loan_code columns in the view (demo).
Incidentally, the documentation also recommends using with object identifier rather than with object oid.

oracle11g sql: Warning: Type created with compilation errors

I'm trying to create a supertype customer service and subtype agent and supervisor, so they can inherent values however when I try to run this in oracle sql: a message comes up
Warning: Type created with compilation errors.
What is wrong with the code below?
Create or replace type customer_s_type as object (
csID number,
csName varchar(15),
csType number ) NOT FINAL;
Create or replace type supervisor_type UNDER customer_s_type ( title varchar (10) );
Create or replace type agent_type UNDER customer_s_type (title varchar (10));
Create table supervisor of supervisor_type (
CONSTRAINT supervisor_PK PRIMARY KEY (csID));
Create table agent of agent_type (CONSTRAINT agent_PK PRIMARY KEY (csID));
create table customer_service(
csID number(10),
csType number(10),
constraint supervisor_pk primary key(csID) );
You can use show errors in SQL*Plus or SQL Developer, or select * from user_errors, to see the error details.
Since you've shown six commands and the warning is about one of the first three (since it refers to type), and they appear OK independently apart from the constraint pointed put in comments, it looks like the whole script is being imterpreted as one command. It depends on your client settings, but you probably just need to seperate the commands with a / to cause them to execute. Becuase types can include PL/SQL the ; isn't treated as a statement seperator. So:
Create or replace type customer_s_type as object (
csID number,
csName varchar(15),
csType number ) NOT FINAL;
/
Create or replace type supervisor_type UNDER customer_s_type ( title varchar (10) );
/
Create or replace type agent_type UNDER customer_s_type (title varchar (10));
/
Create table supervisor of supervisor_type (
CONSTRAINT supervisor_PK PRIMARY KEY (csID));
Create table agent of agent_type (CONSTRAINT agent_PK PRIMARY KEY (csID));
create table customer_service(
csID number(10),
csType number(10),
constraint customer_service_pk primary key(csID) );