270 likes | 397 Views
Características Objeto Relacionales en Oracle. Francisco Moreno Universidad Nacional. Otro ejemplo con el árbol. Analizar el siguiente ejemplo: Por Niveles. Evolución de tipos. Por medio del comando ALTER TYPE se puede alterar un tipo así: Agregar y quitar atributos
E N D
Características Objeto Relacionales en Oracle Francisco Moreno Universidad Nacional
Otro ejemplo con el árbol Analizar el siguiente ejemplo: Por Niveles
Evolución de tipos Por medio del comando ALTER TYPE se puede alterar un tipo así: • Agregar y quitar atributos • Agregar y quitar métodos • Otras opciones, por ejemplo, cambiar las cláusulas de herencia y de instanciabilidad (ver luego), incrementar el tamaño de atributos numéricos o de caracteres, entre otras.
Agregando y quitando un atributo: DROP TYPE person_typ FORCE; CREATE TYPE person_typ AS OBJECT( nombre VARCHAR(20), apellido VARCHAR(20), edad NUMBER(3)); / DROP TABLE person_tab; CREATE TABLE person_tab OF person_typ; INSERT INTO person_tab VALUES(person_typ('Juan','Smith',1)); INSERT INTO person_tab VALUES('Steve','Jaramillo',90); SELECT * FROM person_tab;
ALTER TYPE person_typ ADD ATTRIBUTE (dob DATE), DROP ATTRIBUTE edad CASCADE INCLUDING TABLE DATA; • INCLUDING TABLE DATA el cambio en los datos se haceimmediatamente • NOT INCLUDING TABLE DATA el cambio se produce cuando los datos son consultados* • INCLUDINGes la opciónpredeterminada *O cuando se realiza, por ejemplo, un ALTER TABLE UPGRADE…
DROP TYPE libro_tip FORCE; CREATE OR REPLACE TYPE libro_tip AS OBJECT( idlib NUMBER(5), titulo VARCHAR2(30), MEMBER FUNCTION imprima_titulo RETURN VARCHAR); / CREATE OR REPLACE TYPE BODY libro_tip AS MEMBER FUNCTION imprima_titulo RETURN VARCHAR IS BEGIN RETURN 'El titulo es: ' || titulo; END; END; /
DROP TABLE libro; CREATE TABLE libro OF libro_tip; INSERT INTO libro VALUES(10, 'Dracula'); SELECT l.imprima_titulo() FROM libro l; Se agrega un atributo: ALTER TYPE libro_tip ADD ATTRIBUTE (autor VARCHAR2(20)) CASCADE; Se quita un método: ALTER TYPE libro_tip DROP MEMBER FUNCTION imprima_titulo RETURN VARCHAR CASCADE;
Se agrega un método: ALTER TYPE libro_tip ADD MEMBER FUNCTION imp_tit_y_aut RETURN VARCHAR CASCADE; Ahora hay que cambiar el BODY: CREATE OR REPLACE TYPE BODY libro_tip AS MEMBER FUNCTION imp_tit_y_aut RETURN VARCHAR IS BEGIN RETURN 'El titulo es: ' || titulo || ' y el autor es: ' || NVL(autor,'Anónimo'); END; END; /
Se comprueba invocando el nuevo método: SELECT l.imp_tit_y_aut() FROM libro l; El autor está en nulo y por lo tanto sale anónimo… UPDATE libro SET autor = 'BramStoker' WHERE idlib = 10;
Un ejemplo con constructor de usuario CREATE OR REPLACE TYPE animal_type AS OBJECT( nombre VARCHAR2(20), especie VARCHAR2(20), CONSTRUCTOR FUNCTION animal_type (nom VARCHAR2) RETURN SELF AS RESULT ); / Notas: 1. El nombre del constructor debe ser el mismo del tipo. 2. Se pueden tener también varios constructores (sobrecarga).
CREATE OR REPLACE TYPE BODY animal_type AS CONSTRUCTOR FUNCTION animal_type(nom VARCHAR2) RETURN SELF AS RESULT IS BEGIN SELF.nombre := nom; SELF.especie := 'Desconocida'; RETURN; END; END; / DECLARE a1 animal_type := animal_type('León','Panthera Leo'); a2 animal_type := animal_type('Gato'); BEGIN DBMS_OUTPUT.PUT_LINE(a1.nombre || ' ' || a1.especie); DBMS_OUTPUT.PUT_LINE(a2.nombre || ' ' || a2.especie); END; /
Instancias como valor de retorno de una función • Los valores de retorno al igual que los parámetros de un método pueden a su vez ser instancias de tipos. • Veamos el primer caso.
CREATE OR REPLACE TYPE par_type AS OBJECT( x NUMBER, y NUMBER); / CREATE OR REPLACE TYPE num_type AS OBJECT( valor NUMBER, MEMBER FUNCTION devuelve_par RETURNpar_type); / CREATE OR REPLACE TYPE BODY num_type AS MEMBER FUNCTION devuelve_parRETURN par_type IS BEGIN RETURN par_type(valor+valor, valor*valor); END; END; /
CREATE TABLE num OF num_type; INSERT INTO num VALUES (10); INSERT INTO num VALUES (20); SELECT o.devuelve_par() FROM num o; SELECT o.devuelve_par().x FROM num o; devuelve_par es una función del tipo num_type y devuelve un par_type
Sobrecarga de métodos e instancias como parámetros • Ahora se verá como enviar una instancia de un tipo como un parámetro. • En este mismo ejemplo también se verá la sobrecarga de métodos. • Supóngase una librería universitaria con las siguientes condiciones:
El precio final de un libro será su precio base menos un descuento que se aplica así. Si el comprador es • Un estudiante: el descuento será el 15% sobre el valor de la matrícula si el estudiante es monitor o 10% de lo contrario. • Un particular: el descuento será el 2% sobre el valor del precio base del libro. Los atributos de un unestudiante son: carné, nombre, valor_mat, monitor_sn
DROP TYPEestudiante_type FORCE; CREATE OR REPLACE TYPE estudiante_type AS OBJECT( carne NUMBER(10), nombre VARCHAR(10), valor_mat NUMBER(7), monitor_sn CHAR(1) ); / DROP TABLE estudiante; CREATE TABLE estudiante OF estudiante_type (carne PRIMARY KEY); INSERT INTO estudiante VALUES(345,'Petra',1000,'s'); INSERT INTO estudiante VALUES(100,'Dino',2000,'n');
El tipo libro: DROP TYPE libro_tip FORCE; CREATE OR REPLACE TYPE libro_tip AS OBJECT( --Atributos: titulo VARCHAR2(30), precio_base NUMBER(6), --Métodos: MEMBER FUNCTION precio_finalRETURN NUMBER, MEMBER FUNCTION precio_final(car NUMBER) RETURN NUMBER); / Métodos sobrecargados Recibe como parámetro el carné del estudiante
CREATE OR REPLACE TYPE BODY libro_tip AS MEMBER FUNCTION precio_finalRETURN NUMBER IS BEGIN RETURN precio_base- 2 * precio_base/100; END; MEMBER FUNCTION precio_final(carNUMBER) RETURN NUMBER IS descuento NUMBER(8); BEGIN SELECT CASE WHEN monitor_sn = 's' THEN valor_mat*15/100 ELSE valor_mat*10/100 END CASE INTO descuento FROM estudiante WHERE carne = car; RETURN precio_base - descuento; END precio_final; END; /
DROP TABLE libro; CREATE TABLE libro OF libro_tip (titulo PRIMARY KEY); INSERT INTO libro VALUES('Dracula',10000); INSERT INTO libro VALUES('Lips Unsealed',15000); INSERT INTO libro VALUES('Take it like a Man',5000); INSERT INTO libro VALUES('The Sign of Four', 5000);
SELECT l.precio_final(345) FROM libro l; SELECT l.precio_final() FROM libro l;
Nótese que el método precio_finalquedadependiente de la tablaestudiante. Otraopciónesenviarleel objeto comoparámetro: DROP TYPE libro_tip FORCE; CREATE OR REPLACE TYPE libro_tip AS OBJECT( --Atributos: titulo VARCHAR2(30), precio_base NUMBER(6), --Métodos: MEMBER FUNCTION precio_finalRETURN NUMBER, MEMBER FUNCTION precio_final(e estudiante_type)RETURN NUMBER); /
CREATE OR REPLACE TYPE BODY libro_tip AS MEMBER FUNCTION precio_finalRETURN NUMBER IS BEGIN RETURN precio_base- 2*precio_base/100; END; MEMBER FUNCTION precio_final(e estudiante_type) RETURN NUMBER IS descuento NUMBER(8); BEGIN IF e.monitor_sn = 's' THEN descuento := 15; ELSE descuento := 10; END IF; RETURN precio_base - (e.valor_mat) * descuento/100; END precio_final; END; /
Crear la tabla…Ahora, ¿cómo invocar el método? SELECT l.precio_final( (SELECT * FROM estudiante WHERE carne = 345)) FROM libro l WHERE titulo = 'Dracula'; No funciona, tampoco: SELECT l.precio_final( (SELECT carne, nombre, valor_mat, monitor_sn FROM estudiante WHERE carne = 345)) FROM libro l WHERE titulo = 'Dracula';
Diferencia entre *y VALUE(): • SELECT * FROM estudiante; CARNE NOMBRE VALOR_MAT MONITOR_SN ---------- ---------- ----------------- -------------------- 345 Petra 10 s 100 Dino 200 s • SELECT VALUE(e) FROM estudiante e; VALUE(E)(CARNE, NOMBRE, VALOR_MAT, MONITOR_SN) ----------------------------------------------------------------------------------- ESTUDIANTE_TYPE(345, 'Petra', 10, 's') ESTUDIANTE_TYPE(100, 'Dino', 200, 's')
Por lo tanto, la solución es: SELECT l.precio_final((SELECT VALUE(e) FROM estudiante e WHERE carne = 345)) AS total FROM libro l WHERE titulo = 'Dracula'; Ojo:La consulta que provee el parámetro debe devolver un único valor. Aunquetambién se puedeconstruir el objetoasí: SELECT l.precio_final( (SELECT estudiante_type(carne, nombre, valor_mat, monitor_sn) FROM estudiante WHERE carne = 345)) AS total FROM libro l WHERE titulo = 'Dracula'; Peroesmás simple el uso de VALUE…
¿Qué hace la siguiente consulta?: SELECT carne, SUM(l.precio_final(VALUE(e))) AS tot FROM libro l, estudiante e GROUP BY carne;