Lo más aconsejable es que instales la que hay instalada en las aulas de prácticas de la ETSII que es la 6i, ya que la presentación de la aplicación se hará en esas aulas. Si utilizas una versión superior (9i o 10g) seguramente no funcionará y tendrás que llevarte tu propio ordenador.
Lo más aconsejable es que instales sólo Developer y con éste te conectes a la Base de Datos de la ETSII, pero para ello necesitas conexión a internet. Si prefieres trabajar en local para Windows XP/2000 instala la versión 9, para Windows 95/98/NT instala la version 8 y para Windows ME, cambia de sistema operativo.
Para acceder al servidor Oracle de forma remota se puede hacer usando la aplicación SQL Net Easy configuration (dependiendo de la versión de Developer se puede llamar también Oracle Net8 Easy Config o Net Configuration Assistant). Los pasos que hay que dar son:
De esta forma para conectarse a la base de datos (tanto en SQL Plus como en Developer), te hará falta el usuario, el password y en la cadena de conexión pones el alias creado (por ejemplo, bd2)
Lo primero es usar el usuario que has creado porque no se conectará con los usuarios SYS o SYSTEM. Si aún no se conecta, prueba a configurar un alias (como en el apartado anterior). Donde la instancia de la BD (SID) es la que tú has creado y el servidor es localhost. De esta forma para conectarse a la base de datos (tanto en SQL Plus como en Developer), te hará falta el usuario, el password y en la cadena de conexión pones el alias creado.
Supongamos que tenemos una clave primaria en la tabla Proveedor cuya clave primaria es Nombre y Dirección y una tabla Distribuye que relaciona la anterior con una tabla productos y cuyos campos son Nombre, Dirección y CodigoProducto. La forma de crearla sería la siguente:
CREATE TABLE Distribuye ( Nombre VARCHAR(10), /*Referencia a Proveedor(Nombre)*/ Direccion VARCHAR(25), /*Referencia a Proveedor(Nombre)*/ CodigoProdcuto INTEGER REFERENCES Productos(cod), /*Referencia a Producto(cod)*/ /*La clave primaria son los 3 campos, relación muchos a muchos)*/ CONSTRAINT ClavePrimariaDistribuye PRIMARY KEY (Nombre,Direccion,CodigoProducto), /*La clave externa son 2 campos de la tabla proveedor*/ CONSTRAINT ClaveExternaDobleProveedort FOREIGN KEY (Nombre,Direccion) REFERENCES Proveedor(Nombre,Direccion) );
Después de crear las tablas y de insertar los datos iniciales tienes que hacer un commit;
Desde Archivo->Importar->Imagen y desde ahí puedes abrir una imagen que se te incorpora al formulario o al informe No todos los tipos de formato de imagen son soportados pero si los más comunes.
Usando dicho campo (por ejemplo, codigo) en el bloque de datos (por ejemplo, productos) que se usa, pero no mostrándolo (eso se hace en el asistente de diseño). Posteriormente desde el disparador PRE-COMMIT escribir SELECT MAX(codigo)+1 INTO :productos.codigo FROM tabla_productos;
Poniendo dentro del cuerpo del disparador WHEN-NEW-FORM-INSTANCE la línea execute_query;
Tienes que poner la propiedad de Visualización Automática del LOV a si. Si quieres que no se visualice automaticamente lo pones a No y cuando quieres que se visualice pulsas F9.
Vamos a hacer un acceso identificado para el ejemplo del tutorial, usaremos el nombre de empleado como login y su edad como contraseña. Lo que vamos a hacer es utilizar acceso identificado al formulario de recursos humanos (el de loz lienzos tabulares) Lo primero que haremos será crear un formulario (lo llamaremos Acceso) con un bloque de datos basado en la tabla Persona dónde se visualice un sólo registro. Añadiremos un botón Aceptar, otro Limpiar y otro Salir.
Para que no se nos muestre el password (campo edad) al hacer un ejecutar_consulta tendremos que irnos a sus propiedades y poner Ocultar Datos a Si y Elemento de la Base de Datos a No
Para cada botón definiremos un disparador WHEN-BUTTON-PRESSED (para cada botón no para todo el formulario), donde el codigo del boton Aceptar seria:
DECLARE cursor usuario is select edad, nombre from persona where nombre= :persona.nombre; tipo usuario %rowtype; ignora number; BEGIN open usuario; fetch usuario into tipo; if :persona.edad = tipo.edad then /*Si queremos que no se cierre el formulario de acceso usamos OPEN_FORM('RecursosHumanos'); CLEAR_FORM(NO_VALIDATE); */ /*Abrimos el nuevo formulario y cerramos el de acceso*/ CALL_FORM('RecursosHumanos'); exit_form; else /*En caso de fallo mostramos un Alert diciendo que hay un acceso erroneo*/ ignora:=Show_Alert('errorAcceso'); /*Limpiamos para empezar de nuevo*/ CLEAR_FORM(NO_VALIDATE); end if; close usuario; END;
Observamos que cuando se comete un error llama a la Alerta errorAcceso por tanto hay que crearla. Se puede usar tanto CALL_FORM como OPEN_FORM si se quiere ver las diferencias o si se quisiera utilizar parámetros al llamar al formulario, mirar la ayuda en línea de Oracle Developer.
El codigo del boton Borrar sería clear_form(no_validate);y para el botón Salir seria exit_form;
Si para la contraseña usamos cadenas de texto a la hora de declarar los campos debe usarse VARCHAR, si usamos CHAR no funcionará.
Sería de forma análoga como hemos llamado en la pregunta anterior al formulario Principal desde el formulario Acceso.
Con la utilización de parámetros al igual que como se hace en los informes.
Supongamos que el campo que queremos rellenar es Nombre (el ejemplo de lienzos tabulares del tutorial nos sirve). Le damos al botón de Introducir Consulta (Enter Query) rellenamos el nombre (por ejemplo Ramon) y le damos al botón de Ejecutar Consulta.
Si queremos no tener que utilizar estos dos botones y hacerlo de forma que sólo se introduzca el nombre y le demos a un botón, se haría creando un nuevo botón, al que le asociamos un disparador WHEN-BUTTON-PRESSED donde ponemos de código execute_query; y el disparador WHEN-NEW-FORM-INSTANCE del formulario añadimos la línea enter_query;.
Añadiríamos un botón con un disparador WHEN-BUTTON-PRESSED cuyo código sería delete_record; y lo que haría sería borrar el registro que se está visualizando
Esto ocurre cuando al campo del formulario tiene la propiedad de Obligatorio puesta a Sí. Basta con cambiarlo a No, pero si lo que se quiere es obligar al usuario a introducir datos en un campo sin usar esta característica de Oracle, se tendría que comprobar en un disparador que el contenido no está vacío.
Supongamos que tenemos una relación mucho a muchos entre las entidades Coche, Caracteristicas y la relación Tiene. Si lo hacemos normalmente, creamos el Bloque de Datos Coche, luego lo relacionamos con Tiene y finalmente añadimos el Bloque de Datos Caracteristicas relacionado con el Bloque Tiene, nos va a salir que cada coche tiene una sóla característica, si visualizamos los campos del bloque de datos Tiene veremos que para cada coche se ven todas sus entradas de la tabla Tiene y para cada una de estas se muestra sólo una caracteristica.
Si quisieramos ver todas las características de cada coche las solución más fácil es crear una vista que aglutine Tiene y Caracteriticas, y a la hora de realizar el formulario se haga con dos Bloques de Datos uno para Coche y otro para la vista creada.
Para cada elemento que no quieras que se modifique activale la propiedad Activado a No
Esto lo vamos a hacer de una forma sencilla, en un campo de una tabla guardaremos la ruta hasta la imagen (path) y en el formulario lo que haremos será leer desde un fichero la imagen cuya ruta nos da la BD y mostrarla en el formulario. Es importante que esa ruta sea simple (portabilidad de la aplicación a la ETSII) y que los ficheros con las imágenes existan.
Vamos a suponer que en el ejemplo de la granja tenemos en la tabla persona un campo llamado Foto, donde guardaremos la ruta hacia la imagen de la persona. Cuando construyamos el Bloque de Datos sobre la tabla Persona escogeremos también el campo Foto, pero no los mostraremos.
Una vez con el bloque de datos para Persona creado, en el Editor de Diseño crearemos un Elemento de Imagen (icono con un paisaje), la cambiaremos el nombre a, por ejemplo, IMAGENFOTO y le cambiaremos la propiedad Elemento de Base de Datos a No y la propiedad Obligatoria a No.
Para el bloque de datos Persona crearemos un disparador POST-BLOCK cuyo código será READ_IMAGE_FILE(:Persona.foto, 'JPG', 'Persona.IMAGENFOTO'); donde le decimos que lea una imagen desde un fichero (el que le da :Persona.foto) y lo ponga en un elemento de imagen (llamado 'Persona.IMAGENFOTO'). Si quieres saber más acerca del disparador POST-BLOCK o de la función READ_IMAGE_FILE mira la ayuda en línea de Developer.
Tanto si usamos CALL_FORM, OPEN_FORM(ambos para formularios y que tiene una forma que acepta una lista de parámetros) o RUN_PRODUCT (que nos sirve tanto para formularios como para informes) tendremos que definir una lista de parámetros y añadir los parámetro uno a uno. Por ejemplo:
DECLARE parametros Paramlist; /*Definimos la lista de parametros*/ BEGIN /*Creamos la lista de parametros*/ parametros := Create_Parameter_List('datos'); /*Añadimos parametros*/ Add_parameter(parametros,'empleado',TEXT_Parameter,:persona.nombre); Add_parameter(parametros,'tipo',TEXT_Parameter,'Pago'); /*Llamamos a un informe con parametros*/ Run_PRODUCT(REPORTS,'LibroContabilidadEmpleadoTipo',SYNCHRONOUS, RUNTIME, FILESYSTEM,parametros ,NULL); END;
En el anterior ejemplo añadimos a la lista de parámetros llamada parametros dos parametros de texto (TEXT_PARAMETER) cuyo nombre son empleado y tipo y en el primero le pasamos el valor cogiendo de un campo de un bloque de datos ( persona.nombre) y en el segundo le pasamos una cadena ('Pago').
En el Report Builder, Iniciamos el asistente y creamos una consulta temporal que no utilice los paramétros.
Una vez creada la consulta, desde el navegador de objetos creamos dos Parámetros del Usuario con sus respectivos nombres y tipos (siguiendo el ejemplo anterior les ponemos Empleado y Tipo, usando el Tipo de Dato Cararacter). Ejecutamos el Asitente de Informes y en la pestaña datos modificamos la consulta para que utilice los parámetros (en nuestro caso sería, por ejemplo, select * from librocuentas where persona= :empleado AND tipooperacion= :tipo;)
Desde el Reports Builder con el informe abierto, nos vamos a herramientas->Constructor de Pantalla de Parametros. Dejamos en blanco el Titulo, la Linea de Indicación y la Línea de Estado, además deseleccionamos aquellos atributos que estuviesen seleccionados en la lista.
No se debe, ya que la lista está vacía al principio (sólo tiene el valor por defecto) y posteriormente la rellenas cuando se crea el formulario, si está la clave primaria vacía o la clave externa vacía no puede recuperar bien los datos de la base de datos, ni hacer bien las relaciones.
Lo aconsejable sería utilizar bloque LOV.
Supongamos que lo que queremos hacer es que en el formulario de Recursos Humanos empiece siempre mostrando al empleado 'Ignacio'. Para ello en el disparador WHEN-NEW-FORM-INSTANCE del formulario añadimos el siguiente código:
DECLARE bloquedatos Block; BEGIN /*Nos vamos al bloque de datos en el que queremos hacer la consulta*/ bloquedatos := Find_Block('Persona'); /*Modificamos la clausula WHERE del bloque de datos*/ Set_Block_Property(bloquedatos,DEFAULT_WHERE, ' nombre = ''Ignacio'' '); /*Ejecutamos la consulta*/ Execute_Query; END;
Supongamos que en el formulario de Acceso al darle al botón Aceptar queremos que se pase el nombre del empleado que se ha identificado de forma que en el formulario de RecursosHumanos (llamador por Acceso) se nos muestren los datos de dicho empleado.
Lo primero que tendremos que hacer es modificar el código del botón Aceptar en el formulario Acceso para que mande el nombre del empleado como parámetro al llamar al formulario RecursosHumanos:
DECLARE cursor usuario is select edad, nombre from persona where nombre= :persona.nombre; tipo usuario %rowtype; ignora number; parametros Paramlist; /*Definimos la lista de parametros*/ BEGIN open usuario; fetch usuario into tipo; if :persona.edad = tipo.edad then /*Creamos la lista de parametros*/ parametros := Create_Parameter_List('datos'); /*Añadimos como parametro la persona que se ha identificado*/ Add_parameter(parametros,'empleado',TEXT_Parameter,:persona.nombre); /*Llamamos al formulario de Recursos Humanos*/ Run_PRODUCT(FORMS,'RecursosHumanos',SYNCHRONOUS, RUNTIME, FILESYSTEM,parametros ,NULL); /*cerramos el de acceso*/ exit_form; else /*En caso de fallo mostramos un Alert diciendo que hay un acceso erroneo*/ ignora:=Show_Alert('errorAcceso'); /*Limpiamos para empezar de nuevo*/ CLEAR_FORM(NO_VALIDATE); end if; close usuario; END;
Lo segundo que haremos es modificar el formulario de RecursosHumanos para que se inicialice con la persona que se le pasa como parámetro. Antes de anda tendremos que definir un nuevo parámetro en el navegador de objetos (dándole a crear) y le daremos nombre EMPLEADO (el nombre con el que lo llamamos desde el formulario Acceso) y que sea de tipo carácter. Después modificaremos el disparador WHEN-NEW-FORM-INSTANCE como en la pregunta anterior pero cambiando la línea Set_Block_Property(bloquedatos,DEFAULT_WHERE, ' nombre = ''Ignacio'' '); por Set_Block_Property(bloquedatos,DEFAULT_WHERE, ' nombre = :Parameter.empleado ');.
Para cada botón de un grupo de Radio buttons tenemos que activar la propiedad Valor de Botón de Radio a un valor diferente, por ejemplo 1, 2 y 3 si tenemos tres botones. Posteriormente para saber que valor tiene, si el grupo de botones de radio se llama GBRADIo y está en el bloque de datos PERSONA, tendremos que comparar :Persona.gbradio con 0, 1 y 2 para saber que botón es el que está activado. Para el grupo de Radio buttons (GBRADIO en nuestro caso) habrá que poner la propiedad ValorInicial a uno de los valores introducidos en los radio buttón, por ejemplo, 1 para que se marque ese por defecto.
Tendremos que inicilizar las propiedades Valor Si Está Comprobado y Valor Si No Está Comprobado, por ejemplo a 1 y 0, el primero si está marcado y el segundo para si no lo está. Posteriormente para saber que valor tiene, si el checkbox se llama MiCheckBox y está en el bloque de datos PERSONA, tendremos que comparar :Persona.micheckbox con 1 ó 0 para saber si está activado o no.
Igual que cuando lo vimos en la pregunta ¿Cómo generar valores consecutivos (un código) para un campo desde un formulario? pero podemos poner SELECT misecuencia.NEXTVAL INTO :productos.codigo FROM dual;
Básicamente como muestra el siguiente código:
DECLARE cadena1 varchar2(50); cadena2 varchar2(50); numero number; BEGIN /*Me quedo con la subcadena que tiene el numero*/ cadena1:=substr(:Productos.codigo.texto,2,length(:Productos.codigo)); /*Lo paso a numero*/ numero:=TO_number(cadena1); /*Lo incremento*/ numero:=numero+1; /*Lo vuelvo a pasar a cadena*/ cadena2:=TO_CHAR(numero); /*Le añado la letra la principio*/ cadena1:='T'||cadena2; /*Actualizo la clave*/ :Prodcutos.codigo :=cadena1; END;
Hay que tener en cuenta que esto está pensado para códigos que tiene una sóla letra (la T) antes de un número y que incrementa el que se encuentra en el formulario (para obtener el maximo a partir de la tabla se podría hacer con un SELECT INTO con un ORDER BY para que los ordene).
No se puede hacer, ya que no se puede usar SYSTIME en la creación de tablas. Ten en cuenta que la tabla se crea una vez y usar SYSTIME en una clausula CHECK sería algo dinámico. Para hacerlo se pueden usar disparadores (triggers) dentro de la base de datos, pero eso se sale un poco de nuestros objetivos, lo ideal sería hacer las comprobaciones en nuestra aplicación.
Los bloques de datos de nuestros formularios son consultas a la base de datos pero que no tienen, por defecto, una clausula WHERE. Esta clausula WHERE se puede definir en la paleta de propiedades de los bloques de datos algo que hicimos en PL/SQL en las preguntas 24 y 25.
Rellenando cada uno por separado en el disparador WHEN-NEW-FORM-INSTANCE:
Go_Block('librodecuentas'); Execute_Query; Go_Block('personas'); Execute_Query; Go_Block('empleados'); Execute_Query; Go_Block('alojamiento'); Execute_Query;
Como cualquier otras dos tablas que están relacionadas, si aún así tienes problemas puedes usar una vista para unir todos los campos de ambas tablas
Este problema se suele dar cuando tenemos un bloque de datos a partir de una tabla de la base de datos y queremos realizar alguna operación sobre dicha tablas. El problema está en que Forms abre la tabla (para usarla, lógico) y la bloquea de forma que cualquier operación insert/update sobre dicha tabla fallará. La única solución a este problema es no usar dicha tabla para construir un bloque de datos (y contruir el bloque de datos manualmente, rellenando sus datos desde PL/SQL), o bien, usar el form para añadir/actualizar registros en la base de datos.
No es necesario. Basta con tener todo los ficheros necesarios (formularios, informes, bibliotecas, menús, gráficos, imágenes, ficheros .sql, etc.) recopilado en la entrega.
Si. Hay que entregarlo con los fallos corregidos, que ya se indicaron en su día.
Lo ideal sería que todos los ficheros estuvieran en un CD y se pudiese ejecutar desde ahí. Aunque también se puede optar por guardar todos los ficheros en un directorio (o estructura sencilla) que cuelgue de C: e indicarlo de forma muy clara en la entrega.
En mi despacho en el edificio Mecenas, teneis un mapa en http://decsai.ugr.es/~fjgc/despacho/despacho.html
Los turnos se harán públicos (en internet y en la ETSII) una vez que todo el mundo haya entregado sus prácticas
Si.