Características Objeto Relacionales en Oracle Francisco Moreno Universidad Nacional
Tipos y Refs Ejemplo: Sean los tipos: CREATE TYPE dir_tipo AS OBJECT( dir VARCHAR2(10), ciudad VARCHAR2(20) ); / CREATE TYPE persona_tipo AS OBJECT( cod NUMBER(10), hv XMLTYPE,--hoja de vida p_dir dir_tipo
CREATE TYPE vendedor_tipo AS OBJECT( territorio VARCHAR2(10), v_datos persona_tipo ); / dir_tipo persona_tipo Usado por vendedor_tipo Usado por ¿Hay aquí herencia?
Creación de una tabla tipada: CREATE TABLE vendedor OF vendedor_tipo; ALTER TABLE vendedor ADD PRIMARY KEY(v_datos.cod);
Inserción de un vendedor: INSERT INTO vendedor VALUES ('Norte', persona_tipo(234, XMLTYPE('<Datos> <Nom>Emma</Nom> <Sal>18</Sal> </Datos>'), dir_tipo('Cl 56', 'Bogota') ) );
Otros dos vendedores: INSERT INTO vendedor VALUES ('Sur', persona_tipo(666, XMLTYPE('<Datos> <Nom>Geri</Nom> <Sal>20</Sal> </Datos>'), dir_tipo('Cl 666', 'Cali'))); ('Sur', persona_tipo(611, XMLTYPE('<Datos> <Nom>Mel</Nom> <Sal>50</Sal> </Datos>‘), dir_tipo('Cl 26', 'Bogota')));
Consultas: 1. Seleccionar el nombre, la dirección (dir) y el territorio de todos los vendedores: SELECT EXTRACTVALUE(v.v_datos.hv,'/Datos/Nom') AS nom, v.v_datos.p_dir.dir AS direc, v.territorio AS territ FROM vendedor v;
2. Seleccionar todos los datos personales de los vendedores de Bogotá. SELECT v.v_datos AS datos_personales FROM vendedor v WHERE v.v_datos.p_dir.ciudad = 'Bogota';
3. ¿Cuántos vendedores hay en cada ciudad? SELECT v.v_datos.p_dir.ciudad AS city, COUNT(*) AS cuantos FROM vendedor v GROUP BY v.v_datos.p_dir.ciudad;
Supóngase que cada vendedor puede estar encargado de muchos clientes y un cliente debe ser manejado por un único vendedor: El identificador único es cod CLIENTE VENDEDOR encargado de #id_cliente *nom °territorio v_datos manejado por El manager del cliente es un vendedor
¿Cómo se puede implementar CLIENTE?: - Una tabla con una columna tipada - Crear un tipo y luego la tabla tipada Tipo de las columnas de CLIENTE: - id_cliente Numérico - nom Cadena de caracteres - manager En el modelo relacional sería una clave foránea. En el modelo objeto-relacional es un REF.
Se va a crear un tipo cliente_tipo y luego una tabla tipada: CREATE TYPE cliente_tipo AS OBJECT( id_cliente NUMBER(10), nom VARCHAR2(20), manager REF vendedor_tipo ); / CREATE TABLE cliente OF cliente_tipo( id_cliente PRIMARY KEY, SCOPE FOR (manager) IS vendedor, manager NOT NULL); Puntero
¿Cómo se inserta un cliente? a) Mediante un INSERT basado en un SELECT: INSERT INTO cliente SELECT 129, 'Lisa', REF(v) FROM vendedor v WHERE v.v_datos.cod = 234; Obtiene el puntero del vendedor con cod 234
b) Mediante un INSERT con VALUES, el cual incluye un SELECT para obtener el REF: INSERT INTO cliente VALUES (145, 'Adam', (SELECT REF(v) FROM vendedor v WHERE v.v_datos.cod = 666 ) ); INSERT INTO cliente VALUES (111, 'George', (SELECT manager FROM cliente WHERE id_cliente = 145) ); O asignándole el de otro cliente Otra forma de obtener el puntero de un vendedor
SELECT id_cliente AS codigo, DEREF(manager) AS datos_manager Consultas: 1. Imprimir el código de todos los clientes y todos los datos de su manager. SELECT * FROM cliente; SELECT id_cliente AS codigo, DEREF(manager) AS datos_manager En SQL*Plus no imprime los datos del manager, sino su puntero (en otros productos sí salen los datos) Función de “dereferenciamiento“
2. Imprimir la cédula de cada cliente y la cédula de su manager: SELECT id_cliente, DEREF(manager).v_datos.cod AS cod_manager FROM cliente c; --También funciona sin el DEREF: c.manager.v_datos.cod AS cod_manager
DEREF fue concebido para “dereferenciar” todos los atributos de la tupla objeto referenciada Se puede acceder a cada atributo de una tupla referenciada con o sin DEREF En conclusión: DEREF es una forma más corta de traer todos los atributos de una tupla objeto referenciada
3. Imprimir la cédula de cada manager y el número de clientes que este maneja: SELECT c.manager.v_datos.cod AS codman, COUNT(*) AS representados FROM cliente c GROUP BY c.manager.v_datos.cod; --También se puede agrupar por el puntero: SELECT MAX(c.manager.v_datos.cod) AS codman, GROUP BY manager; --¿Por qué se requiere una función como MAX aquí?
Esta consulta también se puede resolver desde la tabla comisionista: SELECT v.v_datos.cod AS codman, (SELECT COUNT(*) FROM cliente WHERE manager = REF(v)) AS representados FROM vendedor v; Sin embargo, nótese que desde el punto de vista de resultados puede llegar a haber diferencias con la consulta anterior…
Ejercicios: Imprimir la cédula de los vendedores que no manejan clientes. Confrontar los ejemplos anteriores contra la versión relacional. Modelar la siguiente situación mediante REFs: Un país tiene departamentos y un departamento tiene municipios. No usar claves foráneas. Imprimir el nombre de cada municipio y el nombre del departamento y el país al que pertenece el municipio.