Características Características Objeto Relacionales Objeto Relacionales en Oracleen Oracle
Francisco Moreno
Universidad Nacional
Métodos Estáticos
Un método estático no referencia a los atributos del tipo
Su comportamiento está determinado por sus parámetros o por otros elementos (distintos a los atributos del tipo)
La invocación de un método estático se hace con el tipotipo NO con una instancia de dicho tipoinstancia de dicho tipo
CREATE OR REPLACE TYPE matem_tip AS OBJECT( cod VARCHAR(8), STATICSTATIC FUNCTION factorial(n IN NUMBER) RETURN NUMBER);/
CREATE OR REPLACE TYPE BODY matem_tip ASSTATICSTATIC FUNCTION
factorial(n IN NUMBER) RETURN NUMBER IS
BEGIN IF n = 0 THEN RETURN
1; ELSE RETURN n * factorial(n-1); END IF; END factorial;END; /
Métodos Estáticos
Desde una consulta. Sea la tabla:CREATE TABLE aux(a NUMBER); INSERT INTO aux VALUES (8); INSERT INTO aux VALUES (7);
SELECT matem_tip.factorial(a)FROM aux;
Desde PL/SQL:BEGIN
DBMS_OUTPUT.PUT_LINE(matem_tip.factorial(5));END;/
Invocación
Nótese que es eltipo y no una instancia la que invoca al método estático
Métodos MAP y ORDER ¿Qué pasa si se comparan dos columnas
tipadas (objetosobjetos) con un operador como >?
Ej: empleado1 > empleado2 Este problema también se presenta en
consultas que involucran objetosobjetos en una cláusula:
ORDER BY objetoobjeto, GROUP BY objetoobjeto,
DISTINCT objetoobjeto Para solucionar este problema se debe crear un
método MAP u ORDER
Métodos MAP y ORDER Un tipo solo puede tener asociado uno de
estos métodos Son métodos miembros, no estáticos MAP suele tener mejor desempeño
(tiempo de ejecución) que ORDER pero puede ser menos flexible ¿En qué sentido?
Métodos MAP y ORDER No soportan parámetros adicionales a los
preestablecidos No se pueden sobrecargar
Son invocados implícitamente por las operaciones que los requieren (ORDER, GROUP BY,DISTINCT, >, etc.)
Se pueden invocar explícitamente Pueden generar confusión en una cláusula
DISTINCT ya que “desaparecen” objetos que aparentemente son distintos Ver ejemplos
Método MAP No tiene parámetros Es una función que debedebe retornar un
valor correspondiente a un tipotipo primitivoprimitivo del sistema (no puede retornar objetos creados por el usuario)
EjemploDROP TYPE emp_type FORCE;CREATE OR REPLACE TYPE emp_type AS
OBJECT( cedula VARCHAR2(10), nombre VARCHAR2(10), edad NUMBER(2), salario NUMBER (6), MAPMAP MEMBER FUNCTION
ord_por_salario RETURN NUMBER);/
Tipo primitivo
Implementación
CREATE OR REPLACE TYPE BODY emp_type AS
MAPMAP MEMBER FUNCTION ord_por_salario
RETURN NUMBER IS BEGIN RETURN SELF.salario; END ord_por_salario;END;/
DROP TABLE emp;CREATE TABLE emp OF emp_type (cedula PRIMARY KEY, salario NOT NULL);
INSERT INTO emp VALUES('111', 'Bobaldo', 20, 100);INSERT INTO emp VALUES('121', 'Dumbo', 30, 200);INSERT INTO emp VALUES('131', 'Lisa', 25, 80);INSERT INTO emp VALUES('141', 'Mary', 21, 100);INSERT INTO emp VALUES('151', 'Paddy', 21, 100);INSERT INTO emp VALUES('171', 'Edneud', 18, 50);
Ahora ya es posible:
SELECT *FROM emp eORDER BY VALUE(e)VALUE(e);
CEDULA NOMBRE EDAD SALARIO---------- ---------- ---------- ---------- 171 Edneud 18 50131 Lisa 25 80111 Bobaldo 20 100141 Mary 21 100151 Paddy 21 100121 Dumbo 30 200
Si hay empates en el valor retornado por la función MAP, el orden entre los empatados es aleatorio
Empate (100)
Considérese la siguiente consulta:
SELECT DISTINCT VALUE(e)FROM emp e;
Resultado:VALUE(E)(CEDULA, NOMBRE, EDAD, SALARIO, COMISION)------------------------------------------------------------------------------------EMP_TYPE('171', 'Edneud', 18, 50)EMP_TYPE('131', 'Lisa', 25, 80)EMP_TYPE('111', 'Bobaldo', 20, 100)EMP_TYPE('121', 'Dumbo', 30, 200)
¿Qué pasó con Mary y con Paddy? Desaparición
Ver otro ejemplo con un doc XML en el menú Varios
Método ORDER Retorna un número (usualmente -1, 0, o 1) Recibe como parámetro un objeto del mismo tipo
al cual se le está creando la función ORDER En el método ORDER se comparan dos objetos
(SELF y el que llega como parámetro) y se establece si el objeto SELF es <, = o > al objeto parámetro (y se retorna un número negativo, cero o un número positivo, respectivamente)
Cada objeto invocador SELF se compara sucesivamente con todos los objetos que llegan como parámetro
EjemploDROP TYPE emp_type FORCE;CREATE OR REPLACE TYPE emp_type AS
OBJECT( cedula VARCHAR2(10), nombre VARCHAR2(10), edad NUMBER(2), salario NUMBER (6),ORDER ORDER MEMBER FUNCTION
ord_por_salario(a IN emp_type) RETURN NUMBER);/
CREATE OR REPLACE TYPE BODY emp_type AS
ORDER ORDER MEMBER FUNCTION ord_por_salario(a IN emp_type)
RETURN NUMBER IS
BEGIN RETURN (SELF.salario - a.salario); END ord_por_salario;END;/
Crear la tabla emp, insertarle datos y ensayar las dos consultas…
Esta operación devolverá un
número negativo, positivo o el cero
El objeto invocador
SELECT VALUE(e), COUNT(*) AS cuantosFROM emp eGROUP BY VALUE(e);
VALUE(e)(CEDULA, NOMBRE, EDAD, SALARIO) CUANTOS
--------------------------------------- -------EMP_TYPE('171', 'Edneud', 18, 50) 1EMP_TYPE('131', 'Lisa', 25, 80) 1EMP_TYPE('111', 'Bobaldo', 20, 100) 3EMP_TYPE('121', 'Dumbo', 30, 200) 1
Vistas objeto
Considere el siguiente modelo E-R
FACTURA#código*fecha
DETALLE#pdto*cant
compuesta de
de
Implementación relacional:
CREATE TABLE factura(codigo NUMBER(8) PRIMARY KEY,fecha DATE NOT NULL);
CREATE TABLE detalle(pdto VARCHAR2(20),codfac NUMBER(8) REFERENCES factura,PRIMARY KEY(pdto, codfac),cant NUMBER(8) NOT NULL CHECK (cant > 0));
INSERT INTO factura VALUES(1, SYSDATE);INSERT INTO factura VALUES(2, SYSDATE-30);
INSERT INTO detalle VALUES('Leche’, 1, 100);INSERT INTO detalle VALUES('Cerdo’, 1, 5);INSERT INTO detalle VALUES('Cerdo’, 2, 10);
Convertir este modelo a objeto relacional sin migrar los datos Crear una capa virtual Vistas objeto
Procedimiento
Crear los tipos para las vistas objeto deseadas:
DROP TYPE fac_type FORCE;CREATE TYPE fac_type AS OBJECT(codigo NUMBER(8),fecha DATE, MEMBER FUNCTION total_det RETURN
NUMBER);/
CREATE OR REPLACE TYPE BODY fac_type ASMEMBER FUNCTION total_det RETURN NUMBER
IS total_uni NUMBER(5); BEGIN SELECT SUM(cant) INTO total_uni FROM detalle WHERE codfac = SELF.codigo; RETURN total_uni; END total_det;END;/
DROP TYPE det_type FORCE;CREATE TYPE det_type AS OBJECT(pdto VARCHAR2(20),codfac NUMBER(8),cant NUMBER(8),fac_ref REF fac_type);/
Se crean las vistas objeto:
CREATE OR REPLACE VIEW fobj OF fac_type
WITH OBJECT OID(codigo) ASSELECT * FROM factura;
Campo en la vista, se corresponde con el campo codigo de la tabla factura
CREATE OR REPLACE VIEW detobj OF det_type
WITH OBJECT OID(pdto,codfac) ASSELECT pdto, codfac, cant,
MAKE_REFMAKE_REF(fobj, codfac)FROM detalle;
Campos en la vista, se corresponden con (pdto y codfac) en la tabla detalle
Para cada valor de codfac se obtiene un puntero desde la vista fobj
Sintaxis:
MAKE_REF(view_name, value_list)
Donde:
view_name: Vista objeto de la cual se desea derivar el REF
value_list: Lista de valores, separados por comas, los cuales se deben acoplar con los atributos que conforman el OID de la vista view_name.
Ya se puede trabajar con las vistas objetos como si fueran tablas objetuales:
SELECT * FROM fobj; SELECT f.codigo, f.total_det() AS total FROM fobj f; SELECT d.codfac, d.pdto, d.fac_ref.fecha FROM detobj d; INSERT INTO detobj(pdto, codfac, cant) VALUES('Gallina’, 2, 1000);
Incluso se pueden insertar datos a través de la vista. Los datos quedan en las tablas base (originales)
Top Related