270 likes | 437 Views
Características Objeto Relacionales en 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)
E N D
Características Objeto Relacionales en 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 tipoNO con una instancia de dicho tipo
CREATE OR REPLACE TYPE matem_tip AS OBJECT ( cod VARCHAR(8), STATIC FUNCTION factorial(n IN NUMBER) RETURN NUMBER); / CREATE OR REPLACE TYPE BODY matem_tip AS STATIC 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
Invocación • 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; / Nótese que es el tipo 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 (objetos) con un operador como >? Ej: empleado1 > empleado2 • Este problema también se presenta en consultas que involucran objetos en una cláusula: ORDER BYobjeto, GROUP BYobjeto, DISTINCTobjeto • 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 • Carece de parámetros • Es una función que debe retornar un valor correspondiente a un tipoprimitivo del sistema (no puede retornar objetos creados por el usuario)
Ejemplo DROP TYPE emp_type FORCE; CREATE OR REPLACE TYPE emp_type AS OBJECT( cedula VARCHAR2(10), nombre VARCHAR2(10), edad NUMBER(2), salario NUMBER (6), MAP MEMBER FUNCTION ord_por_salario RETURN NUMBER ); / Tipo primitivo
Implementación CREATE OR REPLACE TYPE BODY emp_type AS MAP 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 e ORDER BY VALUE(e); CEDULA NOMBRE EDAD SALARIO ---------- ---------- ---------- ---------- 171 Edneud 18 50 131 Lisa 25 80 111 Bobaldo 20 100 141 Mary 21 100 151 Paddy 21 100 121 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
Ejemplo DROP 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 MEMBER FUNCTION ord_por_salario(a IN emp_type) RETURN NUMBER ); /
CREATE OR REPLACE TYPE BODY emp_type AS 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 de nuevo la tabla emp e insertarle datos Y de nuevo ensayar las dos consultas El objeto invocador Esta operación devolverá un número negativo, positivo o el cero
SELECT VALUE(e), COUNT(*) AS cuantos FROM emp e GROUP BY VALUE(e); VALUE(e)(CEDULA, NOMBRE, EDAD, SALARIO) CUANTOS --------------------------------------- ------- EMP_TYPE('171', 'Edneud', 18, 50) 1 EMP_TYPE('131', 'Lisa', 25, 80) 1 EMP_TYPE('111', 'Bobaldo', 20, 100) 3 EMP_TYPE('121', 'Dumbo', 30, 200) 1
Vistas objeto FACTURA #código *fecha DETALLE #pdto *cant compuesta de de Considere el siguiente modelo E-R
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 tiposparalasvistas objetodeseadas: 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 AS MEMBER 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 ); /
Campo en la vista, se corresponde con el campo codigo de la tabla factura Se crean las vistas objeto: CREATE OR REPLACE VIEW fobj OF fac_type WITH OBJECT OID(codigo) AS SELECT * FROM factura;
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 CREATE OR REPLACE VIEW detobj OF det_type WITH OBJECT OID(pdto,codfac) AS SELECT pdto, codfac, cant, MAKE_REF(fobj, codfac) FROM detalle;
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.
Incluso se pueden insertar datos a través de la vista. Los datos quedan en las tablas originales 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);