-
¿Que versión de Developer instalo?
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.
- ¿Que versión de Oracle instalo?
Lo más sencillo 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 sigue las instrucciones del tutorial de instalación.
- ¿Cómo conectar Oracle Developer con la base de datos Oracle de la ETSII?
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:
- crear/agregar un alias (o un nuevo servicio o configurar los métodos de nomenclatura), por ejemplo, lo puedes llamar bd2 (se llama alias, nombre del servicio o nombre del servicio de red)
- que utilice TCP/IP. No cambiar (si lo permite) el puerto por defecto 1521
- Que use como servidor (TCP/IP host name) oracle0.ugr.es
. Sería conveniente comprobar antes que podeis acceder a dicho servidor, para ello desde MS-Dos (símbolo del sistema) poned "ping oracle0.ugr.es", si no responde es probable que se haya caido el servidor.
- La instancia de la base de datos (database instance o SID de la Base de datos) es PRACTBD
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)
- ¿Cómo conectar Oracle Developer con la base de datos Oracle de mi ordenador?
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.
- No consigo conectar con la base de datos Oracle de la ETSII¿Qué pasa?
Suponiendo que se han seguido todos los pasos correctamente y que el cortafuegos no nos cierra el puerto 1521. Tendremos que asegurarnos que nos estamos conectando a la red de la universidad de Granada por VPN. En algunos casos la versión 2005 del Panda Platinum bloquea el acceso a Oracle.
- ¿Cómo conecto Oracle Developer con la base de datos Oracle XE?
Para conectar Developer Forms 6i a Oracle XE se debe hacer lo siguiente:
- Instalar primero Developer Forms 6i.
- Instalar Oracle XE (Esto con el objetivo de que en las variables de entorno debe estar primero el path de Oracle XE)
- Hay que asegurarse que en el registro de windows en:
HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE
la variable NET80 tenga el valor C:\ORANT\NET80
- En la ruta C:\ORANT\NET80\ADMIN se encuentran los ficheros TNSNAMES.ORA y SQLNET.ORA, hay que hacer una copia de seguridad de los mismos y reemplazarlos por los que instala Oracle XE en la ruta
C:\oraclexe\app\oracle\product\10.2.0\server\NETWORK\ADMIN
- Por ultimo hay que ejecutar lo siguiente desde una ventada de DOS:
C:\>sqlplus /nolog
SQL> connect / as sysdba
Conectado.
SQL> shutdown immediate
SQL> startup restrict
SQL> alter database character set internal_use UTF8;
SQL> shutdown immediate
SQL> startup
Nota: Esto es para que al conectar con Oracle XE no de error windows.
-
Para conectarse:
User Name: system
Password : (Password que colocaron al momento de instalar Oracle XE)
database : XE
Y con esto debería funcionar.
- ¿Cómo referenciar a una clave externa con dos campos?
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)
);
- ¿Cómo almaceno horas en Oracle o fechas y horas?
Usando el tipo de dato DATE y la función SET_DATE, la cual, tiene dos argumentos uno con la
fecha/hora y otro con el formato que sigue esa fecha y hora.
Por ejemplo, si queremos guardar una cita con un cliente un día y a
una hora determinada sería
INSERT INTO Citas VALUES('11223344X',to_date('6/06/2006:20:00:00','dd/mm/yyyy:hh24:mi:ss'));
que guardaría una cita con el cliente 11223344X el día 6 de Junio de 2006 a las
20:00 horas. Si queremos guardar sólo la fecha
INSERT INTO Citas VALUES('11223344X',to_date('6/06/2006','dd/mm/yyyy'));
o sólo la hora
INSERT INTO Citas VALUES('11223344X',to_date('20:00:00','hh24:mi:ss'));
En developer en la paleta de propiedades de los elementos de Tipo de dato Date hay una
propiedad que nos sirve para poner el formato a usar en la fecha denominada máscara de
formato que utiliza el mismo formato que la función TO_DATE
- No me recupera ningún registro desde Developer pero desde Sql Plus al hacer un select me salen los datos ¿Qué pasa?
Después de crear las tablas y de insertar los datos iniciales tienes que hacer un commit;
- ¿Cómo usar mis imágenes para decorar los formularios/informes?
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.
- ¿Cómo generar valores consecutivos (un código) para un campo desde un formulario?
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;
- ¿Cómo empezar con el formulario con valores sin tener que pulsar el botón execute_query/ejecuta_consulta?
Poniendo dentro del cuerpo del disparador WHEN-NEW-FORM-INSTANCE la línea execute_query;
- Utilizo un LOV y al ejecutar el formulario me sale en la barra de estado Lista de Valores/List of Values pero el LOV no se muestra ¿Por qué?
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.
- ¿Cómo hacer un acceso identificado para mi aplicación?
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á.
- ¿Como ejecutar un formulario/informe distinto al que estamos usando al pulsar un botón?
Sería de forma análoga como hemos llamado en la pregunta anterior al formulario Principal desde el formulario Acceso.
- ¿Como elegir diferentes opciones de características de un formulario?
Con la utilización de parámetros al igual que como se hace en los informes.
- En un formulario quiero rellenar un campo darle a un botón y que me rellene el resto de los campos ¿Cómo lo hago?
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;.
- ¿Cómo puedo borrar la tupla actual que se muestra en un formulario pulsando un botón?
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
- Me sale el error FRM-402002: Es obligatorio introducir un valor en el elemento ¿cómo lo quito?
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.
- ¿Como puedo modelar una relación muchos a muchos ?
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.
- ¿Cómo hago que un elemento no se pueda modificar (que sólo se muestre)?
Para cada elemento que no quieras que se modifique activale la propiedad Activado a No
- ¿Cómo usar imágenes de la BD para los formularios?
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.
- ¿Cómo pasar parámetros a un formulario o a un informe?
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').
- ¿Cómo usar los parámetros de un informe en la consulta?
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;)
- ¿Cómo quitar la ventana que te pide los parámetros de un informe?
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.
- ¿Se puede utilizar una lista dinámica para una clave primaria o para una clave externa utilizada en una relación?
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.
- Me gustaría que al entrar a un formulario, se realizara automaticamente Execute_query con un campo relleno. ¿Cómo lo hago?
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;
- ¿Cómo pasar parametros de un formulario a otro?
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:
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 ');.
- ¿Cómo saber que valor he escogido de un grupo de Radio Button?
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.
- ¿Cómo saber si he marcado un checkbox?
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.
- ¿Cómo incrementar el campo código si uso secuencias?
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;
- ¿Cómo incrementar el campo código si tengo una letra antes del número?
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).
- ¿Quiero crear una tabla donde tenga una comprobación de tiempo respecto a la fecha actual ¿Cómo lo hago?
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.
- ¿Cómo hago que en mi formulario se vea sólo la parte de una tabla que cumple determinadas características?
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.
- Tengo una serie de bloques de datos en el mismo formulario y que no están relacionados (por ejemplo, varias pestañas) y al ejecutar un execute_query (ejecutar consulta) sólo se me rellena el primero de ellos ¿cómo relleno los demás?
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;
- Tengo una especialización y tengo problemas para mostrarla junto su generalización ¿cómo lo hago?
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
- Quiero hace un un insert/update dentro de un disparador, pero no funciona ¿cómo hago que funcione?
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.
- ¿Hay que entregar el diseño de la aplicación otra vez?
Si. Hay que entregarlo con los fallos corregidos, que ya se indicaron en su día.
- ¿Cómo preparo los ficheros de mi aplicación para que no me den problemas con las rutas (path)?
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.