Title: Caracter
1Características Objeto Relacionales en Oracle
- Francisco Moreno
- Universidad Nacional
2Mé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 tipo NO con una instancia de dicho tipo
3Métodos Estáticos
- 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
- /
4Invocació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
5Métodos MAP y ORDER
- Qué pasa si se comparan dos columnas tipadas
(objetos) con un operador como gt? - Ej empleado1 gt empleado2
- Este problema también se presenta en consultas
que involucran objetos en una cláusula - ORDER BY objeto, GROUP BY objeto,
- DISTINCT objeto
- Para solucionar este problema se debe crear un
método MAP u ORDER
6Mé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?
7Mé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, gt,
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
8Método MAP
- No tiene parámetros
- Es una función que debe retornar un valor
correspondiente a un tipo primitivo del sistema
(no puede retornar objetos creados por el usuario)
9Ejemplo
- 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
10Implementació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
- /
11- 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', 'Dawn', 30, 200)
- INSERT INTO emp VALUES('131', 'Lisa', 25, 80)
- INSERT INTO emp VALUES('141', 'Sidhe', 21, 100)
- INSERT INTO emp VALUES('151', 'Paddy', 21, 100)
- INSERT INTO emp VALUES('171', 'Edneud', 18, 50)
12- 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 Sidhe 21
100 - 151 Paddy 21 100
- 121 Dawn 30
200 - Si hay empates en el valor retornado por la
función MAP, el orden entre los empatados es
aleatorio
Empate (100)
13- Considérese la 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', 'Dawn', 30, 200)
- Qué pasó con Sidhe y con Paddy? ? Desaparición
14Mé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 lt, o gt 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
15Ejemplo
- 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
- )
- /
16- 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
- /
- Volver a crear la tabla emp, insertarle datos y
ensayar las dos consultas
El objeto invocador
Esta operación devolverá un número negativo,
positivo o el cero
17- 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', 'Dawn', 30, 200) 1
18Vistas objeto
- Considere el siguiente modelo E-R
FACTURA código ?fecha
DETALLE pdto cant
compuesta de
de
19- Implementación relacional
- CREATE TABLE factura(
- codigo NUMBER(8) PRIMARY KEY,
- fecha DATE)
- CREATE TABLE detalle(
- pdto VARCHAR2(20),
- codfac NUMBER(8) REFERENCES factura,
- PRIMARY KEY(pdto, codfac),
- cant NUMBER(8) NOT NULL CHECK (cant gt 0)
- )
fecha opcional, ver la vista final
20- INSERT INTO factura VALUES(1, SYSDATE)
- INSERT INTO factura VALUES(2, SYSDATE-30)
- INSERT INTO factura VALUES(3, SYSDATE1)
- 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
21Procedimiento
- 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)
- /
22- CREATE OR REPLACE TYPE BODY fac_type AS
- MEMBER FUNCTION total_det RETURN NUMBER IS
- total_uni NUMBER(5)
- BEGIN
- SELECT NVL(SUM(cant),0) INTO total_uni
- FROM detalle
- WHERE codfac SELF.codigo
- RETURN total_uni
- END total_det
- END
- /
23- 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
- )
- /
24- Se crean las vistas objeto
- CREATE OR REPLACE VIEW fobj OF fac_type
- WITH OBJECT OID(codigo) AS
- SELECT FROM factura
Campo en la vista, se corresponde con el campo
codigo de la tabla factura
25- CREATE OR REPLACE VIEW detobj OF det_type
- WITH OBJECT OID(pdto,codfac) AS
- SELECT pdto, codfac, cant,
- MAKE_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
26- 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.
27- 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 fec
- FROM detobj d
28- SELECT d.codfac, d.pdto,
- d.fac_ref.total_det() total
- 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)
29- Se pueden también crear vistas sobre vistas, etc.
Aquí se crea una vista no objetual a partir de la
vista objeto anterior - CREATE OR REPLACE VIEW fnobj AS
- SELECT codigo FROM fobj WHERE codigo gt1
- SELECT FROM fnobj
- INSERT INTO fnobj VALUES(0)
- SELECT FROM fnobj
- SELECT FROM fobj
Y el valor ingresado a través de la vista no es
visible para ella! Pero sí lo es para la otra
vista