Edmundo A. Cáceres TABLAS, BASES DE DATOS E ÍNDICES 2008 Índice Introducción ........................................................................................................................................................4 Comando ? .....................................................................................................................................................4 Barra de estado ..............................................................................................................................................4 Resultado de comandos .................................................................................................................................4 Tablas .................................................................................................................................................................5 Tipos de tablas ...............................................................................................................................................5 Creación de una tabla: Diseñador de tablas...................................................................................................6 Create ........................................................................................................................................................7 Tipos de campos ............................................................................................................................................7 Ventana Examinar ..........................................................................................................................................7 Apertura de la ventana Examinar ...................................................................................................................8 Browse .......................................................................................................................................................9 Cierre de tablas. Use, Close, Clear, Quit....................................................................................................9 Apertura de tablas ..........................................................................................................................................9 Use...........................................................................................................................................................10 Modos Editar y Examinar..............................................................................................................................10 Modo Añadir .................................................................................................................................................10 Marcadores de registro.................................................................................................................................10 Marcadores de destrucción ..........................................................................................................................10 Partidor .........................................................................................................................................................11 Tamaño y movimiento de la ventana Examinar ............................................................................................11 Líneas de cuadrícula ....................................................................................................................................11 Ancho y posición de las columnas................................................................................................................11 Alto de encabezados y renglones.................................................................................................................11 Menú Edición................................................................................................................................................11 Set keycomp.............................................................................................................................................12 Fuente ..........................................................................................................................................................12 Filtro de registros..........................................................................................................................................12 Between( ) e Inlist( ) .................................................................................................................................13 Set filter to ................................................................................................................................................13 Exactitud en comparaciones de caracteres ..................................................................................................14 Set exact ..................................................................................................................................................14 Operador ==.............................................................................................................................................14 Número de registro y cantidad de registros ..................................................................................................14 Filtro de campos ...........................................................................................................................................14 Diálogo Selector de campos.........................................................................................................................14 Set fields ..................................................................................................................................................15 List structure y Display structure ..............................................................................................................15 List status y Display status .......................................................................................................................15 Orden del índice ...........................................................................................................................................16 Set order to ..............................................................................................................................................16 Index on ...................................................................................................................................................16 Dir.............................................................................................................................................................16 Borrado del escritorio....................................................................................................................................17 Clear.........................................................................................................................................................17 Archivo de índices compuesto estructural ....................................................................................................17 Alcance.........................................................................................................................................................17 For ................................................................................................................................................................18 While.............................................................................................................................................................18 Ir a un registro ..............................................................................................................................................19 –1– Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 Go, Skip, Locate y Continue.....................................................................................................................20 Comienzo y fin de archivo. Bof( ) y Eof( ).................................................................................................21 Recno( ) ...................................................................................................................................................21 Reccount( )...............................................................................................................................................22 Set deleted ...............................................................................................................................................22 Agregar un registro.......................................................................................................................................22 Append blank ...........................................................................................................................................22 Opciones poco útiles del menú Tabla...........................................................................................................22 Copy structure..........................................................................................................................................23 Copy to.....................................................................................................................................................23 Modify file .................................................................................................................................................24 Diálogo Exportar...........................................................................................................................................24 Agregado masivo de registros: diálogo Añadir desde...................................................................................24 Append from.............................................................................................................................................25 Diálogo Importar ...........................................................................................................................................25 Marcado de registros a eliminar....................................................................................................................25 Delete.......................................................................................................................................................26 Deleted( ) .................................................................................................................................................26 Desmarcado de registros a eliminar .............................................................................................................26 Recall .......................................................................................................................................................26 Eliminación de registros marcados ...............................................................................................................26 Pack .........................................................................................................................................................26 Cambio de los datos de uno o varios campos ..............................................................................................27 Replace ....................................................................................................................................................27 Vinculación de particiones ............................................................................................................................27 Regeneración de índices ..............................................................................................................................27 Reindex ....................................................................................................................................................27 Modificación de la estructura de una tabla ...................................................................................................28 Modify structure........................................................................................................................................28 Campos de tipo fecha, fecha–hora y lógico..................................................................................................28 Campos de tipo memo..................................................................................................................................29 Diálogo Editar propiedades ..........................................................................................................................30 List, Display, Set heading.........................................................................................................................30 Set memowidth.........................................................................................................................................31 Índices...............................................................................................................................................................32 Tipos de índices............................................................................................................................................32 Expresiones complejas de índice. Str( ), Dtos( ) y Ttoc( ).............................................................................33 Aplicación de índices ....................................................................................................................................35 Dtoc( ) ......................................................................................................................................................36 Iif( ) ...........................................................................................................................................................36 Bases de datos .................................................................................................................................................37 Creación de una base de datos....................................................................................................................37 Create database.......................................................................................................................................37 Barra de herramientas Diseñador de bases de datos...................................................................................37 Menús contextuales del diseñador de bases de datos .................................................................................38 Opciones de menú en el diseñador de bases de datos ................................................................................38 Close databases.......................................................................................................................................38 Apertura de una base de datos.....................................................................................................................39 Open database.........................................................................................................................................39 Modificación de una base de datos ..............................................................................................................39 Modify database .......................................................................................................................................39 Propiedades exclusivas de las tablas base ..................................................................................................39 —2— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 Áreas de trabajo. In, Order y Noupdate de Use. Select ...........................................................................41 Relaciones e Integridad referencial...................................................................................................................43 Relaciones transitorias .................................................................................................................................43 Ampliación de una relación...........................................................................................................................44 Nombre.........................................................................................................................................................44 Relaciones permanentes ..............................................................................................................................45 Alumnos........................................................................................................................................................45 Exámenes.....................................................................................................................................................45 Campos ........................................................................................................................................................45 Campos ........................................................................................................................................................45 Indices ..........................................................................................................................................................45 Indices ..........................................................................................................................................................45 Integridad referencial ....................................................................................................................................46 Sesión de datos ................................................................................................................................................47 —3— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 Introducción Esta pequeña obra pretende dar conceptos y ejercicios para que el lector aprenda a diseñar tablas y bases de datos. Como casi todo lo que se trata se puede conseguir mediante menús y barras de herramientas, he creído conveniente exponer también los comandos y las funciones de VFP que logran lo mismo. Esto no es imprescindible, salvo que el lector se interese en programación. Por ello, se exponen estos temas en letra más pequeña. Antes de entrar en tema, veamos algunas cosas útiles, que usaremos con frecuencia. Comando ? En la ventana que dice Comandos, escriba los siguientes ejemplos y termine apretando ENTER. Las líneas verticales en el margen izquierdo indican que debe probar en la ventana COMANDOS. ? 4 + 35 ? 25 * 127 ? date( ) ? date( ) + 10 ?5=3+6 ? "Hoy es", date( ) ? "Hoy es " + cdow(date( )) El comando ? evalúa una o varias expresiones y muestra el resultado en la ventana principal (la gran superficie blanca, donde yace la ventana COMANDOS). Si la ventana COMANDOS no está visible, la puede activar con VENTANA – VENTANA COMANDOS, es decir, dar clic en el menú VENTANA y dar otro clic en la opción VENTANA COMANDOS. También puede usar la combinación de teclas CTRL + F2. Barra de estado La barra de estado es una banda de color gris que se puede hacer visible al pie de la ventana principal de VFP. Esto se consigue con HERRAMIENTAS – OPCIONES – VER – BARRA DE ESTADO. También se puede activar o desactivar emitiendo respectivamente los siguientes comandos: set status bar on set status bar off La barra de estado reduce el espacio de pantalla disponible para ver datos, diseñar formularios, diseñar informes, etc., por lo que conviene ocultarla. En algunas ocasiones es útil que esté visible. Resultado de comandos Hay comandos que escriben resultados en la ventana principal, expresados como números, letras, etc. Esto a veces puede ser útil, pero otras veces molesta. Para activar o desactivar esta característica, válgase de HERRAMIENTAS – OPCIONES – VER – RESULTADO DEL COMANDO. También puede lograr lo mismo, respectivamente, con SET TALK ON y SET TALK OFF. Pruebe: set talk on a = 250 * 32 set talk off b = 250 * 32 Cuando activó mostrar el resultado de los comandos, el comando a = 250 * 32 calculó el producto 250 x 32 y lo almacenó en una porción de la memoria, llamada variable de memoria, a la que identificamos con el nombre a; pero también mostró el resultado 8000 en la pantalla principal. Cuando desactivó mostrar el resultado de los comandos, el comando b = 250 * 32 calculó el resultado y lo almacenó en otra variable de memoria, a la que identificamos con el nombre b; pero no mostró el resultado en la pantalla principal. El estado de SET TALK no afecta al comando ?, porque su propósito es evaluar expresiones y mostrar el resultado en la ventana principal. —4— Tablas Una tabla es el archivo contenedor de datos más común en VFP, cuyo nombre es cualquiera y cuya extensión es DBF. Una tabla está formada por registros y los registros están formados por campos. Todos los registros tienen los mismos campos. Si en una tabla se guardan datos de alumnos, cada alumno tendrá su propio registro. En los campos de un registro particular se guardan los datos de un alumno particular: en un campo la matrícula, en otro el nombre, en otro el domicilio, etc. La igualdad de forma de los registros en cuanto a que todos tienen los mismos campos, es lo que constituye la estructura de un registro genérico. Los registros se guardan físicamente en disco uno tras otro, como indica la siguiente figura. Registro Registro Registro Siguen más Matrícula Nombre Domicilio Etc. Matrícula Nombre Domicilio Etc. Matrícula Nombre Domicilio Etc. registros… Si dispusiéramos un registro bajo otro, cada uno ocuparía una fila y los campos formarían columnas: Matrícula Nombre Domicilio Etc. Siguen más registros… También podríamos disponer los registros de esta ofra forma: Matrícula Nombre Domicilio Etc. Matrícula Nombre Domicilio Etc Matrícula Nombre Domicilio Etc. Siguen más registros… Estas disposiciones son comunes para examinar una tabla, llamadas modos examinar y añadir, respectivamente. Son dos formas de ver el contenido de la tabla, porque la distribución física es la de la primera figura. Tipos de tablas Hay dos variedades de tablas: tablas libres y tablas de base de datos. Las primeras tienen su estructura completamente definida en sí mismas, consistente en las características obligatorias. Pueden ser ordenadas por tres de los cuatro tipos de índices: normal, único y candidato. Tecnológicamente, son las más antiguas. Las tablas de base de datos pueden tener algunas definiciones adicionales en la base de datos donde están incluidas. Aunque no es obligatorio usarlas, las posibilidades que brindan estas definiciones brindan mayor seguridad y evitan errores. Entre estas posibilidades, las más comunes son reglas y mensajes de validación de campos y registros; formatos y máscaras de entrada de cada campo; valores predeterminados de campos al agregar nuevos registros. Las tablas de base de datos pueden ser ordenadas por los cuatro tipo de índices existentes: normal, único, candidato y principal. Cuando se elimina una tabla libre, se la elimina físicamente de la carpeta donde está guardada. Cuando se elimina una tabla de base de datos, hay que elegir entre eliminarla físicamente de la carpeta o eliminarla de la base de datos. Si se elige esta última posibilidad, VFP advierte que se perderán las características adicionales guardadas en la base de datos, además de las relaciones permanentes donde interviene la tabla, si las hay. Confirmada la acción, la tabla se transforma en tabla libre. Si la tabla contiene índice principal, éste se transforma en candidato. –5– Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 Creación de una tabla: Diseñador de tablas Para crear una tabla, primero hay que crear su estructura, es decir, definir qué campos va a contener, y luego agregarle registros. Una forma de crear una estructura, entre otras, es con ARCHIVO – NUEVO. Esto presenta el diálogo NUEVO. En TIPO DE ARCHIVO, elija TABLA. Tiene dos opciones para crearla: NUEVO ARCHIVO y ASISTENTE. La opción NUEVO presenta el diálogo CREAR, donde debe seleccionar una carpeta (VFP le sugiere una) y escribir un nombre para la nueva tabla. Puede elegir cualquier carpeta, como MIS DOCUMENTOS, que suele depender de la unidad C; pero es mejor que use su carpeta de trabajo, SI1. Escriba Alumnos como nombre de la tabla. Pulse el botón GUARDAR. Se presenta el DISEÑADOR DE TABLAS. En la barra de título aparece el nombre de la tabla a crear. El diseñador tiene las fichas CAMPOS, ÍNDICES y TABLA. En la ficha CAMPOS hay seis columnas: NOMBRE, TIPO, ANCHO, DECIMAL, ÍNDICE y NULL. Debajo de NOMBRE hay un rectángulo. Escriba mu, abreviatura de matrícula universitaria. Avance a la columna TIPO, pulsando TAB o dándole clic. Elija Numérico en la lista desplegable. Avance a ANCHO e introduzca el número 6, ya que es el máximo de posiciones que podrá tener en cifras nuestra matrícula. En DECIMAL introduzca 0, pues la matrícula no tiene decimales. En ÍNDICE abra la lista y elija Ascendente. Esto va a crear un índice por este campo, en forma ascendente. Complete la definición de la estructura, para que finalmente se vea así: Nombre mu nombre domicilio sexo Tipo Ancho Decimal Índice Null Numérico 6 0 ↑ Carácter 30 Carácter 30 Carácter 1 Ha definido cuatro campos llamados MU, NOMBRE, DOMICILIO y SEXO. Estos nombres pueden tener hasta 10 posiciones, formados por letras, números y algunos caracteres especiales, como el de subrayado. Deben empezar con una letra. No pueden contener espacios. Cada campo debe tener un tipo. MU es de tipo numérico, lo que significa que sólo podremos ingresar números a este campo. Como tiene un ancho o tamaño de 6 posiciones, los valores posibles irán de –99.999 a 999.999. No podremos ingresar decimales, porque hemos dicho que tiene 0 posiciones decimales. Si hubiéramos dicho que tiene 2 decimales, ¿cuántas posiciones enteras habría? Se podría pensar que si el número tiene en total 6 posiciones, 2 de las cuales son decimales, habría 4 posiciones enteras. No es así, porque VFP guarda el punto decimal, con lo cual 2 decimales más el punto decimal son 3 posiciones, por lo que quedarían 6 – 3 = 3 posiciones enteras. ¿Por qué decimos punto y no coma decimal? Porque en Estados Unidos, donde se ha inventado VFP, se usa el punto como separador decimal, no la coma. Los demás campos son de tipo carácter: su contenido será letras, números y otros símbolos del teclado. Para NOMBRE y DOMICILIO el ancho es una estimación. Si uno de estos campos resulta pequeño para un dato específico, deberemos abreviar o truncar el dato. Para SEXO usaremos un código, F para femenino y M para masculino, por lo que con una posición es suficiente. Los campos de caracteres no tienen decimales. Hemos creado un índice para el campo MU. Un índice, que debe tener un nombre, establece cómo ordenar los registros de acuerdo a un criterio, llamado expresión de índice. Un índice no modifica el orden con que están guardados los registros, pero, cuando se activa, hace que se ordenen virtualmente por un criterio, por ejemplo por nombre o por matrícula. Una tabla puede tener varios índices distintos, por distintos criterios, que se guardan todos en un único archivo de índices. Seleccione la ficha ÍNDICES y verá que la primera fila dice que su NOMBRE es Mu, su TIPO es Normal y su EXPRESIÓN es Mu. En la columna ORDEN se ve una flecha ascendente, indicando que el orden es en tal sentido. La tabla, entonces, va a tener un índice MU que aceptará valores repetidos, si así los ingresamos, en el campo MU. Esto es lo que permiten los índices normales. Obviamente, la matrícula no debería repetirse nunca, porque es el identificador de cada alumno. Hay otros tipos de índice que impiden esta repetición errónea. Vuelva a la ficha CAMPOS. Vea a la izquierda de cada fila un rectángulo gris. Tiene dos propósitos. El primero es indicar el campo activo, es decir el campo que está definiendo o modificando, lo que se indica con el sím—6— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 bolo . El segundo propósito es arrastrar el campo activo hacia arriba o abajo, para cambiarlo de posición. Si vuelve a la ficha ÍNDICES, verá a la izquierda de la única fila, por ahora, un rectángulo igual, que tiene el mismo cometido. Vaya a la ficha TABLA. No hay campos que pueda llenar. Solamente da información inmodificable. Indica que hay 0 registros, 4 campos y que la longitud de cada registro es de 68 posiciones. Si sumamos lo que mide cada campo, es decir 6 + 30 + 30 + 1 = 67. El espacio excedente en cada registro sirve para indicar si se lo quiere destruir, como veremos. Por ahora pulse el botón ACEPTAR. Un mensaje le pregunta si quiere ingresar registros. ¿Qué significa esto? Hemos dicho que todos los registros de una tabla tienen la misma estructura. Al crear la tabla, definió la estructura que van a tener los registros, mediante sus campos componentes con sus características, y posiblemente índices. Pero no ingresó registros con datos específicos. Las tablas tienen dos partes: una es la definición estructural, que se ubica al comienzo del archivo; la otra son los registros con datos particulares. Las tablas deben tener al menos la primera parte; pero pueden carecer de la segunda. Si ese es el caso, tendríamos tablas vacías, donde en cualquier momento puede agregar registros con datos en sus campos. La pregunta que hace VFP es si quiere dejar la tabla vacía o empezar a introducir registros. Dígale que sí. Create El comando para crear una tabla es CREATE, seguido por el nombre de la tabla. Éste puede ir precedido por el camino de carpetas para llegar a la carpeta que va a contener la tabla. Ejemplos: create alumnos create c:\si1\alumnos create c:\windows\temp\pagos Tipos de campos Cada campo componente de la estructura de tabla debe tener un tipo. No sólo los campos, sino los demás datos de VFP, como variables y constantes, necesariamente son de algún tipo. El tipo establece los datos permitidos y el intervalo de valores entre los cuales puede variar. Los campos contemplan más posibilidades que los otros datos en cuanto a tipo. Los tipos de campos más sencillos son los siguientes. Tipo Carácter Numérico Fecha Fecha Hora Lógico Memo Contenido Texto Reales Fechas Fecha y hora Valores lógicos Texto Tamaño Hasta 254 Hasta 20 8 8 1 4 Note que los tamaños de los campos de caracteres y numéricos deben definirse al crear o modificar la estructura de la tabla. Los demás campos son de longitud fija. Cuando se define un campo numérico, además, hay que indicar cuántos decimales posee. VFP no usa coma, sino punto, para separar la porción entera de la porción decimal de un número. Cuando llevan decimales, el punto también se cuenta en el tamaño, porque ocupa una posición. Por ejemplo, si un campo numérico tiene 10 posiciones con 2 decimales, hay que contar el punto y las posiciones decimales, de modo que las posiciones enteras son 7. Dejaremos los campos memo para más adelante, porque son muy particulares. Ventana Examinar Luego de contestar que sí quiere ingresar registros, se presenta la ventana EXAMINAR. Aparecen los nombres de los campos MU, NOMBRE, DOMICILIO, SEXO, uno bajo el otro. Debajo hay una línea horizontal, que se repite regularmente formando bandas, pero vacías. Cada banda representa un registro. El punto de inserción está en MU. Ingrese 5201, la primera matrícula del ejemplo. Si observó, ahora aparece en la segunda banda otra serie de nombres de campos, uno bajo el otro. Complete los restantes datos del primer registro, de modo que se vea así: —7— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 Mu: Nombre: Domicilio: Sexo: 5201 Cortés, Luis Jujuy 8543 M Para avanzar de campo en campo, si el contenido no lo llena completamente, puede usar TAB o ENTER. Al completar el último campo del primer registro, el punto de inserción pasa al campo MU del siguiente registro. Apenas comience a llenarlo, aparecen los nombres de los campos en la tercera banda. Los datos del segundo registro son: Mu: Nombre: Domicilio: Sexo: 1702 Ávila, María Mitre 7047 F Al terminar el segundo registro, el punto de inserción salta al campo MU del tercero. No llene más. Si el último registro está vacío y sale con el botón de cierre o con ESC, ese registro no se grabará en el archivo. Advierta que, si estuviera en un campo que llena o modifica y pulsa ESC, ese campo no será grabado con el nuevo contenido. Por ello debe salir del campo SEXO del segundo registro, confirmando su contenido, para que pueda grabarse. No es necesario pasar a un registro vacío: también podría volver a un campo llenado previamente, del registro actual o de cualquier otro previo. Salga con ESC. Apertura de la ventana Examinar Usted acaba de cerrar la ventana EXAMINAR. Una forma de abrirla es cuando termina de crear la estructura de una tabla y decide ingresar registros. Si la tabla que desea examinar ya tiene registros, el procedimiento anterior no se puede aplicar. Pero hay varias otras formas de abrirla. Como requisito previo, se necesita que la tabla esté abierta y seleccionada. La tabla ALUMNOS está abierta, porque no ha hecho nada para cerrarla. También está seleccionada, porque es la única que está abierta. Seleccionar una tabla tiene sentido cuando hay varias tablas abiertas a la vez, una sola de las cuales puede estar seleccionada. Otra forma de abrir la ventana EXAMINAR para la tabla ALUMNOS es con VER – EXAMINAR "ALUMNOS…". Hágalo. Ahora vuelve a ver el contenido de la tabla. Pero hay una presentación distinta: al ingresar registros luego de definir la estructura de la tabla, los campos aparecían uno bajo otro y los registros se veían separados por bandas. Ahora los campos se ven uno junto a otro, formando columnas, y los registros se ven como filas. Es una diferencia de presentación, pero los datos son los mismos. La ventana EXAMINAR es como las demás ventanas de Windows: se puede movea, maximizar o minimizar, cambiar el alto o el ancho, etc. Cuando tiene varios registros en una tabla que visualiza en la ventana EXAMINAR, puede “navegar” por la tabla, de varias maneras: – Avanzar o retroceder de a un registro, con las teclas de flechas verticales. El registro actual se indica con el símbolo ►en la primera columna de la ventana EXAMINAR. Con el mouse, puede desplazar registros dando clic en los extremos de la barra de desplazamiento vertical. Para cambiar de registro, dé clic en cualquier campo del registro que quiere seleccionar. – Avanzar o retroceder los registros que caben en la ventana, con AVPÁG y REPÁG. Con el mouse, el equivalente es dar clic dentro de la barra de desplazamiento vertical, arriba o debajo del deslizador. Para movimientos mayores, arrastre el deslizador hacia arriba o abajo. – Ir al extremo izquierdo o derecho de un campo, con INICIO y FIN. – Avanzar o retroceder por el interior de un campo, con las flechas horizontales. El campo actual se remarca con un recuadro. – Avanzar al siguiente campo de la derecha, con TAB o ENTER. Retroceder al siguiente campo de la izquierda con CTRL + TAB. Con el mouse, se da clic en el campo que se desea en el registro seleccionado. —8— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 – Ir a un registro específico, buscar el primero que tenga un contenido dado, etc., usando otros comandos o alguna opción de menú. La ventana EXAMINAR permite modificar los datos de la tabla, no su estructura. Usted puede agregar nuevos registros (altas), eliminar registros existentes (bajas) y modificar el contenido de los campos de registros existentes (cambios). Si en las dimensiones actuales de la ventana EXAMINAR no entran todos los campos, porque son muchos o muy grandes, se muestran los que caben. Pero, al llegar a un campo extremo, los movimientos laterales incorporan nuevos campos a medida que desaparecen los que antes estaban visibles. Con el mouse, se puede usar la barra de desplazamiento horizontal. Con la tabla ALUMNOS, que tiene pocos campos y de poco tamaño, no podrá ver este efecto, salvo que la haga estrecha. Si fuera necesario, la ventana EXAMINAR tendrá dos barras de desplazamiento, una vertical y otra horizontal. Salga con ESC. Browse El comando para abrir la ventana EXAMINAR es BROWSE. Es uno de los comandos para tablas más poderosos. Muchas de las funciones de este comando se logran mediante los menús VER y TABLA. También se logran mediante el objeto GRID en un formulario. No obstante, el comando o sus posibilidades están presente tras ellos. browse Usted puede hacer que BROWSE impida agregar registros FY) ni deje marcarlos para destruir (cláusula NODELETE). (cláusula NOAPPEND), no admita cambiar los existentes (cláusula NOMODI- browse noappend nomodify nodelete Por defecto, BROWSE trabaja con todos los campos, pero permite hacerlo con un subconjunto de ellos, usando una lista de campos, introducidos por la cláusula FIELDS. Los campos aparecerán en el orden que ocupan en la lista. browse fields mu, nombre nomodify En la lista de campos se puede incluir un campo calculado. Un campo calculado no existe en la tabla, pero se infiere de un campo real, mediante alguna expresión. En BROWSE, un campo calculado debe tomar la forma de un nombre seguido por = y la expresión. Por ejemplo, si quiere incluir el doble de la matrícula, aunque no tenga sentido, debe hacer: browse fields nombre, doble = mu * 2 noappend El nombre que precede a = se usa como título de la columna. En cada registro, el valor del campo calculado es la expresión resuelta. Los campos calculados no pueden ser modificados, porque no habría donde guardar los cambios en la estructura de la tabla. Si usted quiere modificar solamente un campo, debe indicarlo en la cláusula FREEZE: browse freeze mu browse fields mu, nombre freeze mu nodelete noappend Cierre de tablas. Use, Close, Clear, Quit Hay varias formas de cerrar tablas abiertas. No se puede hacer con el menú ARCHIVO, salvo eligiendo SALIR. Por ahora veamos los siguientes comandos, que puede emitir en la ventana COMANDOS: USE, sin nada adicional, cierra la tabla seleccionada y sus archivos dependientes. CLOSE TABLES ALL cierra todas las tablas abiertas y sus archivos dependientes. CLOSE ALL cierra todos los archivos y diseñadores abiertos. CLEAR ALL cierra todos los archivos y diseñadores abiertos y elimina las variables del usuario. QUIT cierra todo lo que está abierto y sale de VFP. Equivale a ARCHIVO – SALIR. Como aún no conoce muchas de las cosas que se cierran, nos limitemos a los dos primeros comandos. Los archivos dependientes de una tabla son el archivo de índices y el archivo de campos memo. Dependientes significa que son abiertos automáticamente al abrir la tabla de la que dependen. Como tenemos una sola tabla hasta ahora, cerrar todas las tablas la incluirá, por lo que USE y CLOSE TABLES ALL, en este caso, producen lo mismo. Si hubiera varias tablas abiertas, USE cerraría sólo la tabla seleccionada, dejando las demás abiertas; CLOSE TABLES ALL cerraría todas las tablas. Apertura de tablas Si debe interrumpir su trabajo en cualquier momento, para seguir practicando con una tabla debe abrirla. Hay —9— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 varias formas de hacerlo. Puede usar ARCHIVO – ABRIR, que trae el diálogo ABRIR. En TIPO DE ARCHIVO elija Tabla (*.dbf). Esto lista las tablas existentes en la carpeta que aparece en BUSCAR EN. Esta carpeta, ahora, es la predeterminada, que puede cambiar por otra si lo necesita en alguna oportunidad. Elija la tabla deseada en el listado o escriba su nombre en NOMBRE DE ARCHIVO y pulse ACEPTAR. Las tablas, por defecto, tienen la extensión DBF, de modo que, si no la escribe, VFP la supone escrita. Use Otra forma de abrir una tabla es el comando USE seguido por el nombre del archivo a abrir. Con la barra de estado activa, emita close tables all set status bar on use alumnos Si el directorio predeterminado no fuera SI1, podría emitir USE C:\SI1\ALUMNOS. Ahora aparece en la barra de estado el nombre de la tabla, ALUMNOS, el número de registro del registro actual, 1, y el total de registros. Modos Editar y Examinar La diferencia entre ver los campos uno bajo otro o uno junto a otro se maneja en la ventana EXAMINAR. Ábrala. Despliegue el menú VER. Hay dos opciones mutuamente excluyentes: EXAMINAR y EDITAR. Pruebe uno y otro. Elija el modo que le resulte más cómodo o conveniente. Modo Añadir Ahora no puede agregar registros a la tabla, como sucedió cuando terminó de crearla. ¿Se podrá volver a esa modalidad? Sí. Elija VER – MODO AÑADIR. Ahora el punto de inserción salta al final, a un registro vacío, de modo que pueda llenarlo. Si quiere bajar a otro registro nuevo, no es posible. Pero apenas comienza a llenar el registro vacío, se habilitará un nuevo registro vacío. Siempre habrá disponible un solo registro vacío, ya que el que está llenando ya no está vacío. Si decide subir a registros ya llenos, el modo añadir no se cancela. Permanecerá así mientras no cierre la ventana EXAMINAR. Si luego de retroceder a registros existentes quiere seguir agregando registros nuevos, vaya al último y baje uno. Agregue ahora los siguientes registros. Puede agregar más, si desea. Mu 542 2388 257 1377 645 2406 4315 3161 Nombre Suárez, Jorge Ruiz, Marina Oro, Eugenio Toro, Laura Vidal, Daniel Alba, Alberto Castro, Ana Gil, Raúl Domicilio Sexo Salta 101 M Belgrano 1128 F Roca 2928 M Paso 339 F La Rioja 2246 M Córdoba 175 M Solís 4214 F San Martín 5928 M Marcadores de registro Si tiene abierta la ventana EXAMINAR, ciérrela y vuelva a abrirla, para cancelar el modo AÑADIR. Observe que a la izquierda hay una columna de cuadritos en gris, uno de los cuales tiene un símbolo ►. Esta marca indica cuál es el registro actual, es decir, el seleccionado. Si cambia de registro, sea dando clic en otro o moviéndose con las teclas verticales, la marca cambia de sitio. Marcadores de destrucción La columna a la derecha inmediata de los marcadores de registro es un conjunto de cuadritos en blanco. Cada uno sirve para marcar y desmarcar el respectivo registro para eliminarlo. Marcarlo no lo elimina, sino que lo prepara para ello. Antes de eliminarlo para siempre, lo puede rescatar, desmarcándolo. Una forma de poner o quitar la marca es dar clic en el cuadrito del registro que quiere elimnar. Otra forma es usar CTRL + T, que pone o saca la marca. Hay otras formas. En la tabla puede haber varios registros marcados, tantos como desee eliminar. —10— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 Partidor Al pie de la columna marcadores de registro hay un ▌. Si pone el mouse sobre ella, el puntero toma la forma . Si con este puntero arrastra horizontalmente y suelta, la ventana EXAMINAR se divide en dos particiones. La partición activa es donde está el punto de inserción. Una partición se puede ver en modo editar y la otra en modo examinar, activando la partición y usando el menú VER. Pruébelo. Si avanza o retrocede por los registros en una partición, el movimiento se refleja en la otra. Las particiones, entonces, están vinculadas. Hay una forma de desvincularlas, de modo que se avance por una pero no por la otra. Sin embargo, si no ha agregado muchos registros a la tabla, no podrá ver esto ahora, salvo reducir el alto de la ventana EXAMINAR. Para volver a una sola partición, tome el partidor y arrástrelo a su lugar original. Tamaño y movimiento de la ventana Examinar Como cualquier ventana, EXAMINAR se puede mover, si no está maximizada, tomándola de la barra de título y arrastrándola. Para cambiar su tamaño, siempre que no esté maximizada ni minimizada, se toma cualquiera de sus bordes o vértices y se lo arrastra. Líneas de cuadrícula VER – LÍNEAS DE CUADRÍCULA se puede activar o desactivar, mostrando u ocultando las líneas horizontales y verticales entre campos y registros. Ancho y posición de las columnas En modo EXAMINAR, los nombres de los campos aparecen como encabezados. Si coloca el puntero en la línea vertical donde termina el encabezado de un campo, toma la forma |. Si con ese puntero arrastra lateralmente y suelta, puede variar el ancho de la columna. Esto afecta a la ventana EXAMINAR, no al ancho con que está definido el campo en la estructura de la tabla. En modo EXAMINAR, si lleva el puntero al interior de un encabezado, toma la forma ª. Si con ese puntero arrastra lateralmente, puede cambiar la ubicación de la columna con respecto a las demás. En modo EDITAR, si da clic y sostiene en el nombre de un campo, se seleccionan todos los que tienen igual nombre en los demás registros visibles. Esto le permite variar por arrastre su posición con respecto a los otros campos. Los cambios descriptos afectan a la ventana EXAMINAR, no a la posición del campo en la estructura de la tabla. Alto de encabezados y renglones En modo EXAMINAR, a la izquierda del primer encabezado, sobre el primer marcador de registro y el primer marcador de destrucción, hay un rectángulo gris sin nombre. Si coloca el puntero en la base de este rectángulo, toma la forma . Si con ese puntero arrastra verticalmente, puede variar la altura de todos los encabezados a la vez. Si coloca el puntero en la base del primer marcador de registro o del primer marcador de destrucción, toma la forma . Si con ese puntero arrastra verticalmente, puede variar la altura de todos los registros a la vez. Menú Edición Estando en la ventana EXAMINAR, el menú EDICIÓN permite seleccionar todo, copiar, cortar y pegar, operaciones que ya conoce, pero reducidas al campo actual. Puede seleccionar una porción del campo, arrastrando el mouse o usando MAYÚSC + flechas horizontales. Con INICIO y FIN puede ir al comienzo o fin del campo, esté o no seleccionado todo o parte de su contenido. Si modifica el contenido de un campo y quiere volver a su valor original, use EDICIÓN – DESHACER. EDICIÓN – BUSCAR presenta un diálogo para introducir el texto a buscar. Note que busca registro a registro, campo a campo, considerando que la tabla es un gran texto. Esto es útil en ocasiones; pero se puede buscar exclusivamente dentro de un campo, forma más usual y poderosa, para lo que se necesita otra opción. EDICIÓN – BUSCAR SIGUIENTE continúa buscando la siguiente aparición del texto deseado. —11— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 Las operaciones de edición se pueden lograr con combinaciones de teclas, sin abrir el menú EDICIÓN. Estas combinaciones, que aparecen junto a cada opción del menú, son: CTRL + A CTRL + C CTRL + F CTRL + G Seleccionar todo Copiar Buscar Buscar siguiente CTRL + R CTRL + V CTRL + X CTRL + Z Rehacer Pegar Cortar Deshacer Set keycomp Ya habrá notado que al cambiar de campo, aquél al que entra se selecciona completamente. Este comportamiento se llama "seleccionar al entrar", lo cual permite reemplazar todo el contenido por otro, sin tener que borrarlo posición a posición. Es el modo propio de Windows. En modo DOS, este efecto no se produce, sino que el punto de inserción se coloca al comienzo del campo. Para cambiar de modo se usan los comandos SET KEYCOMP TO WINDOWS y SET KEYCOMP TO DOS. Estos comandos no están en ningún menú, de modo que hay que emitirlos en la ventana COMANDOS. Estando en la ventana EXAMINAR, active la ventana COMANDOS con VENTANA – VENTANA COMANDOS o con CTRL + F2. Emita set keycomp to dos Vuelva a la ventana EXAMINAR, dándole clic, eligiéndola por su nombre en el menú VENTANA o pulsando CTRL + F1. Ahora cambie de campos y verá que no hay más selección al entrar. Para volver a modo Windows, active la ventana COMANDOS y emita set keycomp to windows Active la ventana EXAMINAR y cambie de campos. Fuente Cada vez que se abre la ventana EXAMINAR, aparece el menú TABLA en la barra de menús. Desaparece cuando se cierra esa ventana. La segunda opción de este menú, FUENTE, trae el diálogo de igual nombre, que permite cambiar la fuente, el estilo y el tamaño que se aplicará a toda la ventana. Filtro de registros La primera opción del menú TABLA, PROPIEDADES, presenta el diálogo PROPIEDADES DEL ÁREA DE TRABAJO, donde hay varias opciones. La opción FILTRO DE DATOS tiene un cuadro de texto para ingresar una expresión y un botón con tres puntos, que lleva al diálogo GENERADOR DE EXPRESIONES. Si sabe escribir la expresión, puede hacerlo directamente en el cuadro de texto. Si no lo sabe, o si quiere asegurarse de su corrección, dé clic en el botón de tres puntos. La expresión a escribir será, por ejemplo, mu < 5000. Esto actuará como un filtro de los registros: aquéllos cuyo campo MU tenga un valor menor a 5000 pasarán el filtro; aquellos cuyo campo MU tenga un valor igual o mayor a 5000 quedarán retenidos por el filtro. Los que pasan la prueba serán los únicos que muestre la ventana EXAMINAR. Los demás no aparecerán. Este efecto durará mientras no quite el filtro o lo cambie por otro. Elija el botón …. En el GENERADOR DE EXPRESIONES, abajo, a la izquierda, hay una lista desplegable que indica el nombre de la tabla, ALUMNOS. Si abre la lista, por ahora no hay más que esa tabla. Arriba de esta lista hay una lista desplegada con los campos de la tabla, donde aparecen sus nombres, tipos, anchos y posiciones decimales. Dé doble clic en el campo MU. Esto provoca que en el cuadro grande superior, llamado expresión SET Filter: <expL>, aparezca escrito Mu. La abreviatura <expL> indica que se requiere una expresión lógica, que se evalúe como verdadera o falsa. Luego abra la lista de funciones LÓGICAS y elija el operador <. En el cuadro superior ahora se ve Mu < o Alumnos.Mu <, es lo mismo. Complete la expresión escribiendo 5000, ya que no puede hacerlo de otra forma. Si prefiere, puede escribir la expresión Mu < 5000 directamente en el cuadro superior. Puede dejar espacios antes y después del operador. Para saber si la expresión es correcta, pulse el botón COMPROBAR. Esto le dirá si está bien o tiene errores. El mensaje aparece en la barra de estado o en una ventanita, según que tal barra esté o no visible. Si la expresión es válida, pulse ACEPTAR, que lo devuelve al diálogo PROPIEDADES DEL ÁREA DE TRABAJO. En éste, pulse el botón ACEPTAR. VFP vuelve a la ventana EXAMINAR, donde puede comprobar que el filtro está en vigencia. Pruebe nuevos filtros. Por ejemplo, Mu > 5000 o Nombre <= "D". Note que 5000 y "D" no son campos, sino valores literales. El primer ejemplo usa un campo numérico, por lo que debe compararse con una expresión numérica, como en este caso el literal numérico 5000. El segundo, que usa como primer operando un campo —12— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 de caracteres, debe compararse con una expresión de caracteres, como es el literal de caracteres "D". ¿Por qué las comillas en este caso? Para indicar que es un literal de caracteres. Si no las escribiera, VFP interpretaría que es el nombre de otro campo o de una variable. En lugar de comillas, puede usar apóstrofos. El segundo ejemplo filtra los registros cuyos nombres empiecen con las letras A, B, C y D. Los literales numéricos, es decir, los números, no tienen delimitadores, como el 5000 del ejemplo. Los literales de caracteres, es decir, las cadenas, deben usar los delimitadores comillas o apóstrofes, como la "D" del ejemplo. Esto significa que 2150 no es igual a "2150", porque son de distinto tipo. Además de los literales numéricos y de caracteres, hay otros. ¿Cómo sería la expresión para filtrar registros con matrícula entre 1000 y 5000? Puede escribirse Mu >= 1000 and Mu <= 5000. Esta expresión indica filtrar registros cuya matrícula sea mayor o igual a 1000 y a la vez menor o igual a 5000. Between( ) e Inlist( ) Hay funciones que facilitan escribir expresiones complejas como la anterior. Por ejemplo, las funciones BETWEEN( ) e INLIST( ). BETWEEN( ) prueba si el valor de algo está dentro de un intervalo de valores. Usa tres argumentos: el primero es lo que se quiere probar, el segundo el extremo inferior del intervalo y el tercero el extremo superior. ? between(5,1,10) ? between(20,1,10) ? between("F","A","M") antes = date( ) — 10 después = date( ) + 10 ? between(date( ), antes, después) Apelando a BETWEEN( ), la expresión Mu >= 1000 and Mu <= 5000 se puede reemplazar con between(Mu,1000,5000) Si le resulta más claro, puede dejar espacios, como en between (Mu, 1000, 5000) between ( Mu, 1000, 5000 ) En el GENERADOR DE EXPRESIONES, en la lista de funciones lógicas, además de los operadores AND, OR, NOT, <, =, >, etc., hay funciones lógicas, como BETWEEN( ) e INLIST( ). Para listar los registros cuyo campo NOMBRE comience con A, D, F, L y Z, una expresión filtro puede ser: Nombre="A" or nombre="D" or NOMBRE="F" or nomBRE="L" or nombre="Z" Los nombres de los campos pueden escribirse en minúsculas o mayúsculas, porque VFP los reconoce no importa cómo los escriba. Hasta la versión 2.5 de VFP no pasaba lo mismo con los literales "A", "D", etc., porque "A" no era igual a "a" ni "D" a "d", etc. Las versiones posteriores no hacen esa diferencia cuando se usa el operador =. No puede insertar espacios dentro de estos valores, porque "A" es distinto a "•A•", "A••", "•••••••A", etc. (Cada • representa un espacio.) La expresión ejemplificada es bastante larga de escribir. La función INLIST( ) facilita la tarea, logrando el mismo resultado. Tiene como primer argumento lo que se quiere probar, el contenido del campo NOMBRE en el ejemplo. Siguen hasta 24 argumentos que son los valores contra los cuales probar. ? inlist(5,1,5,7,12,15) ? inlist(5,1,10, 20,30) ? inlist("F","A","F","M") La expresión filtro para la tabla, entonces, puede escribirse también de este modo: inlist(nombre,"A","D","F","L","Z") Para volver a ver todos los registros, elimine la expresión filtro en vigencia. Puede borrarla en el cuadro donde está escrita o en el GENERADOR DE EXPRESIONES. Note finalmente que el título FILTRO DE DATOS que aparece en el diálogo PROPIEDADES DEL ÁREA DE TRABAJO es, en realidad, un filtro no de cualquier dato, sino un filtro de registros. Set filter to El comando para filtrar registros es SET FILTER TO. Si no se escribe nada después de TO, se elimina el filtro vigente sobre la tabla seleccionada, ALUMNOS en este caso. Esto no cierra la tabla. Si se la cierra, también se elimina el filtro que pesa sobre ella. Si se escribe una expresión lógica después de TO, se establece un nuevo filtro sobre tal tabla. Pruebe lo siguiente en la ventana COMANDOS —13— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 y active la ventana EXAMINAR luego de cada uno, para ver los efectos: set filter to nombre>="D" set filter to between(nombre,"C","T") set filter to inlist(nombre, "A","C","F","M") set filter to between(mu,1500,3000) set filter to Exactitud en comparaciones de caracteres Si usáramos un filtro de registros como Nombre = "C", veríamos los registros cuyos nombres comienzan con C, como Cortés, Luis. Estrictamente hablando, Cortés, Luis no es igual a C. Es parcialmente igual a partir de la izquierda. En comparaciones de caracteres, es posible usar una igualdad parcial o exigir igualdad total. Esta característica se logra con HERRAMIENTAS – OPCIONES – DATOS – SET EXACT ACTIVADO. Controle que la exactitud está desactivada. Establezca el filtro de registros Nombre = "C". Verá los registros cuyo campo NOMBRE tiene valores que comienzan con C. Active la exactitud y no verá registros. Vuelva a desactivar la exactitud y verá los registros cuyos nombres comienzan con C. Active la exactitud y cambie el filtro por Nombre = "Cortés, Luis". Verá un solo registro. Desactive la exactitud y verá ese mismo registro. Esto quiere decir que la igualdad parcial no se limita al primer carácter de la izquierda, sino hasta donde se acaba el segundo operando. Con la exactitud desactivada, el filtro Nombre = "Cor" dejaría pasar a Corleone, Corona, Cortés, Correa, Coria, etc., si los hubiera. Elimine el filtro. Set exact El comando para activar la exactitud al comparar de caracteres es SET EXACT ON y para desactivarla SET EXACT OFF. Operador == Sin tener en cuenta si la exactitud está activada o no, el operador == exige exactitud total para dar por iguales ambos miembros de la comparación de caracteres, distinguiendo entre mayúsculas y minúsculas. Se lo puede llamar operador exactamente igual. ? "Dos" == "dos" ? "Dos" == "DOS" ? "Dos" == "Dos " ? "Dos" == "Dos" Número de registro y cantidad de registros Active la barra de estado. Aparece en ella el nombre de la tabla seleccionada, ALUMNOS. Hasta ahora está usando esa única tabla, de modo que no podría seleccionar otra. También aparecen dos números, separados por una /. El primero es el número del registro actual y el segundo la cantidad total de registros en la tabla. El número de registro es el orden que se añade un registro a la tabla: el primero tiene número de registro 1; el segundo tiene número de registro 2, etc. Examine la tabla. Dé clic en otro registro. Verá en la barra de estado que cambia el primer número del par. Se debe a que ha cambiado de registro, el cual tiene otro número. El segundo número del par no cambia, porque la cantidad total de registros sigue siendo la misma. Variará cuando agregue nuevos registros o elimine los registros marcados para destruir. Filtro de campos Así como hay filtros para registros, hay filtros para campos. Primero hay que incluir en este tipo de filtro los campos a ver. Cuando el filtro se pone en vigencia, serán los únicos campos que tendrá en cuenta la ventana EXAMINAR y todos los comandos que procesan registros. Cierre la tabla ALUMNOS para eliminar el filtro de registros que pudiera estar vigente. Ábrala y examínela. En TABLA – PROPIEDADES – PROPIEDADES DEL ÁREA DE TRABAJO, el botón FILTRO DE CAMPOS trae el diálogo SELECTOR DE CAMPOS. Diálogo Selector de campos Tiene los siguientes componentes: – TODOS LOS CAMPOS. Es una lista que muestra todos los campos de la tabla, con sus nombres, tipos, an—14— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 chos y decimales. – CAMPOS SELECCIONADOS. Es la lista donde figuran los campos camponentes del filtro. – MOVER. Si selecciona un campo y pulsa este botón, el campo pasa a la lista Campos seleccionados y se ve atenuado en la lista original. El mismo efecto tiene darle doble clic. – TODOS. Mueve todos los campos a la vez a Campos seleccionados. – QUITAR. Devuelve un campo seleccionado a la lista Todos los campos. También puede darle doble clic. – QUITAR TODOS. Devuelve todos los campos seleccionados a la lista Todos los campos. El diálogo sirve para filtrar los campos que queremos ver: los campos seleccionados serán los únicos que mostrará la ventana EXAMINAR. Seleccione el campo NOMBRE. Pulse ACEPTAR para cerrar el diálogo y volver a PROPIEDADES DEL ÁREA DE TRABAJO. En el recuadro PERMITIR ACCESO A, además del botón FILTRO DE CAMPOS, hay dos botones de opción. Active SÓLO LOS CAMPOS ESPECIFICADOS EN EL FILTRO DE CAMPOS, es decir, active el filtro. Pulse ACEPTAR. Está de vuelta en la ventana EXAMINAR, pero se ven todos los campos, no únicamente el filtrado. ¿Hubo un mal funcionamiento? No. El filtro de campos tendrá vigencia en las próximas aperturas de la ventana EXAMINAR. Salga de la ventana actual con ESC o el botón de cierre. Vuelva a examinar la tabla. Ahora sí verá el efecto del filtro. Active ahora el botón TODOS LOS CAMPOS DEL ÁREA DE TRABAJO del recuadro inferior y pulse ACEPTAR. Esto desactiva el filtro. Deberían verse todos los campos, pero sólo se ve el campo filtrado. Para que lo establecido tenga efecto, cierre la ventana EXAMINAR y vuelva a abrirla. Si ahora quiere filtrar los campos NOMBRE y DOMICILIO, repita los pasos para llegar al diálogo SELECTOR DE CAMPOS. El campo NOMBRE ya está seleccionado, lo cual indica que el filtro de campos es aditivo. Que sea aditivo quiere decir que, salvo quitar los campos puestos por un filtro anterior, permanecen. El filtro de campos que afecta a una tabla, esté activo o no, permanece mientras la tabla está abierta. Desaparece cuando se la cierra. Set fields La puesta en vigencia de filtros de campos también se puede lograr mediante los comandos SET FIELDS. Hay varios tipos de ellos. Como son poco usuales, no nos interesa verlos en detalle. Lo que sí conviene recalcar es que un filtro de campos activado no afecta a la ventana EXAMINAR, sino que afecta a la tabla o tablas involucradas. Por ello, cuando se las examina, se ven los campos establecidos por el filtro. List structure y Display structure Estos comandos muestran la estructura de una tabla. Por defecto, la tabla es la que está seleccionada. Pero puede ser otra tabla abierta, si se usa IN seguido por el nombre de la tabla (o su alias). La salida puede ir a impresora o un archivo, para lo que se usan las cláusulas TO PRINTER y TO FILE. Para suprimir la salida a pantalla se usa NOCONSOLE. Para cada campo, el listado da nombre, tipo, ancho y decimales. Si hay índices cuyos nombres y expresiones sean iguales a los nombres de campo, junto a éstos se indica si son ascendentes o descendentes. Si está en vigencia un filtro de campos, aparece > junto a cada campo del filtro. Se indica el número total de registros y la fecha de la última actualización. Si la tabla tiene campos memo, se muestra el ancho con que se verá su contenido. (Luego veremos qué son campos memo.) Se da el tamaño del registro. use alumnos display structure list structure close tables all List status y Display status Estos comandos muestra el entorno de VFP. La salida va a la ventana principal. El despliegue puede ir a impresora, con TO o a un archivo, con TO FILE. NOCONSOLE para suprime la salida por pantalla. La información que brindan es muy útil y sirve para muchas comprobaciones. Sin agotar todos los ítemes, mencionaremos: PRINTER, Tablas abiertas Directorio predeterminado Relaciones vigentes Área de trabajo seleccionada Ruta de acceso Alias de tablas Configuración de márgenes Expresiones de índices —15— Archivos memo activos Destino de impresora Índices activos Valores de los comandos set Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 Índice principal Formato de fecha actual Página de códigos actual Tipo de procesador Archivos CDX abiertos Macros de teclado use alumnos display status list status close tables all Orden del índice Abra y examine la tabla ALUMNOS. TABLA – PROPIEDADES trae el diálogo PROPIEDADES DEL ÁREA DE TRABAJO. La lista ORDEN DEL ÍNDICE dice < sin orden >. Esto indica que no se ha activado ningún índice. Dado que al crear la estructura de la tabla definió el índice MU, para ponerlo en vigencia despliegue la lista y elíjalo. No hay más índices porque no creamos más. Pulse ACEPTAR. Observe que los registros se ven ahora ordenados en forma ascendente por el campo MU. Muévase por los registros. Se va de uno a otro como si hubieran sido grabados en ese orden, lo cual no es cierto. Ahora desactive el índice, eligiendo < sin orden >. Los registros se ven en el orden real de grabación, tal cual están dispuestos físicamente en el archivo. Set order to El comando para activar o desactivar índices es SET ORDER TO. Si sigue el nombre de un índice, es ése el que se activa. Si no se coloca nada, se desactiva el índice actual y se vuelve al orden de grabación. set order to mu browse Los registros están ordenados por matrícula. set order to browse Ahora los registros no están ordenados. Si cambia de índice con la ventana EXAMINAR abierta, el efecto se aprecia inmediatamente en ella. Sin embargo, no es necesario que esté abierta para emitir SET ORDER TO, dado que este comando afecta a la tabla, no a la ventana. Cree otro índice normal por el campo NOMBRE. Antes de ello, si está trabajando en red, para modificar la estructura de una tabla debe abrirla en modo exclusivo. Esto se logra con ARCHIVO – ABRIR, seleccionar la tabla ALUMNOS en el diálogo ABRIR, como ya sabe, pero tildando EXCLUSIVO. Otra forma es emitir el comando USE ALUMNOS EXCLUSIVE. También podría emitir el comando SET EXCLUSIVE ON, que establece abrir de ahora en adelante todas las tablas en modo exclusivo, y luego emitir USE ALUMNOS. Para modificar la estructura de la tabla agregando un nuevo índice, puede valerse de VER – DISEÑADOR DE TABLAS. En el diseñador, podría usar la ficha CAMPOS, definiendo un índice ascendente en el campo NOMBRE. De un modo más general, puede usar directamente la ficha ÍNDICES, agregando luego del índice MU el índice llamado Nombre, de tipo Normal y expresión Nombre. El nombre del índice no tiene por qué ser igual al nombre del campo. Podría haber sido cualquier otro. Acepte los cambios. Index on El comando para crear un índice es INDEX ON. Como hay varias clases de índices, el comando tiene muchas variantes. Pero nos reduciremos a crear índices compuestos estructurales, que son los mejores y más eficientes, por lo que las variantes se reducen. Luego de INDEX ON se coloca la expresión del índice, que es uno o más campos, transformados por funciones de caracteres si hace falta. Si son varios campos o funciones sobre ellos, se concatenan con el operador +. A continuación sigue la palabra TAG y el nombre que va a tener el índice. Todo lo anterior es obligatorio. Opcionalmente se pueden usar las cláusulas que se exponen a continuación. La cláusula opcional ASCENDING, que se supone escrita, hace que el índice ordene los registros en secuencia ascendente. La contraria, también optativa, es DESCENDING, que debe incluirse si se desea secuencia descendente. Para crear el índice NOMBRE del punto anterior, el comando sería index on nombre tag nombre Examine la tabla y active el índice NOMBRE. Verá los registros ordenados por ese campo. Dir El comando DIR, que también se puede escribir DIRECTORY, muestra los archivos de una carpeta en el escritorio. Si no se indica una carpeta, se aplica a la carpeta actual, es decir, la de trabajo. Si escribe DIR sin agregar datos adicionales, muestra las tablas, una por línea, indicando su nombre, fecha de creación, tamaño en bytes, cantidad de registros, etc. Emita DIR en la ventana COMANDOS. —16— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 Si indica un patrón luego de la palabra DIR, pero no indica extensión, se listan las tablas que responden a él. En el patrón se pueden usar los comodines ? y *. El ? indica que en la posición donde aparece puede haber cualquier carácter. El * indica que en varias posiciones puede haber cualquier carácter. Por ejemplo, todos los comandos siguientes listan la tabla ALUMNOS: dir alumnos dir al* dir ?lumnos dir ?lu* dir *m* dir *s dir *os dir *no? Si hubiera otras tablas que responden a estos patrones, también serían listadas. ¿Para qué usar patrones? Suponga que hubiera 500 tablas. Si quisiera ver datos solamente de aquellas tablas cuyo nombre responde a un patrón, usando éste en el comando DIR reduciría el listado solamente a ellas. Si en el patrón incluye la extensión, el listado incluirá las tablas y todos los archivos que respondan a él, pero listará los nombres y extensiones, no los tamaños, fechas de creación, etc. El patrón tendrá dos partes: la primera se refiere al nombre y la segunda a la extensión. Ambas partes se separan por un punto, que es indispensable. Pruebe: dir al* dir al*.dbf dir *.cdx dir alum*.* && Lista las tablas que empiezan con al, en este caso Alumnos && Lista las tablas que empiezan con al, en este caso Alumnos && Lista todos los archivos de índices && Lista todos los archivos que empiezan con alum Los && introducen comentarios al final de una línea. No son interpretados como parte del comando. No hace falta que usted los escribe. Se han colocado para explicar lo que hace cada comando. Si cualquier ventana tapa el escritorio, DIR y cualquier otro comando que escriba resultados en el escritorio se ejecutarán lo mismo, pero no se podrá ver lo escrito, salvo que se cierren las ventanas, se las cambie de lugar, se las minimice, etc. DIR puede listar archivos de cualquier otra carpeta, si se incluye el camino adecuado. Borrado del escritorio Si quiere limpiar el escritorio, puede usar VENTANA – BORRAR. Clear El comando para borrar el escritorio es CLEAR, que no lleva más componentes. Archivo de índices compuesto estructural Cierre la ventana EXAMINAR si está abierta, borre el escritorio y emita dir alumnos.* Verá que hay dos archivos: ALUMNOS.DBF y ALUMNOS.CDX. El que tiene extensión DBF es la tabla ALUMNOS. El que tiene extensión CDX es el archivo donde se guardan los índices MU y NOMBRE. Como es un archivo que puede tener más de un índice, se llama compuesto. Hay otros archivos con un solo índice, menos poderosos, cuya extensión es IDX. El archivo de índices tiene el mismo nombre de la tabla, lo cual indica que es estructural. Un archivo de índices estructural siempre es compuesto. Un archivo compuesto no siempre es estructural. Un archivo compuesto estructural se abre o cierra siempre que lo hace la tabla. Si se agregan o eliminan registros, todos los índices se actualizan automáticamente. No pasa lo mismo con los archivos compuestos no estructurales, que necesitan ser abiertos y actualizados mediante comandos apropiados. Los compuestos estructurales, entonces, son los más ventajosos, por lo que desde que existen son prácticamente los únicos que se usan. De todos los índices que forman un archivo compuesto estructural, sólo uno puede estar activo. Sin embargo, los cambios que se introduzcan en la tabla, agregando, eliminando o modificando registros, actualizan todos estos índices. Alcance Hay opciones de menú y comandos que afectan a una cantidad variable de registros. ALCANCE es la cantidad de registros a afectar por esas opciones y comandos. Hay cuatro alcances: Alcance Efecto ALL Incluye todos los registros de la tabla —17— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 NEXT Incluye N registros siguientes, contando desde el actual. RECORD Incluye solamente el registro cuyo número de registro es N. REST Incluye desde el registro actual hasta el final de la tabla. Si se usan NEXT o RECORD, hay que proporcionar un número N, que es la cantidad de registros siguientes o el número del registro. Si hay un filtro de registros en vigencia, en el alcance se incluyen solamente los registros que pasan ese filtro. For La cláusula FOR introduce una condición lógica en un comando para modificar su comportamiento. El comando prueba la condición FOR registro a registro, dentro del ALCANCE. Todo registro que cumpla esa condición, es decir, aquél para el cual la condición resulte verdadera, será afectado por el comando. Todo registro que no la cumpla, será ignorado. El comando funciona hasta agotar la totalidad del alcance, aunque no encuentre registros que satisfagan la condición. El uso de FOR es opcional, excepto en un caso que veremos pronto. While La cláusula WHILE introduce una condición lógica en un comando para modificar su comportamiento, pero actúa de otro modo. El comando prueba la condición WHILE registro a registro, dentro del ALCANCE. Si es verdadera, el comando sigue funcionando. Si es falsa, termina la ejecución del comando. WHILE predomina sobre FOR e incluso sobre la porción remanente del ALCANCE. Si el comando termina, puede quedar una porción del alcance sin inspeccionar, dentro de la cual puede haber registros para los cuales FOR sea verdadera. El uso de WHILE siempre es opcional. Dejemos clara la diferencia entre FOR y WHILE. Sea que la tabla ALUMNOS, con el índice MU activo, tiene los siguientes registros: Mu 257 542 645 1377 1702 2388 2406 3161 4315 5201 Nombre Oro, Eugenio Suárez, Jorge Vidal, Daniel Toro, Laura Ávila, María Ruiz, Marina Alba, Alberto Gil, Raúl Castro, Ana Cortés, Luis Domicilio Sexo Roca 2928 M Salta 101 M La Rioja 2246 M Paso 339 F Mitre 7047 F Belgrano 1128 F Córdoba 175 M San Martín 5928 M Solís 4214 F Jujuy 8543 M Registro 5 3 7 6 2 4 8 10 9 1 Veamos distintas combinaciones de ALCANCE, FOR y WHILE para un comando que los admita. Consideraremos cuál es el registro actual al momento de emitir el comando. Registro actual es aquel donde está el puntero. Reg. actual Cualquiera All Alcance While — Sexo = "M" es Cualquiera All Nombre = "C" .T. en 5, 3, 7. Sexo = "F" es .F. en 5, Cualquiera All Nombre = "A" fin del comando. 5 Next 5: 5, 3, 7, 6, 2 Nombre = "T" — 6 Rest: 6, 2, 4, 8, 10, 9, 1 Sexo = "M" — Mu < 2400 es 6 Rest Sexo = "M" .T. en 6, 2, 4. Cualquier Record 4 Cualquiera All For Nombre = "C" Nombre = "T" — — Nombre # "Ávila" —18— Regs. afectados 9, 1 Ninguno. While es .F. en 6, fin del comando. Ninguno 6 8, 10, 1 Ninguno. While es .F. en 8, fin del comando. Ninguno. Nombre del registro 4 no comienza con T. 5, 3, 7, 6. While es .F. en 2. Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 Para el alcance ALL no importa el registro de partida, porque se incluyen todos los registros, desde el comienzo. Tampoco importa para RECORD, pues se incluye únicamente el registro indicado. Puede que se pregunte para qué usar WHILE, pues sería posible introducir su condición dentro de FOR. Así, el Ejemplo 6, en lugar de for Sexo = "M" while Mu < 2400, podría usar for sexo = "M" and Mu < 2400. Desde un punto de vista lógico la objeción es correcta. Pero no lo es en cuanto al rendimiento. FOR examina todo el alcance y termina al agotarlo. Si la tabla tuviera gran número de registros, digamos 15.000.000, el comando que llevara ese FOR demoraría un buen rato. WHILE, por el contrario, termina el comando la primera vez que su condición resulta falsa. Esto implica que, si se activa el índice adecuado y se establece adecuadamente el registro actual antes de emitir el comando, el tiempo de inspección de los registros se reduce drásticamente. En computación, es obvio, el tiempo que tarda un comando es de gran importancia. FOR y WHILE usan condiciones lógicas que se pueden construir libremente con cualquier campo o campos. Si no hay un índice activo, el comando inspecciona los registros en el orden de grabación. Si lo hay, el comando inspecciona los registros en el orden que establece el índice. Pero el índice solamente influye en el orden de acceder a los registros; nada tiene que ver con lo que hace el comando en sí. Ir a un registro Al examinar una tabla, el menú TABLA – IR AL REGISTRO tiene varias posibilidades. – PRIMERO. El puntero de registros salta al primer registro de la tabla. – ÚLTIMO. El puntero salta al último registro de la tabla. – SIGUIENTE. El puntero salta al registro siguiente. – ANTERIOR. El puntero salta al registro anterior. Los cuatro casos anteriores tienen un comportamiento diferente, según haya o no un índice activo. Si no hay un índice activo: PRIMERO es el que tiene número de registro 1, es decir el primero grabado. Para simplificar, en lugar de decir "registro que tiene número de registro X", diremos "registro X". ÚLTIMO es el grabado al final. Si la tabla tiene 150 registros, último es el registro 150. SIGUIENTE es el que sigue al actual en orden de grabación. Si el puntero está en el registro 38, siguiente es el registro 39. ANTERIOR es que precede al actual en orden de grabación. Si el puntero está en el registro 38, anterior es el registro 37. Si hay un índice activo, el comportamiento es diferente: PRIMERO es el que el índice indica que está al comienzo, el cual no necesariamente es el registro 1. ÚLTIMO es el que el índice indica que está al final. Por ejemplo, si la tabla ALUMNOS tuviera nada más que cuatro registros, cuyo campo MU en orden de grabación fuera: Mu Registro 2154 1 1259 2 3275 3 2048 4 Si se activa el índice MU, cuya expresión es el campo MU, los registros se verían ahora: Mu Registro 1259 2 2048 4 2154 1 3275 3 —19— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 PRIMERO, en esta situación, no es el registro 1, sino el registro 2. ÚLTIMO es el registro 3. Si el registro actual es el 4, SIGUIENTE es el registro 1 y ANTERIOR el registro 2. ¿Qué sucede cuando se pretende avanzar después del último registro o retroceder antes del primero? Volveremos sobre esto más adelante. – REGISTRO NÚMERO. El puntero salta al registro cuyo número se indica. Para ello se abre el diálogo IR AL REGISTRO, donde se escribe tal número y luego se pulsa ACEPTAR. No importa si hay o no un índice activo: el número de registro es siempre el mismo. – ENCONTRAR. Presenta el diálogo ENCONTRAR REGISTRO, donde se definen criterios de búsqueda. Cuando se pulsa el botón ENCONTRAR, se busca el primer registro que cumple los criterios. Los criterios se establecen mediante ALCANCE, FOR y WHILE, temas que vimos de modo general. Lo único que debemos agregar aquí es que FOR, para este comando, es obligatorio. Go, Skip, Locate y Continue Las formas TABLA – IR AL REGISTRO – PRIMERO, ÚLTIMO, SIGUIENTE y ANTERIOR tienen comandos equivalentes: PRIMERO ÚLTIMO SIGUIENTE ANTERIOR GO TOP GO BOTTOM SKIP (que se interpreta skip 1) SKIP – 1 Si queremos un salto de varios registros hacia adelante o atrás, se usa SKIP N o SKIP –N, que avanza N registros o retrocede –N registros, donde N es un número o expresión numérica. Por ejemplo: skip 5 skip 4 + 3 skip –6 skip x && avanza 5 registros && avanza 7 registros && retrocede 6 registros && avanza o retrocede tantos registros como el número almacenado en X. El comando equivalente a TABLA – IR AL REGISTRO – REGISTRO NÚMERO es GO, seguido por el número de registro al que se quiere ir. Las formas GO TOP y GO BOTTOM, también válidas, van al primero y último registro, con las salvedades vistas sobre qué entender por primero y último. El número de registro debe ser una expresión numérica positiva, como: go 5 go 10 + 5 go x && salta al registro 5 && salta al registro 15 && salta al registro cuyo número está en X. Si el número proporcionado es mayor al número de registro mayor, se da un mensaje de error y el puntero de registros permanece donde estaba. El comando equivalente a TABLA – IR AL REGISTRO – ENCONTRAR es LOCATE FOR. Si no se explicita el alcance, se supone ALL. WHILE es opcional. Ejemplos: locate for nombre = "C" locate for nombre = "C" while sexo = "F" rest locate for domicilio = "Salta" rest ENCONTRAR y LOCATE FOR siempre buscan el primer registro que cumple la condición FOR. ¿Cómo encontrar el segundo, tercero, etc., que la cumplan? No hay opción de menú que realice esta tarea. En programación, el comando CONTINUE, sin más agregados, busca el siguiente registro que cumple la condición. Las sucesivas emisiones de CONTINUE siguen buscando el siguiente, hasta agotar el alcance. Examine la tabla ALUMNOS. Con TABLA – IR AL REGISTRO – ENCONTRAR…, introduzca Mu <= 9000 en la condición FOR. Vea cuál es el registro encontrado. Vuelva a repetir la búsqueda exactamente igual. El registro encontrado es el mismo, porque se busca el primer registro que satisface la condición FOR. Active la ventana COMANDOS y emita LOCATE FOR MU <= 9000. Dé clic en la ventana EXAMINAR para activarla y vea que el registro es el mismo de antes. Ahora emita el comando CONTINUE y active la ventana EXAMINAR. El registro hallado es el segundo que cumple la condición. Emita el comando CONTINUE y active la ventana EXAMINAR. El registro hallado es el tercero que cumple la condición. Etc. El comando ? puede aplicarse a campos porque evalúa una o más expresiones, y los campos son expresiones. Los campos son los del registro actual. Si se cambia de registro, exactamente el mismo comando puede producir otro resultado, porque el registro actual ha cambiado. Por ejemplo: close tables all use alumnos ? mu —20— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 ? nombre ? mu, nombre, domicilio, sexo go 10 ? mu, nombre, domicilio, sexo skip –1 ? mu, nombre, domicilio, sexo ? mu * 2 use Comienzo y fin de archivo. Bof( ) y Eof( ) Al hablar del comando SKIP, dijimos que se puede ordenar un salto por una cantidad de registros que esté después del último o antes del primero. Por supuesto que no se puede ir a un registro que no existe, pero algo pasa. Cuando se salta más allá del último registro, se alcanza el fin de archivo. Esta situación se puede conocer consultando la función EOF( ), que devuelve .T. únicamente en el fin de archivo. Cuando se salta antes del primer registro, se alcanza el comienzo de archivo. Esta situación se puede conocer consultando la función BOF( ), que devuelve .T. únicamente en el comienzo de archivo. clear close tables all use alumnos ? bof( ) ? eof( ) go 10 ? bof( ) ? eof( ) go bottom ? bof( ) ? eof( ) skip ? bof( ) ? eof( ) go top skip – 1 ? bof( ) ? eof( ) use Recno( ) En programación, el manejo de los números de registro es fundamental. La función RECNO( ) devuelve el número de registro actual de cualquier tabla abierta. Si no se escribe nada dentro de los paréntesis, la función se aplica a la tabla seleccionada. Si dentro de los paréntesis se escribe entre comillas o apóstrofes el nombre de una tabla abierta, esté o no seleccionada, la función se aplica a ella. Estos nombres de tabla entre paréntesis también funcionan en BOF( ), EOF( ) y en varias otras funciones. Por ahora sabe usar una sola tabla, la única que podemos probar: use alumnos ? recno( ) go 10 ? recno("alumnos") go bottom ? recno( ) set order to mu go top ? recno('alumnos') go bottom ? recno( ) use La utilidad de esta función se puede apreciar en lo que sigue: use alumnos locate for nombre = "A" x = recno( ) El último comando guarda en la variable x el número de registro encontrado por LOCATE. Si luego se cambia el puntero de registros usando otros comandos, se puede volver al registro encontrado por LOCATE. Por ejemplo: —21— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 go top ? recno( ) go bottom ? recno( ) go x ? recno( ) use Cuando el puntero está más allá del último registro, RECNO( ) da un número igual a la cantidad de ellos más uno. Cuando el puntero está antes del comienzo de la tabla, esta función da 1. Reccount( ) La función RECCOUNT( ) da la cantidad de registros de una tabla abierta. Si no se escribe un argumento, se aplica a la tabla seleccionada. Para aplicarla a tablas abiertas pero no seleccionadas, se escribe como argumento el alias de la tabla, entre comillas simples o dobles. El valor que devuelve RECCOUNT( ) es el número real de registros de la tabla aludida, sin tener en cuenta si hay filtros vigentes o el estado del comando SET DELETED. use alumnos ?reccount( ) set filter to nombre = "A" ?reccount( ) use Set deleted Este comando establece un filtro sobre los registros marcados para destruir. La forma SET DELETED ON activa el filtro, de modo que los registros marcados se vuelven invisibles para los demás comandos que procesan registros. La forma SET DELETED OFF hace que los registros marcados sean visibles para esos comandos. El estado de SET DELETED es ignorado por los comandos INDEX y REINDEX, que procesan todos los registros. Use la tabla ALUMNOS y marque algunos registros para destruir. set deleted on browse set deleted off browse Elimine todas las marcas y cierre la tabla. Agregar un registro En el menú TABLA aparece AÑADIR NUEVO REGISTRO. A diferencia del modo AÑADIR, que permite agregar cualquier número de registros nuevos, AÑADIR NUEVO REGISTRO agrega uno solo, en blanco. En la ventana EXAMINAR es poco importante. Append blank El equivalente en programación para agregar un registro es el comando append blank, sin más agregados. Opciones poco útiles del menú Tabla En la ventana EXAMINAR hay varias opciones en el menú TABLA que son poco útiles, porque realizan lo que se logra fácilmente con el mouse. Son las siguientes: – ALTERNAR MARCA DE ELIMINACIÓN. Si el registro actual no está marcado para ser eliminado, lo marca; si está marcado, lo desmarca. Con el mouse, se da clic en el marcador de destrucción. – AJUSTAR CAMPO. Permite variar el ancho de una columna con las flechas horizontales. La operación se finaliza con ENTER o ESC. Con el mouse, se arrastra el borde derecho del encabezado. – MOVER CAMPO. Permite cambiar la posición de una columna usando las flechas horizontales. La operación se finaliza con ENTER o ESC. Con el mouse, se arrastra el encabezado. – CAMBIAR TAMAÑO DE PARTICIONES. Permite mover el partidor con las flechas horizontales. La operación se finaliza con ENTER o ESC. Con el mouse, se arrastra el partidor. – CAMBIAR PARTICIONES. Activa la partición no activa. Con el mouse, se da clic en la no activa. —22— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 Copy structure Este comando crea una tabla vacía con la misma estructura de la tabla abierta y seleccionada. No copia ningún registro. Luego de COPY STRUCTURE TO se escribe el nombre que va a tener la nueva tabla. Por defecto, el comando copia toda la estructura, pero no el archivo de índices compuesto estructural. Si se quiere copiar la estructura de algunos campos, se usa FIELDS seguido por la lista de campos. Si se quiere copiar el archivo de índices, se usa WITH CDX. Note que si hay un índice principal, se convierte en candidato, conceptos que veremos luego. use alumnos copy structure to alumnos2 dir use alumnos2 display structure browse Se copiaron a ALUMNOS2 todos los campos de todos los registros. use alumnos copy structure to alumnos3 fields mu, nombre use alumnos3 display structure Se copiaron a ALUMNOS3 solamente los campos de datos indicados luego de la palabra FIELDS. Copy to Este comando crea un archivo a partir de una tabla abierta y seleccionada. Tiene muchas posibilidades, de las que veremos las más importantes. Luego de COPY TO se escribe el nombre del archivo a crear, cuya extensión por defecto es deducida por VFP. Si no se indica el tipo de archivo a obtener, se crea una tabla. La copia, por defecto, incluye todos los campos y todos los registros. Para copiar algunos campos, se usa la palabra FIELDS seguida por una lista de campos. También se aceptan las formas FIELDS LIKE y FIELDS EXCEPT, seguidas por un patrón construido con los comodines * y ?. En el primer caso se copian todos los campos que responden al patrón y en el segundo todos los campos que no responden a él. Ambas cláusulas se pueden combinar en la forma FIELDS LIKE PATRÓN1 EXCEPT PATRÓN2. Para limitar la cantidad de registros a copiar, se pueden usar ALCANCE, FOR y WHILE. Si la copia es de una tabla, se puede copiar el archivo de índices compuesto estructural, usando la cláusula WITH CDX. Si se indica un tipo de archivo, se creará una tabla u otra clase de archivo. Para ello se usa TYPE, que es opcional, y otras palabras más específicas. Todos estos tipos aceptan las formas FIELDS y ALCANCE, FOR y WHILE. Algunos no aceptan campos memo, incluso si se especifican en la lista de campos. Ejemplos de algunos tipos son los siguientes. XL5. Crea un hoja de Excel, versión 5.0. Cada campo origina una celda y cada registro, una fila. La extensión por defecto es XLS. Para los tipos que siguen, tomemos la tabla ALUMNOS como tabla abierta y seleccionada. Sea que tiene los siguientes registros: Mu 257 542 645 Nombre Oro, Eugenio Suárez, Jorge Vidal, Daniel Domicilio Roca 2928 Salta 101 La Rioja 2246 Sexo M M M SDF. Crea un archivo en formato de datos del sistema, de texto ASCII, con registros de longitud fija. La extensión por defecto es TXT. El comando copy to prueba type sdf producirá el archivo PRUEBA.TXT, con el siguiente contenido: 257 542 645 Oro, Eugenio Suárez, Jorge Vidal, Daniel Roca 2928 Salta 101 La Rioja 2246 M M M Las líneas auxiliares indican que los datos correspondientes a un campo tienen igual longitud. Delimited. Crea un archivo de texto ASCII, con campos son de longitud variable, separados por comas. Como los campos de caracteres pueden incluir comas, se los delimita entre comillas. La extensión por defecto es TXT. El comando copy to prueba type delimited producirá el archivo PRUEBA.TXT, con el siguiente contenido: 257,"Oro, Eugenio","Roca 2928","M" 542,"Suárez, Jorge","Salta 101","M" 645,"Vidal, Daniel","La Rioja 2246","M" —23— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 Todos los archivos PRUEBA.TXT anteriores pueden ser examinados con el comando MODIFY FILE. Modify file El comando MODIFY FILE, seguido por un nombre de archivo, permite modificar el texo de ese archivo, si existe. Si no existe, lo crea y permite modificarlo. Si no se indica, se supone que la extensión es TXT. Si se quiere otra extensión, hay que escribirla explícitamente. Nótese que los archivos de texto puro se ven sin problemas. Otros textos, como los documentos de Word, se ven con señales extrañas, porque dentro del texto hay muchos comandos para comenzar y terminar negritas, cursivas, etc. En general, ese comando trabaja con cualquier tipo de archivo, aunque no se entienda lo que contiene. Diálogo Exportar En el menú ARCHIVO, haya o no una tabla abierta, se puede lograr lo equivalente a PORTAR. Se presenta el cuadro de diálogo EXPORTAR, con las siguientes opciones: COPY TO, usando EX- – TIPO. Sirve para definir el tipo de archivo que se quiere crear con la exportación: DBF, texto delimitado, XLS, XL5, etc. – A. Sirve para definir la ruta y el nombre del archivo a crear. El botón de tres puntos llama al diálogo GUARDAR COMO, para establecer la carpeta y el nombre del archivo a producir. – DELIMITADOR DE TEXTO. Aparece cuando en TIPO se elije TEXTO DELIMITADO. Permite definir el carácter que va a delimitar los campos de caracteres, el cual por defecto es la comilla. – SEPARADOR DE CAMPOS. Aparece cuando en TIPO se elige TEXTO DELIMITADO. Permite definir el carácter que se va a usar para separar los campos, el cual por defecto es la coma. – DESDE. Sirve para definir la ruta y el nombre de la tabla existente a exportar. El botón de tres puntos es una alternativa para encontrar la tabla. – OPCIONES. Muestra el cuadro de diálogo OPCIONES DE EXPORTACIÓN, donde se pueden definir condiciones FOR y WHILE y los campos a exportar. ALCANCE, Agregado masivo de registros: diálogo Añadir desde TABLA – AÑADIR REGISTROS agrega registros a la tabla que se está examinando desde otro archivo existente, que puede ser una tabla, una planilla de cálculo, un texto, etc. En el diálogo AÑADIR DESDE, TIPO es una lista para elegir el tipo de tal archivo y DESDE es un cuadro de texto para escribir su nombre, incluyendo el camino de carpetas, si es necesario. Esta tarea puede facilitarse buscándolo en la estructura de carpetas, para lo cual sirve el botón de tres puntos. Si el archivo origen, aquél desde el cual vamos a agregar registros, es una tabla, debe tener por lo menos un campo coincidente en nombre y tipo con la tabla que estamos examinando, es decir, la tabla destino. Podríamos querer que los registros añadidos tuvieran todos los campos coincidentes llenos con los datos del origen. Pero podríamos querer que, aunque coincidan, sólo se llenen algunos campos, dejando los otros en blanco. También podríamos añadir todos los registros del origen o solamente los que cumplan una condición. Por defecto, se agregan todos los registros del origen, llenando todos los campos coincidentes. Para modificar este comportamiento, se pulsa el BOTÓN OPCIONES, que presenta el diálogo OPCIONES DE AÑADIR DESDE. El botón CAMPOS trae el diálogo SELECTOR DE CAMPOS, ya conocido. El botón FOR trae el GENERADOR DE EXPRESIONES, para escribir un filtro. La expresión de filtro debe contener campos coincidentes. A partir de la tabla ALUMNOS, creemos un duplicado llamado COPIA. Para ello usaremos el comando COPY TO. Luego usaremos COPIA y le agregaremos nuevos registros, a partir de ALUMNOS. close tables all use alumnos copy to copia with cdx use copia set order to mu Examine COPIA. Son los mismos registros de ALUMNOS. Ahora agregue todos los registros de ALUMNOS. Elija TABLA – AÑADIR REGISTROS. En el diálogo AÑADIR DESDE, TIPO dice Tabla (DBF). Es correcto, porque el archivo —24— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 origen de la copia, ALUMNOS, es una tabla. En DESDE escriba Alumnos, la tabla origen. Pulse ACEPTAR. Compruebe que los registros están totalmente duplicados. Repita el procedimiento, pero antes de ACEPTAR pulse CAMPOS. En el diálogo SELECTOR DE CAMPOS seleccione los campos MU y NOMBRE y pulse ACEPTAR. Ahora pulse ACEPTAR en el diálogo AÑADIR DESDE. Los registros están triplicados, pero los últimos carecen de contenido en DOMICILIO y SEXO. Repita el procedimiento, esta vez pulsando FOR. En el GENERADOR DE EXPRESIONES escriba Mu < 2000. Compruebe que los registros con Mu menor a 2000 aparecen cuatro veces. Es posible agregar registros que no estén en una tabla de VFP, sino en una planilla de cálculo, un archivo de texto, etc. Para ello, en TIPO se elige el tipo del archivo origen. Si es un archivo delimitado, se presentan las opciones DELIMITADOR DE TEXTO y SEPARADOR DE CAMPOS, como ya sabe. Append from El comando equivalente a TABLA – AÑADIR REGISTROS es APPEND FROM. Si el archivo desde el que se va a copiar es una tabla, luego de FROM se escribe su nombre. Si se quiere el contenido de algunos campos coincidentes, se escribe FIELDS y una lista de nombres de campos, separados por comas. Si se quiere agregar registros que cumplen una condición, se ESCRIBE FOR y luego la condición. El comando no admite la cláusula WHILE. Ejemplos: append from alumnos append from alumnos fields mu, nombre append from alumnos for mu < 2000 FROM y FIELDS no son excluyentes, de modo que pueden ir en un mismo comando: append from alumnos fields mu, nombre for mu < 2000 o también append from alumnos for mu < 2000 fields mu, nombre Si la tabla que se va a agregar tiene registros para destruir, son agregados sin marca, sin tener en cuenta el valor de SET DELETED. Como sucede con COPY TO, que a partir de una tabla permite obtener archivos que no sean tablas, APPEND FROM puede añadir registros de otros tipos de archivo. Se puede usar opcionalmente la cláusula TYPE para introducir la declaración del archivo origen de la copia. En correspondencia con lo visto para COPY TO, los tipos son XLS, SDF, DELIMITED, etc. Las mencionadas no son las únicas posibilidades, por lo que recomendamos consultar la Ayuda. Si el archivo origen tiene fechas, éstas se pueden importar sin problemas si están en formato adecuado. El formato predeterminado es MM/DD/AA. Es opcional incluir la parte de siglo. Si no se lo coloca, VFP supone un siglo. Los delimitadores de fecha pueden ser cualquier carácter no numérico, excepto el separador de campos. Si el formato de las fechas de origen no es el predeterminado, pero es válido, antes de importar los registros debe emitirse SET DATE con el formato adecuado. Diálogo Importar ARCHIVO – IMPORTAR presenta un diálogo con igual nombre. Es similar al diálogo AÑADIR DESDE, pero no ofrece la posibilidad TEXTO DELIMITADO. El propósito de este diálogo es crear una nueva tabla, no agregar registros a una tabla existente. Esto explica por qué no trabaja con archivos de texto, pues no hay una estructura de la tabla destino a la cual adaptar los datos. Marcado de registros a eliminar TABLA – ELIMINAR REGISTROS permite eliminar registros que respondan a ciertos criterios. Hasta ahora, la forma de marcarlos era dando clic en el marcador de destrucción de cada uno. Si hubiera cientos o miles de registros a marcar, hacerlo a mano sería lento y fatigoso, y posiblemente nos equivocaríamos. Esta opción de menú permite hacerlo de manera automática. Presenta el diálogo ELIMINAR, donde aparecen las opciones ALCANCE, FOR y WHILE, que ya conoce. El alcance por defecto es NEXT 1. Al pulsar ELIMINAR se ejecuta automáticamente el marcado. Use la tabla ALUMNOS y examínela. Experimente marcando los registros cuya matrícula esté en un rango de valores, usando alcance ALL y una expresión en FOR como between(mu,1000,2000). Compruebe. Vaya a un registro próximo al fin del archivo y marque los restantes con alcance REST. Compruebe. Marque con alcance ALL los registros cuyo SEXO sea F. Compruebe. Marque finalmente todos los registros, con ALCANCE ALL, sin usar FOR ni WHILE. Compruebe. No se asuste. En seguida los desmarcaremos. —25— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 Delete El comando para marcar registros a eliminar es DELETE. El ALCANCE por defecto es NEXT 1, es decir el registro actual. Esto se ha hecho así para marcar lo menos posible, porque puede ser peligroso si a continuación se quitan definitivamente los registros marcados. El comando puede llevar condiciones FOR y WHILE, que cambian automáticamente el alcance a ALL. Por ejemplo: delete delete for sexo = 'M' delete for sexo = 'M' and between(mu,1000,2500) delete for sexo = 'M' while recno( ) < 15 delete rest for mu < 4000 delete all Deleted( ) Esta función devuelve .T. si el registro actual de la tabla abierta indicada está marcado para destruir. Si no está marcado, devuelve .F. Si no se usa argumento, se aplica a la tabla seleccionada. Para aplicarlo a otra tabla abierta, se escribe como argumento el alias, entre comillas simples o dobles. use facturas delete record 10 ? deleted( ) go bottom ? deleted( ) recall all use SET FILTER TO NOT DELETED( ) es parcialmente igual a SET DELETED ON. Ambos no dejan ver los registros marcados, pero el último no es tenido en cuenta por INDEX y REINDEX, mientras que el primero sí. Desmarcado de registros a eliminar Así como marcar registros puede automatizarse, lo mismo sucede con desmarcar. Para ello se usa TABLA – DESMARCAR REGISTROS. Aparece el diálogo DESMARCAR, con las opciones ALCANCE, FOR y WHILE. El alcance por defecto es NEXT 1. El botón DESMARCAR ejecuta la operación, observando los criterios establecidos. Use la tabla ALUMNOS y examínela. Experimente desmarcando los registros cuya matrícula esté en un rango de valores, usando alcance ALL y una expresión en FOR como between(mu, 1000, 2000). Compruebe. Vaya a un registro próximo al fin del archivo y desmarque los restantes con alcance REST. Compruebe. Desmarque con alcance ALL los registros cuyo SEXO sea F. Compruebe. Desmarque finalmente todos los registros, por si alguno tiene marca todavía, con alcance ALL, sin usar FOR ni WHILE. Compruebe. Recall El comando para desmarcar registros a eliminar es RECALL. El ALCANCE por defecto es NEXT 1. Puede llevar condiciones FOR y WHILE, que cambian el alcance por defecto a ALL. Los comandos para lograr lo explicado antes, serían: recall recall for sexo = 'M' recall for sexo = 'M' and between(mu,1000,2500) recall for sexo = 'M' while recno( ) < 15 recall rest for mu < 4000 recall all Eliminación de registros marcados Los registros marcados no se eliminan de inmediato, posibilitando desmarcarlos. Para eliminarlos definitivamente se usa TABLA – QUITAR REGISTROS ELIMINADOS. VFP pide confirmar la acción. Si luego de eliminar definitivamente los registros marcados se examina la tabla, no se verá ningún registro marcado. Pack El comando para eliminar definitivamente los registros marcados es PACK, sin agregados, que presenta el mensaje de advertencia. En redes, la tabla debe haberse abierto en modo exclusivo. —26— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 Cambio de los datos de uno o varios campos Trabajando en la ventana EXAMINAR, puede cambiar el dato de un campo cualquiera si se coloca en él y lo edita. Si tuviera que cambiar el dato de un campo en varios registros que cumplen ciertos criterios, el trabajo a mano sería lento y sujeto a errores. Siempre que pueda establecer criterios para un cambio masivo, conviene automatizar el trabajo. La opción TABLA – REEMPLAZAR CAMPO permite cambiar el dato de un solo campo en todos los registros que cumplan los criterios. Presenta el diálogo REEMPLAZAR CAMPO, con las opciones CAMPO, WITH, ALCANCE, FOR y WHILE. Lo que se reemplaza es el dato de un campo, no el campo: el nombre de la opción del menú no es feliz. El campo en cuestión se elige en la lista CAMPO. El valor con el cual va a ser llenado se escribe en WITH, directamente o usando el generador de expresiones. ALCANCE, FOR y WHILE funcionan como ya conoce. El botón REEMPLAZAR inicia la acción automática. Examinando la tabla ALUMNOS, reemplace el contenido del campo SEXO con una A para los registros con SEXO F y Mu > 2500. Debe elegir Sexo en CAMPO, escribir "A" en WITH y escribir Sexo = "F" and Mu > 2000 en FOR. Compruebe. Deje las cosas como estaban al principio: elija Sexo EN CAMPO, escriba "F" en WITH y escriba Sexo = "A" en FOR. Replace El comando para lograr lo explicado en el punto anterior es REPLACE. Luego de REPLACE se escribe el nombre del campo, la palabra WITH y el nuevo dato. Se puede usar ALCANCE, FOR y WHILE, en cualquier orden. Si no escribe ALCANCE, se supone NEXT 1. Si usa FOR o WHILE, el ALCANCE por defecto cambia a ALL. Las dos operaciones que hizo antes por menú se pueden escribir: replace sexo with "A" for sexo = "F" and mu > 2000 replace sexo with "F" for sexo = "A" REPLACE es más poderoso que TABLA – REEMPLAZAR CAMPO. Ello se debe a que el comando permite reemplazar a la vez varios campos por los correspondientes datos. En este caso, la terna CAMPO – WITH – DATO se puede escribir varias veces, separándola por comas, como en el siguiente ejemplo: replace all sexo with "F", mu with mu + 10 Vinculación de particiones Primero use la tabla COPIA y agréguele varias veces todos los registros de la tabla ALUMNOS. Con esto tendrá muchos registros y podrá ver lo que vamos a tratar. close tables all use copia append from alumnos append from alumnos append from alumnos append from alumnos Ahora examine la tabla COPIA y mueva el partidor a la izquierda, para tener dos particiones. Avance y retroceda registros hasta el inicio y el fin en cualquiera de ellas. Abra el menú TABLA. Vea que VINCULAR PARTICIONES está activa. Dé clic en esa opción para desactivarla. Repita el avance y retroceso hasta los extremos. La partición inactiva queda fija, mientras la activa muestra diferentes registros. Únicamente el movimiento del puntero se ve, en la partición inactiva, en la porción de registros comunes a ambas. Regeneración de índices VOLVER A GENERAR ÍNDICES del menú TABLAS reconstruiye el archivo CDX a partir de las definiciones que residen en la estructura de la tabla. Esto es poco necesario tratándose de índices compuestos estructurales. Pero en ocasiones, el mal funcionamiento de una tabla puede deberse a que el archivo de índices estructural esté dañado. Un corte de energía o salir de modo inapropiado de VFP puede dañar o "corromper" el archivo CDX. Para corregir esa posible falla, use esta opción. Si trabaja en red, debe abrir la tabla en modo exclusivo. Reindex El comando para regenerar índices es REINDEX, sin más agregados. Se reindexa la tabla seleccionada. —27— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 Modificación de la estructura de una tabla Para modificar la estructura de una tabla, úsela y emita VER – DISEÑADOR DE TABLAS. Recuerde que si trabaja en una red, debe usar la tabla en modo exclusivo. Modify structure El comando para modificar la estructura de una tabla es MODIFY STRUCTURE, sin más agregados. La tabla a modificar debe estar abierta y seleccionada. Si en el área seleccionada no hay una tabla abierta, se presenta el diálogo ABRIR para elegir la tabla. Agregue los siguientes campos, tipos y anchos a la tabla ALUMNOS: Campo Otro1 Otro2 Otro3 Otro4 Otro5 Otro6 Tipo Carácter Carácter Carácter Carácter Carácter Carácter Ancho 30 30 30 30 30 30 Luego acepte los cambios. display structure La estructura corresponde a las modificaciones introducidas. Cuando se hace una modificación estructural, VFP toma muchas precauciones. Primero copia la estructura original a un archivo temporal. Sobre éste registra los cambios. Al finalizar la operación, copia los registros de la tabla original al archivo temporal. Luego cambia la extensión de la vieja tabla, de DBF a BAK. Finalmente, da al archivo temporal el nombre de la vieja tabla y la extensión DBF. Si se aborta la modificación estructural, VFP destruye el archivo temporal, con lo que la tabla original queda intacta. browse Los registros se han conservardo, con los campos nuevos en blanco. Ahora la ventana EXAMINAR no puede mostrar todos los campos, pero permite desplazarlos, por lo que hay una barra de desplazamiento horizontal. Campos de tipo fecha, fecha–hora y lógico Use la tabla ALUMNOS y modifique su estructura. use alumnos modify structure Agregue los campos NACIDO, de tipo fecha, y ARGENTINO, de tipo lógico. Guarde los cambios. Un campo de tipo fecha sirve, obviamente, para guardar fechas. Su ancho es 8 y no se puede modificar. El campo aceptará fechas válidas, rechazando valores como 31/02/2004 o 30/30/2000, porque febrero no tiene 31 días y no hay un mes 30. Si se ingresa día 29 para febrero, se aceptará si el año es bisiesto. El rechazo de una fecha incorrecta se comunica con un mensaje de error. Las fechas se guardan con el siguiente formato: año (incluyendo siglo), mes y día. La forma en que se visualiza una fecha depende de la configuración. El 5 de noviembre de 2004, por ejemplo, puede verse: 05–11–2004 05/11/2004 05/11/04 11–05–2004 2004–11–05 etc. Un campo de tipo fecha–hora guarda fechas, horas o ambas. Siempre el ancho es 8, inmodificable, y guarda los datos en notación binaria. Las horas se pueden ver en 12 ó 24 horas, con o sin segundos. No hemos agregado un campo de este tipo a la tabla ALUMNOS, porque es fácil de entender. Un campo de tipo lógico siempre tiene ancho 1, inmodificable. Puede guardar los valores T y F, para verdadero y falso. En la ventana EXAMINAR, el campo lógico actual, si es T, se ve V. Los demás campos se ven T. Para modificar el campo actual con el valor T, hay que escribir V. Estas “rarezas” se deben a que se ha usado la V por Verdadero, pero solamente para el campo actual. Examine la tabla. Ingrese datos a los nuevos campos. Pruebe introducir una fecha incorrecta. Así como hay literales de caracteres y numéricos, también los hay de fecha, fecha–hora y lógicos. Los delimitadores de los literales de fecha son { a la izquierda y } a la derecha. Hasta la versión 5, la fecha se escribe de —28— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 acuerdo a la configuración SET DATE vigente. Por ejemplo, si la configuración es DD-MM-AAAA, 2 lugares para día, 2 para mes y 4 para año, la fecha se escribe {DD/MM/AAAA}. Si se omite el siglo, como en {DD/MM/AA}, se supone el establecido con el comando SET CENTURY. Desde la versión 6 se usa un formato más complicado: {^AAAA/MM/DD}. En ambos casos, pueden omitirse los ceros no significativos. Ejemplos: {05-08-2004} {5-8-04} {^2004-08-05} {05-08-04} {5-8-4} {^2004-8-5} Los literales de fecha–hora también usan { y } como delimitadores. Se escribe la fecha, una coma o un espacio, y la hora, teniendo presente la diferencia de versiones explicada antes. La hora sigue el formato HH:MM:SS. Los minutos y segundos son opcionales. Si se omiten los minutos y segundos, se supone 00:00. Si se omiten los segundos, se supone 00. La porción de fecha puede omitirse, en cuyo caso se supone 30–12– 1899. Si se quiere un literal de fecha–hora sin indicar la hora, escriba la fecha, la coma y un 0. Ejemplos: {01-10-2002,13:40:15} {01-10-2002,13} {^2004-10-02,13:40} {01-10-2004,1:40:15PM} {1-10-4,0} {^2004-10-2,1:40PM} Los literales lógicos usan un punto inicial y un punto final como delimitadores. Son solamente dos, .T. (true) y .F. (false), que se pueden escribir en minúscula. Como sinónimo de .T. se puede usar .Y. (yes) y .N. (not), que también pueden ir en minúscula. Campos de tipo memo Los campos de una tabla siempre tienen un ancho determinado, algunos fijados a voluntad, como los de caracteres y numéricos, y otros predeterminados, como los de fecha, fecha–hora y lógicos. ¿Qué hacer si necesitamos un campo para escribir 100 caracteres de texto en un registro, 5000 en otro y 100.000 en un tercero? No se podría definir el campo con el ancho del caso mayor, porque el desperdicio de espacio en la tabla sería un despropósito y además porque los campos de caracteres pueden tener hasta 254 posiciones. Este problema se soluciona con un campo memo. Un campo de este tipo siempre tiene ancho 4 en la tabla, donde VFP escribe una "llamada". La llamada se desarrolla en un archivo asociado, cuyo nombre es igual al de la tabla y cuya extensión es FPT. El funcionamiento es similar a las llamadas usadas en algunos libros: en el texto principal se colocan las llamadas y en el pie de página o en un apéndice se escribe el texto correspondiente a cada una. La estructura del registro puede contener varios campos memo; por ejemplo, el registro de alumnos podría tener dos campos memo, HISTORIAL y OBSERVACIONES. Modifique la estructura de la tabla ALUMNOS, agregando un campo memo llamado NOTAS. Luego examínela. Observe que, en la columna NOTAS, todos los campos aparecen con la palabra memo. Ubíquese en cualquiera de ellos y pulse doble clic o la combinación CTRL + AVPÁG. Se abre una ventana de edición con el nombre ALUMNOS.NOTAS, lo que indica que está trabajando sobre el campo memo NOTAS del registro actual de la tabla ALUMNOS. Escriba el texto que quiera, de dos o tres líneas mínimas. Puede usar ENTER para separar párrafos y TAB para sangrarlos. El menú EDICIÓN le permite copiar, cortar, pegar, buscar, reemplazar, etc., como en cualquier archivo de texto. Puede guardar el contenido de la ventana con ARCHIVO – GUARDAR, tantas veces como quiera mientras está editando. No se le pedirá dónde guardar, porque VFP introduce una llamada en el campo NOTAS del registro actual y guarda el texto editado en en el archivo memo, asociado a la llamada. Para cerrar la ventana puede usar ARCHIVO – CERRAR o el botón de cierre, que pedirán si quiere guardar los últimos cambios en caso de no haberlo hecho. Para guardar y cerrar a la vez, use CTRL + W. Después de guardar y cerrar, observe que el campo donde introdujo texto dice Memo, no memo. Esto indica que tiene contenido. Si vuelve a editarlo, verá el contenido guardado la última vez. Si borra todo el contenido, tras guardar los cambios y cerrar la ventana, verá nuevamente memo. Emita el comando DIR ALUMNOS.*. Verá en el escritorio que hay tres archivos: uno es la tabla, otro el archivo de índices y otro el archivo con el contenido de los campos memo. Reconocerá esto por las extensiones, que son respectivamente DBF, CDX y FPT. Si modifica la estructura de la tabla y elimina todos los campos memo, se elimina automáticamente el archivo FPT. —29— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 Diálogo Editar propiedades Elija cualquier campo memo y entre a editarlo. Emita EDICIÓN– PROPIEDADES. Esto presenta el diálogo PROPIEDADES, con varias opciones para modificar las características de edición. Veamos algunas. EDITAR – EDICIÓN CON ARRASTRAR Y COLOCAR. Habilita seleccionar un trozo de texto y arrastrarlo a otro lugar. – AJUSTE AUTOMÁTICO DE LÍNEA. Si está activa, los párrafos se ajustan al ancho de la ventana de edición, de modo que se vean en varias líneas. Si no está activa, se verá lo que entre de cada párrafo en tal ancho, en una sola línea, quedando lo demás invisible. – SANGRÍA AUTOMÁTICA. Si se aumenta la sangría con TAB en cualquier lugar de un párrafo, el resto del párrafo tendrá ese sangrado. Esto permite lograr sangría francesa, como en el ejemplo siguiente. – Sangría francesa: Es cuando la primera línea del párrafo tiene un margen izquierdo más a la izquierda que el margen izquierdo de las restantes líneas. – ALINEACIÓN. Permite alinear todo el texto a izquierda, centro o derecha. – ANCHO DE TABULACIÓN (CARACTERES). Establece el espacio que saltará el punto de inserción hacia la derecha cada vez que se pulse TAB. – FUENTE. Permite cambiar fuente, estilo y tamaño para todo el texto, mediante el diálogo FUENTE. – MOSTRAR POSICIÓN hace falta. – APLICAR A LOS ARCHIVOS TIPO MEMO. Guarda la configuración de estas opciones para aplicar en el futuro a los campos memo. DE LÍNEA / COLUMNA. Presenta esa información en la barra de estado, activándola si List, Display, Set heading Los comandos LIST y DISPLAY listan la tabla seleccionada en la ventana principal. Por defecto, listan todos los campos que no sean memo. Para listar algunos campos, se usa una lista de ellos, predecida opcionalmente por FIELDS. Para listar el contenido de un campo memo, hay que incluirlo en una lista. El contenido de los campos memo se acomoda al ancho establecido por el comando SET MEMOWIDTH. Los comandos pueden usar ALCANCE, FOR y WHILE. El alcance por defecto de DISPLAY es NEXT 1 y el de LIST es ALL. Si se usa FOR o WHILE, el alcance de DISPLAY se convierte EN ALL. Cada campo tiene un encabezado, igual al nombre del campo. Cada registro aparece precedido por el número de registro. Para no ver estos números, se usa OFF. El listado puede enviarse a impresora si se incluye la cláusula TO PRINTER. La forma TO PRINTER PROMPT hace que se abra un diálogo que permite configurar la impresora, la cantidad de copias y el intervalo de páginas a imprimir. El listado también puede ir a un archivo, si se incluye TO FILE seguido por el nombre del archivo. No se supone extensión, por lo que, si quiere verla con MODIFY FILE, convendría que sea TXT. De lo contrario tendrá que escribir MODIFY FILE y el nombre del archivo, seguido por un punto, pero sin extensión. El envío del listado a impresora o a un archivo no suprime la salida a la ventana principal. Para suprimirla, se usa NOCONSOLE. DISPLAY con alcance de varios registros llena una pantalla y se detiene, esperando que se pulse una tecla para llenar otra. LIST, en cambio, lista todo el alcance sin detenerse. Esta diferencia es común a todas las variedades de ambos comandos. Además de incluir campos en la lista FIELDS, pueden incluir cualquier otra expresión, lo que permite obtener otros datos. Con el comando SET HEADING ON, se ven los encabezados de los campos. SET HEADING OFF los suprime. use alumnos list list off display display off display all list for nombre='A' display fields mu, nombre display mu, nombre set heading off list display record 7 set heading on list close tables all —30— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 Set memowidth Los comandos LIST y DISPLAY, cuando se emiten sin lista de campos, no muestran el contenido de los campos memo, sino solamente la palabra memo. use alumnos list display all Sin embargo, cuando el campo memo se indica en una lista de campos, sí se ve el contenido. display all mu, nombre, notas display notas record 1 list notas for not empty(notas) El comando ? seguido por un campo memo muestra el contenido de tal campo. go 1 ? notas Quizás el ancho con el que se lista el contenido del campo memo (si tiene varias líneas de texto) no le resulte cómodo. Esto se puede cambiar con el comando SET MEMOWIDTH. Este comando establece un ancho para las líneas de un campo memo. set memowidth to 20 display for not empty(notas) set memowidth to 40 display for not empty(notas) Además de afectar a los comandos LIST, DISPLAY y ?, SET MEMOWIDTH afecta a varias funciones referidas a campos memo. —31— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 Índices Los índices son una forma muy eficiente de ordenar una tabla por uno o varios campos. La ordenación es virtual, es decir, no hay cambio del lugar físico de los registros, sino que se hace en un archivo de índices. Cuando se activa un índice, el acceso a los registros se realiza de acuerdo al orden establecido por él. Todo índice tiene un nombre, un tipo, una expresión y un sentido. Opcionalmente, puede usar un filtro. El nombre es arbitrario y puede tener hasta 10 posiciones. Hay diferentes tipos de índices, con distintos efectos, como veremos. El sentido puede ser ascendente o descendente. El filtro discrimina qué registros van a ser considerados para construir el índice. La expresión es el criterio por el cual se van a indexar los registros. Puede consistir en uno o más campos de la tabla, o expresiones más complejas sobre ellos. Por ejemplo, si se quiere ordenar la tabla de artículos por el código, se usará éste para construir el índice. Tratándose de una expresión que use un único campo, este puede ser de cualquier tipo, sin necesidad de transformarlo. Para construir un índice por varios campos o expresiones sobre ellos, hay que crear una expresión final de tipo carácter. Supongamos que queremos indexar el archivo de ventas por código de cliente y número de factura. Si ambos campos son de caracteres, la expresión del índice será código + factura. Si el código fuera de caracteres y la factura numérica, la expresión anterior sería errónea, pues los componentes de la expresión deben ser de caracteres para que la expresión total sea de tal tipo. En este caso, sería necesario convertir la factura a caracteres, mediante la función STR( ). La expresión correcta, entonces, sería código + str(factura, x), suponiendo que factura tiene tamaño x, sin decimales. Si el código también fuera numérico, la expresión sería str(código, z) + str( factura, x), suponiendo que el tamaño del código fuera z, sin decimales. Para los campos fecha o fecha hora, cuando se usan con otros campos para construir la expresión del índice, es necesario transformarlos a caracteres, usando la función DTOS( ). Dado que el ordenamiento se hace en un archivo de índices, sin afectar la tabla, ésta puede tener todos los índices que sean necesarios. Tipos de archivos de índices Hay archivos de índices simples y compuestos. Los simples solamente pueden almacenar un ordenamiento. Su extensión es IDX. Dado que las tablas pueden sufrir altas, bajas y cambios de registros, para que tales cambios queden reflejados en lo índices, hay que someterlos a comandos específicos. Los archivos de índices compuestos pueden almacenar varios ordenamientos, cada uno con un nombre diferente. Su extensión es CDX. Pueden ser no estructurales y estructurales. Los no estructurales tienen un nombre distinto al de la tabla que ordenan. Como sucede con los índices simples, deben someterse a comandos específicos para que reflejen los cambios en las tablas. Los archivos de índices estructurales tienen el mismo nombre de la tabla a la cual ordenan. Cuando se abre la tabla, todos los índices están disponibles y se actualizan automáticamente a medida que la tabla sufre cambios, sin necesidad de comandos específicos. Esto hace de los índices compuestos estructurales los más útiles, por lo que puede prescindirse de los anteriores. Para abrir una tabla con un índice compuesto estructural activo, se emite el comando USE con la opción ORDER. Para cambiar posteriormente el índice activo, se usa el comando SET ORDER. Tipos de índices Hay cuatro tipos de índices. – NORMAL. El índice permite que un mismo valor de la expresión se repita en diferentes registros y cada registro tiene su entrada en el índice. Entendamos por "entrada" la referencia en el índice a un registro particular en la tabla. Si hay 1 registro cuya expresión es A, 100 cuya expresión es B y 200 cuya expresión es C, habrá 1 entrada para A, 100 para B y 200 para C. En otras palabras, habrá tantas entradas como registros. Este tipo es adecuado, por ejemplo, para un archivo que contenga los artículos vendidos en un negocio, con una entrada de índice por cada vez que se hayan vendido. El esquema siguiente ilustra (1) —32— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 el campo CÓDIGO de la tabla VENTAS, en el orden de grabación, (2) los números de registro y (3) las entradas de un índice normal por la expresión Código, en orden ascendente, más el número del registro que la contiene. (1) Código 327 432 125 327 801 125 – (3) Expresión Registro 125 3 125 6 327 1 327 4 432 2 801 5 ÚNICO. El índice permite que un mismo valor de la expresión se repita en diferentes registros, pero si varios registros tienen el mismo valor en la expresión, habrá una sola entrada en el índice. Si hay 1 registro cuya expresión es A, 100 cuya expresión es B y 200 cuya expresión es C, habrá 1 entrada para A, 1 para B, 1 para C. Entonces, habrá una entrada por cada valor diferente de la expresión. Como cada entrada se refiere a un registro particular, ¿a cuál de los 100 registros de B y a cuál de los 200 de C se referirán? Pues al primero que se encuentre de uno y otro. Este tipo sirve para conocer, por ejemplo, cuáles artículos se han vendido. El esquema siguiente ilustra un índice único, con los supuestos del esquema anterior. Código 327 432 125 327 801 125 – (2) Registro 1 2 3 4 5 6 Registro 1 2 3 4 5 6 Expresión Registro 125 3 327 1 432 2 801 5 CANDIDATO. Este tipo obliga que la expresión no se repita en diferentes registros y cada registro tiene su entrada en el índice. Habrá entonces tantas entradas como registros. Si al construir el índice se encuentran valores repetidos, se da un mensaje de error y el proceso fracasa. Si el índice se construye con éxito y posteriormente se pretende duplicar el valor de la expresión en distintos registros de la tabla, se da un mensaje de error y se pide una decisión. Este tipo es adecuado, por ejemplo, para indexar la tabla ALUMNOS por la expresión Mu, porque es ilógico que haya varios alumnos con la misma matrícula. El mismo argumento vale para usar como expresiones el DNI, el número de cuenta bancaria, el número de empleado, etc. Los tres tipos vistos hasta aquí, normal, único y candidato, se pueden usar en tablas libres y en tablas base. Una tabla puede tener varios índices de cada tipo. – PRINCIPAL. Es igual en restricciones y funcionamiento al tipo candidato, pero se aplica solamente a las tablas base y puede haber uno solo por tabla. Tiene ventajas sobre los índices candidato. Expresiones complejas de índice. Str( ), Dtos( ) y Ttoc( ) Las expresiones de índice pueden estar formadas por el nombre de un campo, como Mu o Nombre. Pero también puede ser algo como Mu+2, Mu*8, etc. Esto es la razón por la cual se llama expresión de índice, no campo de índice. Un caso especialmente útil es cuando queremos indexar una tabla por más de un campo. Por ejemplo, indexar la tabla ALUMNOS por SEXO y NOMBRE en orden ascendente significa: (1) Disponer primero los registros con sexo F y luego los registros con sexo M; (2) Dentro de cada grupo, disponer los registros en orden alfabético por nombre. Activando el índice, la tabla ALUMNOS se vería como sigue. Mu 1702 4315 2388 Nombre Ávila, María Castro, Ana Ruiz, Marina Domicilio Mitre 7047 Solís 4214 Belgrano 1128 —33— Sexo F F F Nacido Argentino 25-10-1981 T 22-06-1980 T 02-08-1982 F Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 1377 2406 5201 3161 0257 0542 0645 Toro, Laura Alba, Alberto Cortés, Luis Gil, Raúl Oro, Eugenio Suárez, Jorge Vidal, Daniel Paso 339 Córdoba 175 Jujuy 8543 San Martín 5928 Roca 2928 Salta 101 La Rioja 2246 F M M M M M M 13-04-1979 17-05-1987 21-03-1982 30-01-1982 02-07-1988 05-10-1978 07-07-1980 T T T T T T T La expresión del índice anterior se debe escribir Sexo + Nombre. El + no es el operador suma, porque ambos campos son de caracteres. Es el operador de concatenación. Hay que tener cuidado con estos operadores, porque VFP los interpreta de una forma u otra, según la situación. Si la tabla contuviera los campos numéricos EDAD y MU, podríamos indexar por EDAD o por MU. Si la expresión fuera Edad + Mu, el resultado distaría mucho de lo correcto. Como ambos son campos numéricos, VFP resolvería la suma y ordenaría por el resultado. Activando el índice y examinando la tabla, los campos en cuestión aparecerían como sigue. A la derecha se da el resultado de la expresión, que se ha usado para indexar. Mu Edad 1200 20 1199 21 1410 28 1413 25 1500 20 Edad + Mu 1220 1220 1438 1438 1500 Una forma artificiosa de resolver el problema es inventar una fórmula aritmética. Por ejemplo, sabiendo que MU tiene ancho 6, la expresión podría ser Edad * 1000000 + Mu. La ilustración ahora sería la que sigue, mostrando la corrección de la fórmula usada como expresión. Mu Edad 1200 20 1500 20 1199 21 1413 25 1410 28 Edad * 1000000+ Mu 20001200 20001500 21001199 25001413 28001410 Más general y útil es usar funciones de conversión de tipos de datos. STR( ) convierte una expresión de tipo numérico a tipo carácter. Tiene un argumento obligatorio y dos opcionales, todos expresiones numéricas. El primer argumento es la expresión a convertir. El segundo indica cuántos caracteres se desean que tenga el resultado. Si se lo omite, el resultado tendrá un ancho establecido por VFP y se eliminarán los decimales originales, si los hay. El tercero indica cuántas posiciones decimales se quieren en el resultado. Los argumentos se separan por comas. La mejor forma de ver como funciona STR( ) es probándola con variables de memoria, como sigue. clear memory a = 12563.57 b = str(a) c = str(a, 5) d = str(a, 7, 1) e = str(a, 8, 2) f = str(a, 9, 3) g = str(a, 2) display memory like * Observe que la variable g tiene dos asteriscos como contenido. Se ha respetado el ancho, pero como es insuficiente, los asteriscos indican que la función ha fracasado. El índice por EDAD y MU, aplicando STR( ), puede usar la expresión str(edad,2) + str(mu,6). Lo más económico —34— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 y preciso es usar el ancho y decimales de cada campo, que en este caso se han omitido por ser 0. (Se ha supuesto que EDAD tiene ancho 2.) Si queremos construir un índice por la fecha de nacimiento, la expresión Nacido funcionará correctamente. Pero si queremos otro por SEXO y NACIDO, como un campo es de caracteres y el otro de fecha, no podemos usar la expresión Sexo + Nacido, porque todos los componentes deben ser del tipo carácter. Debemos valernos de la función DTOS( ), que transforma una expresión de tipo fecha o fecha–hora a caracteres. Tiene un argumento, que es la expresión a convertir. Si ésta es de fecha–hora, el resultado trunca la porción de hora. La expresión del índice, entonces, deberá ser sexo + dtos(nacido). Si NACIDO fuera de fecha–hora y quisiéramos un índice por este campo, la expresión Nacido funcionaría bien. Pero si quisiéramos otro por SEXO y NACIDO, conservando la parte de hora, la función a emplear sería TTOC( ). El primer argumento puede ser de fecha o fecha–hora. Si el primer argumento carece de la porción de fecha, se supone el 30-12-1899. Si carece de la porción de hora, se supone 12:00:00AM. Si se omite el segundo argumento, se obtiene una cadena de caracteres que responde al formato vigente. Si se usa un 1 como segundo argumento, el resultado es adecuado para expresiones de índice. Si se usa un 2, el resultado es solamente la porción de fecha. La expresión de índice, entonces, deberá ser sexo + ttoc(nacido, 1). Para construir un índice por NACIDO y MU, la expresión deberá ser dtos(nacido) + str(mu, 6), de caracteres, por ser el tipo común al cual se pueden convertir los componentes. Aplicación de índices Examine la tabla ALUMNOS y active el índice MU. Compruebe que no haya ningún número de matrícula repetido. Si los hay, cámbielos por otros, de modo que ninguno se repita. Modifique la estructura con VER – DISEÑADOR DE TABLAS o con MODIFY STRUCTURE. Active la ficha ÍNDICES. Cambie el tipo del índice MU por Principal y pulse ACEPTAR. Vuelva a examinar la tabla. Repita en el campo MU de un registro el valor que tiene en otro. Muévase por los demás campos del registro, sin salir de él. No se detecta la duplicación, porque mientras esté en el registro tiene tiempo de cambiar el número de matrícula por un valor aceptable. Trate de ir a otro registro, lo cual supone que da por terminado el trabajo sobre el registro con el problema. Ahora sí, aparece un mensaje diciendo que se ha violado la unicidad del índice MU. El botón ACEPTAR lo vuelve al registro erróneo, para que escriba otro valor aceptable. El botón VOLVER restablece el valor original del campo MU. Active el modo Añadir. Llene MU con un valor repetido y los demás campos con cualquier dato. Trate de ir a otro registro. Aparece el mismo mensaje de error. Pulse VOLVER y todo el registro que quiere añadir se pone en blanco. Salga con ESC y vuelva a examinar la tabla. El registro no se ha añadido, lo cual es inteligente, pues evita marcarlo para destruir y eliminarlo. Si en vez de elegir Principal para el índice MU hubiera elegido Candidato, el comportamiento de VFP sería el mismo que el descripto en el párrafo anterior. Cree ahora otro índice, de nombre y expresión Sexo y tipo Único. Examine la tabla y active el índice SEXO. Solamente aparecen dos registros, porque el propósito de estos índices es detectar cuáles valores distintos hay en la expresión, en este caso el campo SEXO. Si aparecen más de dos registros, es porque en SEXO se han introducido valores incorrectos, distintos a F y M. Los índices únicos tienen una entrada para el primer registro de un grupo con igual valor en la expresión. Suponga que hay tres registros con el valor erróneo G en SEXO. El índice único va a mostrar el primer registro con F, el primero con M y el primero con G. Si usted cambia la G por el valor F o M, el índice seguirá teniendo una entrada para ese registro, ahora correcto; pero los otros dos con G no tienen entrada. El índice, entonces, se ha vuelto incorrecto. La solución es volver a indexar la tabla, sea con TABLA – VOLVER A GENERAR ÍNDICES o con el comando REINDEX. Para probar expresiones complejas, cree varios índices, de acuerdo a las siguientes directivas. Nombre Sexonm sexonom nacidonm sexonacnm Tipo Normal Normal Normal Normal Expresión sexo + str(mu, 6) sexo + nombre dtos(nacido) + str(mu, 6) sexo + dtos(nacido) + str(mu, 6) —35— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 Dtoc( ) La función DTOC( ) también convierte una expresión de fecha a caracteres. La diferencia con DTOS( ) es que la conversión de ésta siempre es al formato AÑO–MES–DÍA, con el año en cuatro posiciones, sin separadores. DTOC( ), en cambio, puede convertir a varios formatos de fecha, respetando el que está vigente, es decir, lo establecido con SET DATE y SET CENTURY. Sean las fechas 31 de diciembre de 2004 y 1 de enero de 2005. Veamos qué ordenamiento ascendente produciría un índice usando DTOC( ) con tres formatos de SET DATE: set date dmy "01–01–2005" "31–12–2004" set date american "01–01–2005" "12–31–2004" set date ansi "2004–12–31" "2005–01–01" Los formatos DMY y AMERICAN provocan ordenamientos incorrectos. Para entenderlo, imagine que las fechas son números (no considere los guiones intermedios). En este supuesto, el ordenamiento es correcto. Es lo que ha hecho VFP, ordenando sin tener en cuenta el orden cronológico, sino el orden de los caracteres resultantes de la función. El formato ANSI, en cambio, es correcto, porque primero va el año, luego el mes y finalmente el día. La conclusión es que DTOC( ) no es adecuada para crear índices. Anteriormente se la corregía con un segundo argumento, 1, separado con una coma del primero. Con esta corrección, la función funciona como DTOS( ). Como es posible que se olvide del segundo argumento, recomendamos usar DTOS( ) para crear índices y DTOC( ) para convertir una fecha a caracteres, para usar, por ejemplo, en un título. Iif( ) Hemos visto que, para crear expresiones complejas de índice, si los campos componentes no son de caracteres, debemos usar las funciones STR( ), DTOS( ) y TTOC( ), según corresponda, para obtener una expresión final de caracteres. Nada dijimos sobre cómo tratar los campos lógicos. No hay una función que trasforme de tipo lógico a tipo carácter. Pero podemos recurrir a la función IIF( ), que permite lograrlo indirectamente. IIF( ) tiene tres argumentos. El primero es una expresión lógica. Si la expresión es verdadera, la función devuelve el segundo argumento; si es falsa, devuelve el tercero. El segundo y tercer argumentos pueden ser de cualquier tipo de datos. Pruebe lo que sigue. ? iif(3 + 2 = 5, "Correcto", "Incorrecto") ? iif(3 + 2 = 5, "Correcto", date( )) ? iif(3 + 2 = 5, 24, time( )) ? iif(3 + 2 = 5, .T., date( )) Como los argumentos de las funciones pueden ser otras funciones, entonces IIF( ) puede incluir otras IIF( ). a = 10 ? iif(a = 10, "Igual", iif(a > 10, "Mayor", "Menor)) sexo = "M" edad = 35 ? iif(sexo = "M", iif (edad >= 21, ; "Hombre mayor", "Hombre menor"), ; iif(edad >= 21, "Mujer mayor", ; "Mujer menor")) El último comando ha sido escrito en varias líneas. Cuando un comando tiene mucho texto, puede escribirse en tantas líneas como quiera, terminando cada una con un punto y coma, excepto la última. Observe lo siguiente, porque es muy práctico. vive = .T. ? iif (vive = .T., "Vivo", "Fallecido") ? iif (vive, "Vivo", "Fallecido") La expresión vive = .T. se puede escribir simplemente vive, porque VFP supone que el nombre de la variable o campo lógico representa contenido verdadero. Su contraria, vive = .F., puede lograrse negando el nombre. La negación es una operación lógica, que se expresa con el operador NOT o su equivalente ! (signo de exclamación derecho). Vive = .F. se puede lograr, entonces, con not vive o ! vive. ? iif (not vive, "Fallecido", "Vivo") Con lo aprendido sobre IIF( ), podríamos crear un índice para la tabla ALUMNOS por los campos ARGENTINO y MU. La expresión debe ser de caracteres, para lo cual sabemos como tratar a MU. Para convertir a ARGENTINO, usaremos la siguiente convención: si es verdadero, lo transformaremos en A; si no lo es, lo transformaremos en E (de extranjero). La expresión del índice, entonces, será iif(argentino, "A", "E") + str(mu, 6). —36— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 Bases de datos Una base de datos es un archivo "contenedor" de tablas y otras cosas, con extensión DBC. Por contenedor no entendemos una caja donde entren físicamente las tablas, sino un contenedor virtual, es decir, un archivo donde se las registra, de modo que puedan manejarse desde ahí con grandes ventajas. Creación de una base de datos Para crear una base de datos se puede usar ARCHIVO – NUEVO, elegir el tipo Base de datos en el diálogo NUEVO y pulsar el botón NUEVO ARCHIVO. Se abre el diálogo CREAR para elegir una carpeta y dar un nombre al archivo a crear. Create database El comando para crear una base de datos es CREATE DATABASE, seguido por el nombre de la base de datos. Hay otras formas de crearla. Siguiendo cualquier procedimiento explicado, cree la base de datos ALUMNOS. Ahora va a tener un tabla y una base de datos con el mismo nombre. No hay problemas, porque son archivos de tipo distinto. Aparece el DISEÑADOR DE BASES DE DATOS vacío, en cuyo título tiene el nombre, Alumnos. También está la barra DISEÑADOR DE BASE DE DATOS, que puede mover, variar en tamaño y cerrar. Ciérrela. Como es muy útil, vuelva a abrirla con VER – BARRA DE HERRAMIENTAS. En el diálogo de igual nombre, active DISEÑADOR DE BASES DE DATOS y pulse ACEPTAR. Barra de herramientas Diseñador de bases de datos Veamos algunos de los botones que contiene. – NUEVA TABLA. Sirve para crear una nueva tabla. Búsquelo, demorando el mouse en cada botón, hasta que aparezca el nombre en un pequeño rectángulo amarillo. Púlselo, pero cancele el diálogo NUEVA TABLA, porque no vamos a crear ninguna. – AGREGAR TABLA. Registra una tabla existente en la base de datos. Púlselo. Aparece el diálogo ABRIR. Elija la tabla ALUMNOS y pulse ACEPTAR. Ahora se ve una ventanita en el diseñador, que representa la tabla agregada y se llama CURSOR. Su título es Alumnos. La primera línea dice Campos, seguida por otras con el nombre de cada campo. Luego otra línea dice Índices, seguidas por otras con el nombre de cada índice. Si no ve todas las líneas en el cursor, puede modificar su tamaño o usar la barra de desplazamiento vertical. Agregue también la tabla COPIA. – EXAMINAR TABLA. Abre la ventana EXAMINAR para la tabla seleccionada. Seleccionar la tabla es lo mismo que seleccionar el cursor. Seleccione ALUMNOS y pulse el botón EXAMINAR. Active el diseñador. Si no está visible, porque las dimensiones de la ventana EXAMINAR no dejan verlo, elíjalo en la lista de ventanas abiertas del menú VENTANA. Seleccione COPIA y pulse el botón EXAMINAR. Para examinarlas, si estaban cerradas, VFP abre las tablas. Ahora tiene dos ventanas EXAMINAR abiertas, más la ventana del diseñador, y quizás la ventana COMANDOS, si estaba abierta. Puede ver las cuatro a la vez si cambia sus dimensiones a mano. Puede resultarle más fácil emitir VENTANA – ORGANIZAR TODO. Cierre ambas ventanas EXAMINAR y maximice el diseñador. – MODIFICAR TABLA. Permite modificar la estructura de la tabla seleccionada, para lo que abre el DISEÑADOR DE TABLAS. Seleccione ALUMNOS y púlselo. ¿Observe algo nuevo? el DISEÑADOR DE TABLAS tiene varias cosas, debajo de los campos, que antes no tenía. ¿Qué pasó? Para agregar una tabla a una base de datos, la tabla debe ser libre. Una vez agregada, se convierte en tabla de base de datos, o más brevemente tabla base. Las tablas base tienen más posibilidades estructurales que las tablas libres. Esto las hace superiores, como veremos. Cancele la modificación. – QUITAR TABLA. Elimina la tabla seleccionada. Seleccione COPIA y pulse el botón. Aparece un mensaje preguntando si la quiere eliminar definitivamente del disco, es decir, destruirla para siempre, o quitarla de la base de datos, esto es, hacerla libre. Si eligiera quitarla, puede que se pierdan las posibilidades estructurales de que carecen las tablas libres y que se pierdan otras cosas más, por lo que se le pregunta si quie—37— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 re hacerlo. Cancele la operación. El diseñador modifica la barra de menús y tiene menús contextuales propios. Éstos se activan dando clic secundario: según el contexto dónde se lo dé serán las opciones que presente. Menús contextuales del diseñador de bases de datos Dé clic secundario en el diseñador, donde no hay cursores. Aparecen varias opciones, de las cuales nos interesan las siguientes, que debe ir probando. – CONTRAER TODO. Contrae todos los cursores a sus barras de título. – EXPANDIR TODO. Vuelve todos los cursores contraídos a sus tamaños anteriores. – BUSCAR OBJETO. Presenta el diálogo BUSCAR TABLA O VISTA con un listado de estos objetos, para seleccionar uno y activarlo con el botón BUSCAR. Es útil si hay gran cantidad de tablas y vistas. – NUEVA TABLA y AGREGAR TABLA. Hacen lo mismo que los botones de la barra. – PROPIEDADES. Presenta el diálogo PROPIEDADES DE LA BASE DE DATOS, donde se configura lo que se quiere ver en ella: tablas, vistas locales, vistas remotas, relaciones. Por ahora sólo puede probar TABLAS. Quítele la tilde y pulse ACEPTAR. Ahora el diseñador no muestra las tablas. Vuelva a poner la tilde para verlas. Dé clic secundario sobre un cursor. Aparece un menú contextual. Las opciones que nos interesan son las siguientes. – EXAMINAR, ELIMINAR y MODIFICAR. Hacen lo mismo que los botones de la barra de herramientas. – CONTRAER. Contrae el cursor seleccionado a la barra de títulos. Si está contraído, la opción cambia a EXPANDIR, que restaura el cursor al tamaño previo. Hay otro menú contextual, sobre las relaciones, que por ahora no podemos ver. Opciones de menú en el diseñador de bases de datos Los diseñadores y algunas ventanas, como EXAMINAR, modifican la barra de menús, sea agregando o quitando opciones en los menús habituales, sea agregando nuevos menús. La ventana EXAMINAR, como vimos, agrega el menú TABLA. El diseñador de bases de datos agrega el menú BASE DE DATOS, con algunas opciones que ya conoce, sea porque están en la barra de herramientas, en los menús contextuales o en el menú TABLA de la ventana EXAMINAR. Son las siguientes: NUEVA TABLA, AGREGAR TABLA, MODIFICAR, EXAMINAR, QUITAR, BUSCAR OBJETO, VOLVER A GENERAR ÍNDICES DE TABLAS, QUITAR REGISTROS ELIMINADOS y PROPIEDADES. Las que no conoce son las que siguen. – ORGANIZAR. Presenta el diálogo ORGANIZAR TABLAS Y VISTAS, con opciones para ordenar los cursores. Note que hay una opción para dar a todos los cursores el tamaño predeterminado, útil cuando se los ha modificado por arrastre. – LIMPIAR BASE DE DATOS. Una base de datos, aunque le parezca extraño, es una tabla. Para diferenciarla de las tablas del usuario, su extensión es DBC. Tiene un archivo de índices compuesto estructural, con extensión DCX, y un archivo de campos memo, con extensión DCT. Su estructura está predefinida y la genera VFP al crearla. En lo demás, es una tabla como las que conoce. Cuando se agrega una tabla convencional a una base de datos, se agregan varios registros en ésta para definirla. Si quita la tabla, esos registros se marcan para destruir. Si quiere eliminar definitivamente los registros marcados, porque aumentan innecesariamente el tamaño del archivo, se usa esta opción. Salga del DISEÑADOR DE BASES DE DATOS con ESC, el botón de cierre o ARCHIVO – CERRAR. Close databases El comando para cerrar bases de datos es CLOSE DATABASES. Si no se agrega nada más, cierra la base de datos activa y sus archivos dependientes (tablas, índices, memo). Si agrega la palabra ALL, cierra todas las bases de datos abiertas y sus archivos dependientes, incluso las tablas libres abiertas, sus índices y sus memo. También puede cerrarlas todas, con un efecto aún más amplio, con CLOSE ALL. —38— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 Apertura de una base de datos Para abrir una base de datos use ARCHIVO – ABRIR, elija Base de datos (*.cdx) en TIPO DE ARCHIVOS del diálogo ABRIR, seleccione el archivo y pulse ACEPTAR. Esto presenta la base de datos en el diseñador. Open database El comando OPEN DATABASE seguido por el nombre del archivo DBC abre la base de datos, pero no el diseñador. Puede haber varias bases de datos abiertas, pero sólo una es la activa. Modificación de una base de datos Si abre una base de datos con ARCHIVO – ABRIR, se presenta en el DISEÑADOR DE BASES DE DATOS, donde puede modificarla. Modify database El comando MODIFY DATABASE, sin agregados, abre el diseñador para modificar la base de datos activa. Si se le agrega un nombre, presenta la base de datos de tal nombre en el diseñador, abriéndola si hace falta, para modificarla. Si la base de datos no existe, la crea. Propiedades exclusivas de las tablas base Ahora tenemos las tablas ALUMNOS y COPIA. La segunda no sirve, porque la hemos usado para ilustrar el agregado de registros a una tabla desde otra. Déjela por ahora. En la vida real, los alumnos rinden exámenes, que aprueban o no. Necesitaremos una tabla EXÁMENES, para las notas de las materias rendidas, y una tabla MATERIAS, para los códigos y nombres de las materias. Abra el DISEÑADOR DE BASES DE DATOS. Cree una nueva tabla, EXÁMENES, con esta estructura: Nombre Mu Materia Fecha Nota Tipo Numérico Numérico Fecha Numérico Ancho 6 2 8 2 Decimal Índice Null 0 ↑ 0 ↑ 0 Supongamos 30 materias distintas, del 1 al 30, y notas del 0 al 10, sin decimales. Cuando ingresemos datos, podemos hacer que VFP rehúse materias fuera del intervalo 1 – 30 y notas fuera del intervalo 0 – 10. Si cometemos errores, queremos que nos avise a través de un mensaje. Seleccione el campo MATERIA. Dentro del recuadro VALIDACIÓN DE CAMPO hay una opción REGLA, con un cuadro de texto y un botón de tres puntos. La regla para controlar que las materias estén en el intervalo 1 – 30 se puede expresar between(materia, 1, 30). Escríbala directamente o usando el GENERADOR DE EXPRESIONES. Debajo está la opción MENSAJE. Si la deja en blanco, VFP dará un mensaje estándar si se ingresa un valor incorrecto. Pero es mejor escribir un mensaje adecuado, como "Materia debe variar entre 1 y 30.". Puede escribirlo en el cuadro de texto; pero vaya al GENERADOR DE EXPRESIONES, abra la lista CADENA y elija "texto". Esto produce un par de comillas, con el punto de inserción entre ellas, evitándole escribirlas. No es de mucha ayuda, pero es algo. El mismo recurso existe para escribir delimitadores de fecha, paréntesis, operadores y funciones. Escriba el texto del mensaje. Seleccione el campo NOTA. Escriba la regla between(nota, 0, 10) y el mensaje "Nota debe variar entre 0 y 10.". Observe el cuadro de edición COMENTARIO DE CAMPO. Cada campo tiene el suyo propio, por si desea escribir un texto con aclaraciones sobre él. El nombre del campo MU puede resultar poco claro para quien examina la tabla. Mejor sería que apareciera Matrícula en la ventana EXAMINAR. En el recuadro MOSTRAR, escriba Matrícula en la opción TÍTULO. Guarde la tabla sin agregar registros. Modifique la tabla ALUMNOS. En el campo MU escriba Matrícula en TÍTULO. En el campo SEXO, para controlar que los códigos aceptables sean F o M, en REGLA escriba inlist(sexo, "F", "M") y en MENSAJE escriba "Sexo debe ser F o M.". Los códigos deben estar en mayúscula, pero al llenarlo puede que se los introduzca en mi—39— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 núscula. Para que VFP los convierta automáticamente a mayúscula, en FORMATO escriba el código ! (signo de exclamación derecho). Hay varios códigos de formato, que afectan a todo el dato que se ingrese al campo. En particular, el código ! convierte a mayúscula cualquier letra que se introduzca en cualquier posición del campo. Como SEXO tiene ancho 1, el efecto se reducirá a esa única posición. Siendo SEXO un campo de caracteres, podríamos ingresar cualquier carácter; si es una letra, el código de formato la va a convertir a mayúscula; pero la regla exigirá que lo ingresado sea una F o una M. Esto logrará que el valor del sexo sea correcto. Los códigos de formato tienen un ámbito de aplicación bastante mayor al diseño de tablas, pudiéndose aplicar en otros contextos. La opción MÁSCARA DE ENTRADA, que no usaremos por ahora, también usa códigos. Pero, a diferencia de los códigos de formato, que afectan a la totalidad del campo, se usan para definir lo que se quiere, posición a posición. Así, los códigos A y 9 indican que en el lugar donde aparecen debe ingresarse una letra y un número, respectivamente. Para una patente de automóvil, la máscara de entrada sería AAA999. Para que las letras sean convertidas a mayúscula, debería usar el código de formato !, como ya sabe. La opción VALOR PREDETERMINADO permite definir un valor que va a tomar el campo en cada nuevo registro que se añada a la tabla. El valor predeterminado es el que ocurre con más frecuencia, de modo que al agregar un nuevo registro, aparecerá inicialmente lleno con este valor, evitándonos tener que escribirlo. Esto no significa que posteriormente no se pueda cambiar por otro valor. Por ejemplo, para el campo ARGENTINO se puede dar el valor .T., porque se supone que la mayoría de los alumnos son argentinos. Si alguno no lo fuera, se puede cambiar por .F. Cree la tabla MATERIAS, con la siguiente estructura: Ancho Decimal Índice Null Nombre Tipo Materia Numérico 2 0 Nombre Carácter 30 En la ficha ÍNDICES, cree el índice de nombre y expresión Materia y de tipo principal. Guarde la tabla sin agregar registros. Use la tabla EXÁMENES. Vamos a agregarle varios registros, con números de matrícula existentes en la tabla ALUMNOS. Para no trabajar a mano, valgámonos de la tabla COPIA, que tiene registros repetidos para cada matrícula. El único campo coincidente en nombre y tipo con EXÁMENES es el campo MU. Llenaremos los restantes campos a mano. Agregue a EXÁMENES todos los registros de COPIA, valiéndose de TABLA – AÑADIR REGISTROS o APPEND FROM. Examine EXÁMENES y active el índice MU. Llene el campo MATERIA de cada registro, con números entre 1 y 30. Luego complete el campo FECHA, más tedioso. Finalmente llene el campo NOTA, con números entre 0 y 10. Si tiene ganas, puede agregar registros nuevos a mano, siempre que las matrículas repitan números de los registros agregados automáticamente, porque sería incorrecto registrar un examen para un alumno inexistente. Use la tabla MATERIAS. Agréguele 30 registros, llenado el campo MATERIA con 1, 2, …, 30. Complete el campo NOMBRE con nombres de asignaturas como Matemáticas, Historia, Economía, etc. La ficha TABLA del DISEÑADOR DE BASE DE DATOS permite controlar aspectos adicionales. Esto no sucede en las tablas libres. El aspecto más importante es la VALIDACIÓN DE REGISTROS, que abarca una regla y un mensaje. En la ficha Campos hemos visto que el contenido de cada campo se controla con una regla de validación para cada uno, pudiendo personalizar un mensaje de error para el caso de infringir la regla. Pero ello es insuficiente para controlar la coherencia entre los valores de dos o más campos. Para hacerlo, hay que usar reglas de validación a nivel de registro. Supongamos una empresa que tiene tres sucursales con distintas secciones, según el siguiente esquema: Sucursal Secciones 1 A, B 2 C, D 3 E, F —40— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 Sea que los campos que contienen la surcursal y la sección se llamen SUC y SEC. Para dar el campo SUC por correcto, se puede usar la regla de validación between(suc, 1, 3). Para hacerlo con el campo SEC, se puede usar la regla between(sec, 'A', 'F'). Estas reglas, sin embargo, no impedirán que se ingresen valores erróneos, como 2 en SUC y A en SEC. Para controlar el error anterior, hay que usar una regla de validación a nivel de registro, que para el ejemplo podría ser: suc = 1 and between(sec, A,BD) or suc = 2 and between(sec, C, D) or suc = 3 and between(sec, E, F) Al ingresar datos, la regla que valida el registro se comprueba cuando se intenta ir a otro registro. Si la regla no se cumple, VFP da un mensaje de error, personalizado o estándar, según se haya o no definido un mensaje del usuario, y no abandona el registro erróneo. Áreas de trabajo. In, Order y Noupdate de Use. Select Hasta ahora, todas las veces que hemos usado una tabla, no hemos tenido ninguna precaución. Las tablas abiertas podían ser modificadas, ya sea cambiando el contenido de sus campos, agregando registros o marcando registros para destruir. Incluso si no alteráramos su contenido, las tablas abiertas podrían ser dañadas por un corte de energía eléctrica. Para abrir las tablas sin permitir cambiarle ni una coma, hay que usar el comando USE con la cláusula NOUPDATE. Una tabla abierta de este modo se dice de “sólo lectura”. Una tabla abierta sin esta protección se dice de “lectura / escritura”. Vea, en el ejemplo que sigue, que no podrá modificar el contenido de ALUMNOS: set status bar on close tables all use alumnos noupdate order mu browse En programación, como norma general, es muy conveniente abrir siempre las tablas en modo sólo lectura, excepto que el propósito sea modificarlas. La cláusula ORDER de USE abre una tabla, activando simultáneamente uno de sus índices. La tabla ALUMNOS ha sido abierta activando el índice MU. La cláusula IN de USE abre una tabla en un área de trabajo. Un área de trabajo es una porción de memoria que contiene registros de una tabla abierta. Los registros están grabados en disco, de modo que en el área de trabajo se coloca una copia de ellos. Si la tabla es muy grande, en el área de trabajo se copia un grupo de registros, luego otro, etc. Hay miles de áreas de trabajo posibles, que se numeran 1, 2, 3, etc. En cada área se puede abrir una tabla, para lo cual hay que seleccionarla. Cuando se emite un comando que cierra todas las tablas, como CLOSE TABLES ALL, se selecciona el área 1. Por ello el comando USE ALUMNOS NOUPDATE ORDER MU abrió la tabla en el área 1. Para abrir la tabla EXÁMENES en otra área, se puede seleccionar un número de área con el comando SELECT y luego emitir USE. Por ejemplo: select 2 use exámenes order mu noupdate Una forma más práctica consiste en usar SELECT 0. Esto hace que se seleccione el área de trabajo no usada de menor número, desobligando de llevar cuenta de los números de área. El ejemplo anterior podría haber sido: select 0 use exámenes order mu noupdate El área también se puede seleccionar en el mismo comando USE, con la cláusula IN N, donde N es un número positivo, o IN 0. Las formas anteriores, respectivamente, se pueden reemplazar como sigue: use exámenes in 2 order mu noupdate y mejor aún con use exámenes in 0 order mu noupdate La mejor forma, como puede advertir, es ésta última. Haga: use exámenes in 0 order mu noupdate Una tercera forma de seleccionar un área, posible cuando el área ya tiene una tabla abierta, es usar el comando SELECT seguido por el nombre de la tabla. Corrobore esto, observando la barra de estado: select exámenes go 5 —41— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 select alumnos go bottom ? recno( ) ? recno("alumnos") ? recno("exámenes") —42— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 Relaciones e Integridad referencial Cada tabla contiene registros con datos de entidades similares. En una aplicación típica, los registros de una tabla están asociados con registros de otra tabla. Por ejemplo, una tabla con datos personales de los alumnos tendrá matrícula, nombre, sexo, domicilio, teléfono, DNI. Una tabla de exámenes tendrá matrícula, carrera, asignatura, fecha, nota. Ambas tablas son complementarias: para un registro de la tabla de alumnos, puede haber uno o más registros en la otra, con los exámenes dados por ese alumno. Los registros de ambas tablas, evidentemente, se vinculan por un dato en común, la matrícula. VFP puede producir esta asociación entre los registros de ambas tablas mediante relaciones. Una relación es un vínculo dirigido desde una tabla a otra, por uno o más campos comunes. La tabla de donde parte la relación se llama madre,principal o parent y la tabla donde termina la relación se llama hija, secundaria o child. Por ejemplo, podríamos relacionar la tabla de alumnos con la de exámenes por el campo matrícula, logrando entonces que, cuando estemos colocados en el registro de un alumno, solamente estén disponibles los registros de exámenes correspondientes a tal alumno. Matríc. 8 ►2 17 43 5 83 Nombre Gómez, Pedro Arce, Luis Vega, Alberto Alamo, Estela Juárez, Esteban Pérez, Norma Sexo M M M F M F Matríc. 2 2 2 2 Carrera 10 10 10 10 Materia 01 03 02 05 Fecha 06/07/2001 25/07/2001 17/11/2001 07/12/2001 Nota 8 7 10 9 En sentido inverso, podríamos relacionar la tabla de exámenes con la de alumnos por el campo matrícula, logrando que, cuando estemos colocados en un examen, solamente esté disponible el registro del alumno correspondiente. Matríc. 8 ►2 17 2 5 83 Carrera 11 10 08 10 10 10 Materia 24 03 18 05 03 04 Fecha 05/07/2001 25/07/2001 02/03/2001 07/12/2001 16/09/2000 26/11/2000 Nota 5 7 8 9 7 4 Matríc. 2 Nombre Arce, Luis Sexo M En el primer ejemplo, a un registro de la madre corresponden varios registros en la hija. Esta relación se llama de uno a varios, que representaremos 1 — N. En el segundo ejemplo, a un registro de la madre corresponde uno en la hija. Esta relación se llama de uno a uno, que representaremos 1 — 1. En los ejemplos anteriores, vemos que las madres no necesitan un orden determinado, aunque puedan tenerlo. Por el contrario, para que un registro de la madre encuentre su registro o registros correspondientes en la hija, es necesario que ésta posea un índice por el campo matrícula y que esté activo. Siempre es necesario que la hija posea un índice adecuado para construir una relación. En cuanto a la madre, puede o no requerirlo, según el tipo de relación a construir, como veremos en seguida. Relaciones transitorias Se construyen fuera del DISEÑADOR DE BASE DE DATOS. Duran hasta que un comando las desactive o se cierre una de las tablas. Pueden construirse usando uno de los siguientes recursos. • En el entorno de informes y formularios. Habiendo agregado las tablas a relacionar, se arrastra desde el campo de la madre al índice de la hija. También puede arrastrarse desde el campo de la madre al campo de la hija, siempre que ésta tenga un índice por tal campo. Si el índice usa una expresión compleja sobre el campo, hay que modificar la propiedad RelationalExpr de la relación, de modo que el campo de la madre que va a buscar en el índice de la hija quede de acuerdo a la expresión. Por ejemplo, si el campo matrícula en la madre se llama MU y el mismo campo en la hija se llama MATRÍCULA, siendo que el índice de —43— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 ésta está construido por la expresión str(matrícula,8), la propiedad RelationalExpr deberá ser str(mu,8). • En el cuadro de diálogo SESIÓN DE DATOS del menú VER. Hay que agregar las tablas a relacionar. Se selecciona la madre y se pulsa el botón RELACIONES. Esto coloca la madre en el panel derecho y traza una línea de relación sin hija. Se selecciona la hija, con lo que se abre el diálogo ESTABLECER ORDEN DE ÍNDICE, para elegir el índice de la hija a usar. Luego de ello, se abre el GENERADOR DE EXPRESIONES, para construir la expresión relacional con el campo buscador de la madre. • En procedimientos. Previamente hay que abrir las tablas a relacionar y activar el índice de la hija a usar en la relación. Luego se emite SET RELATION TO, indicando la expresión relacional construida con el campo buscador de la madre, la palabra INTO y la tabla hija. Si la expresión del índice de la hija está construida por varios campos, la expresión relacional puede incluir a todos o sólo a algunos campos buscadores de la madre, de izquierda a derecha. Por ejemplo, si se quiere relacionar la tabla ENCFAC con la tabla LINFAC. Sea que ENCFAC tenga los campos FACTURA, FECHA y CLIENTE, y que LINFAC tenga los campos NÚMERO, ARTÍCULO, CANTIDAD y PRECIO, donde NÚMERO es el número de factura. También tiene el índice NÚMERO, cuya expresión es str(número,5)+artículo. Como en ENCFAC no existe el campo ARTÍCULO, podemos usar la expresión relacional str(factura,5). En este ejemplo, estamos ante un caso de expresión relacional parcial, que realizará la búsqueda siempre que SET EXACT valga OFF. Ampliación de una relación Las relaciones transitorias inicialmente son 1 — 1, es decir, al seleccionar un registro cualquiera en la tabla madre, se selecciona el primer registro correspondiente de la tabla hija. Si abrimos dos ventanas EXAMINAR, una para la tabla madre y otra para la tabla hija, al elegir un registro cualquiera en la madre veremos todos los registros correspondientes de la hija, como indica el siguiente ejemplo: Matríc. 8 ►2 17 43 5 83 Nombre Gómez, Pedro Arce, Luis Vega, Alberto Alamo, Estela Juárez, Esteban Pérez, Norma Sexo M M M F M F Matríc. 2 2 2 2 Carrera 10 10 10 10 Materia 01 03 02 05 Fecha 06/07/2001 25/07/2001 17/11/2001 07/12/2001 Nota 8 7 10 9 Lo que presenta la segunda ventana EXAMINAR es una visualización de los registros correspondientes al registro madre, lo cual parece indicar que la relación es 1 — N. Pero no es así, porque el registro hijo seleccionado es el primero. En este escenario, para cambiar de registro hijo hay que seleccionar la segunda ventana EXAMINAR y moverse al registro deseado. Desde la tabla madre es imposible recorrer los registros hijos. Sin embargo, hay una manera de simular registros "ficticios" en la tabla madre, tantos como hagan falta para igualar la cantidad de registros relacionados en la hija. Esto es una ampliación de la relación, que ahora se dice 1 — N. Activando esta modalidad, las tablas anteriores se verían como indica la ilustración que sigue. En este nuevo escenario, ahora se puede avanzar por la madre tantos registros como registros con la misma matrícula haya en la hija. El sombreado indica la repetición del registro inmediatamente anterior. Matríc. Nombre 8 Gómez, Pedro ►2 Arce, Luis 17 43 Vega, Alberto Alamo, Estela Sexo M M Matríc. 2 2 2 2 M F —44— Carrera 10 10 10 10 Materia 01 03 02 05 Fecha 06/07/2001 25/07/2001 17/11/2001 07/12/2001 Nota 8 7 10 9 Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 5 83 Juárez, Esteban Pérez, Norma M F La ampliación es útil para ciertas aplicaciones, como el caso de informes que usan datos de ambas tablas. En los informes, la tabla madre siempre está seleccionada, por lo que no hay modo de seleccionar la tabla hija. Para que la madre procese todos los registros hijos, debe irlos seleccionado uno por uno. Esto se logra ampliando la relación. La ampliación también es útil para el caso de un solo Grid que muestre a la vez campos de ambas tablas relacionadas, como el siguiente. Matríc. 8 2 17 43 5 83 Nombre Gómez, Pedro Arce, Luis Carrera Materia Fecha Nota 5 17 08/07/2001 8 10 01 06/07/2001 8 10 03 25/07/2001 7 10 02 17/11/2001 10 10 05 07/12/2001 9 Vega, Alberto 8 06 12/07/2001 5 Alamo, Estela 2 12 06/07/2001 6 2 14 08/07/2001 2 Juárez, Esteban 10 03 25/07/2001 6 Pérez, Norma 10 05 07/12/2001 7 Para ampliar una relación 1 — 1 en 1 — N, hay varios procedimientos: • En el entorno de datos de informe o formulario, se hace .T. la propiedad OneToMany de la relación. • En el cuadro Sesión de Datos, una vez establecida la relación, se pulsa el botón 1 A VARIOS y se establece cuál es la tabla hija con la cual se quiere ampliar la relación. • En procedimientos, se establece la relación con SET RELATION y luego se da el comando SET SKIP. Relaciones permanentes Se construyen dentro del Diseñador de Base de Datos. Duran indefinidamente, mientras no sean eliminadas explícitamente en la base de datos o no se quite o elimine de ella alguna de las tablas involucradas. Las relaciones permanentes debe partir de un índice principal o candidato de la madre y terminar en un índice de cualquier tipo en la hija. Si el índice de la tabla hija es principal o candidato, la relación es 1 — 1. Si ese índice es normal o único, la relación es 1 — N. Vea la ilustración que sigue. Alumnos Campos matrícula nombre sexo domicilio dni Indices ¶matrícula nombre Exámenes Campos matrícula carrera materia fecha nota Indices matrícula Una relación permanente genera inicialmente una relación transitoria de igual sentido cuando se introducen las tablas involucradas en un entorno de datos. Si en la aplicación se necesita el sentido inverso, es necesario destruir la generada inicialmente en el entorno y trazarla como se necesita, lo cual no significa que se destruya en la base de datos. —45— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 Integridad referencial El propósito de las relaciones permanentes es establecer ciertas reglas que controlen las altas, bajas y cambios en la tablas madre e hija, llamadas reglas de integridad referencial. Las reglas se definen para cada relación, según sigue. Para ejemplificar, usaremos dos tablas: Alumnos, con los datos personales de los alumnos, y Exámenes, con los datos de los exámenes rendidos por los alumnos. Reglas para la actualización. Se refieren a qué permitiremos cuando intentemos cambiar un valor clave en la madre, es decir, el campo o campos por el que está construido el índice de donde parte la relación. Hay tres reglas posibles, mutuamente excluyentes. • CASCADA. Permite cambiar un valor clave en la madre, cambiando automáticamente los valores correspondientes en la hija. Si cambiamos la matrícula de un alumno en Alumnos, cambiarán todas las matrículas iguales en Exámenes, conservando la correspondencia entre los registros de una y otra tabla. • RESTRINGIR. Impide cambiar un valor clave en la madre, si tiene registros relacionados en la hija. Si un alumno tiene exámenes, no podrá cambiarse su matrícula en la madre. Cuando el registro de la madre no tiene correspondientes, el cambio puede hacerse sin inconvenientes. Si un alumno todavía no ha dado exámenes, podremos cambiar su matrícula. • IGNORAR. Permite cambiar un valor clave en la madre, sin trasmitir los cambios a los valores correspondientes en la hija. Más que una regla, es la carencia de ella. Es el valor inicial al construir una relación permanente. Reglas para la eliminación. Se refieren a qué permitiremos cuando intentemos marcar para eliminación un registro en la madre. Hay tres reglas posibles, mutuamente excluyentes. • CASCADA. Permite marcar un registro en la madre, marcando automáticamente los registros relacionados en la hija. Si marcamos un registro en Alumnos, serán marcados todas los registros correspondientes en Exámenes. Hay que tener cuidado: si desmarcamos el registro de la madre, no son desmarcados los registros relacionados en la hija. • RESTRINGIR. Impide marcar un registro en la madre, si tiene registros relacionados en la hija. Para poder marcarlo, previamente habrá que eliminar físicamente los registros relacionados en la hija. Cuando el registro de la madre no tiene correspondientes, el marcado puede hacerse sin inconvenientes. Si un alumno todavía no ha dado exámenes, podremos marcar su registro. • IGNORAR. Permite marcar un registro en la madre, sin trasmitir las marcas a los registros correspondientes en la hija. Es el valor inicial al construir una relación permanente. Reglas para la inserción. Se refieren a qué permitiremos cuando intentemos añadir un registro en la hija. Hay dos reglas posibles, mutuamente excluyentes. • RESTRINGIR. Impide añadir un registro en la hija, si no tiene un registro relacionado en la madre. Para poder añadirlo, previamente habrá que añadir un registro de igual clave en la madre. Si queremos añadir un registro en Exámenes para una matrícula que no existe en Alumnos, no podremos hacerlo. La regla tiene también otra consecuencia: si se cambia el valor clave en la hija, podrá hacerse siempre que exista un valor correspondiente en la madre. Si cambiamos la matrícula de un examen, será admitido siempre que haya un registro en Alumnos con tal matrícula. • IGNORAR. Permite añadir un registro en la hija, sin que tenga un correspondiente en la madre. Es el valor inicial al construir una relación permanente. —46— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 Sesión de datos Veamos una forma fácil de abrir tablas, activar índices y establecer relaciones, sin necesidad de comandos. Para ello usaremos VENTANA – SESIÓN DE DATOS. Este comando trae el diálogo SESIÓN DE DATOS, cuyas opciones más sencillas son las siguientes. – ABRIR. Muestra un cuadro de diálogo ABRIR, para seleccionar y abrir una tabla o vista. Si no hay bases de datos abiertas, el diálogo es el convencional de ARCHIVO – ABRIR. Si hay por lo menos una base de datos abierta, toma la forma del diálogo AGREGAR TABLA O VISTA, pero con el título ABRIR, cuyas opciones son: ● BASE DE DATOS. Muestra la base de datos actual y permite seleccionar otra base de datos abierta. ● TABLAS/VISTAS DE LA BASE DE DATOS. Muestra las tablas o las vistas de la base de datos actual. ● TABLAS. DATOS. ● VISTAS. Muestra las vistas de la base de datos actual en el cuadro TABLAS/VISTAS DE LA BASE DE DATOS. ● OTRAS. Muestra el diálogo ABRIR convencional, para seleccionar una tabla que libre o de una base de datos no abierta. Muestra las tablas de la base de datos actual en el cuadro TABLAS/VISTAS DE LA BASE DE – ALIAS. Muestra el nombre de las vistas y tablas abiertas. Como una tabla o vista se pueden abrir varias veces, para distinguir cada apertura se le da un sobrenombre o alias. Así, si se abre ALUMNOS por primera vez, su alias será ALUMNOS; si se abre por segunda vez, su alias será ALUMNOS_A, etc. – PROPIEDADES. Presenta el diálogo PROPIEDADES DEL ÁREA DE TRABAJO, ya visto en el menú TABLA de la ventana EXAMINAR. – EXAMINAR. Muestra la tabla o vista seleccionada en ALIAS en una ventana EXAMINAR. – CERRAR. Cierra la vista o la tabla seleccionada en ALIAS. Si es una tabla, cierra sus archivos asociados. – RELACIONES (cuadro). Muestra las relaciones temporales establecidas entre las tablas o vistas abiertas. – RELACIONES (botón). Necesita primero seleccionar en ALIAS la tabla o vista que va a ser madre de la relación. Luego se pulsa el botón. Esto hace aparecer en el cuadro RELACIONES la tabla o vista madre, con una línea de conexión incompleta. Luego se elige la tabla que va a ser hija. Si ésta no tiene un índice activo, aparece el diálogo ESTABLECER ORDEN DE ÍNDICE, con una lista de los índices disponibles. Elegido el índice correcto, aparece el GENERADOR DE EXPRESIONES, para definir la expresión relacional. Esto hace aparecer, en el cuadro RELACIONES, la tabla hija en el otro extremo de la conexión. Si la tabla hija ya tiene un índice pero no es el adecuado, previamente hay que activar el índice correcto mediante el botón PROPIEDADES. Una tabla o vista madre puede tener relaciones con una o más tablas hijas. – 1 A VARIOS. Este botón se activa cuando se selecciona una tabla madre en ALIAS. Primero hay que seleccionar la tabla madre de la relación a ampliar. Luego se pulsa este botón, que presenta el diálogo CREAR RELACIONES UNO A VARIOS, cuyas opciones son las siguientes. ● ALIAS SECUNDARIOS. Es una lista de las tablas hijas de la tabla o vista madre seleccionada en ALIAS, para elegir aquéllas con las que se quiere ampliar las relaciones. ● ALIAS SELECCIONADOS. Es una lista de las tablas hijas con las que se van a ampliar las relaciones. La lista se prepara moviendo las tablas que están en ALIAS SECUNDARIOS. ● MOVER. Mueve la tabla seleccionada en ALIAS SECUNDARIOS a ALIAS SELECCIONADOS. ● TODOS. Mueve todas las tablas de ALIAS SECUNDARIOS a ALIAS SELECCIONADOS. ● ELIMINAR. Elimina la tabla seleccionada en ALIAS SELECCIONADOS. ● ELIMINAR TODOS. Elimina todas las tablas de ALIAS SELECCIONADOS. Ejercitemos ahora lo aprendido. —47— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 1. Emita VENTANA – SESIÓN DE DATOS. 2. Pulse el botón ABRIR y abra la tabla ALUMNOS. 3. Pulse el mismo botón otra vez y abra la tabla EXÁMENES. 4. Seleccione ALUMNOS y pulse el botón PROPIEDADES. Establezca el índice NOMBRE. 5. Pulse el botón EXAMINAR. Salga con ESC. 6. Seleccione EXÁMENES y pulse el botón EXAMINAR. Salga con ESC. 7. Seleccione ALUMNOS. Pulse el botón RELACIONES. Observe el cuadro RELACIONES. 8. Seleccione EXÁMENES en el cuadro ALIAS. Se abre el diálogo ESTABLECER ORDEN DE ÍNDICE. Elija el índice MU. Se abre el GENERADOR DE EXPRESIONES. Si no aparece, escriba la expresión mu y cierre el diálogo. Observe el cuadro Relaciones. 9. Examine ALUMNOS, sin cerrar la ventana EXAMINAR. Modifique su tamaño, de modo que tenga vea algo de la ventana SESIÓN DE DATOS. Haga lo mismo con EXÁMENES. 10. Teniendo ambas ventanas visibles, seleccione un registro de ALUMNOS en su ventana EXAMINAR. Verá que los exámenes que figuran en la otra ventana EXAMINAR corresponden al mismo alumno, como indica el campo MU. Cambie de registro en ALUMNOS y verá que la otra ventana muestra nada más que sus exámenes. Cuando se muestran dos tablas relacionadas, cada una en su propia ventana EXAMINAR, este efecto es automático. 11. Cierre ahora ambas ventanas EXAMINAR. 12. En la ventana COMANDOS ejecute select alumnos browse fields mu, nombre, exámenes.materia, exámenes.fecha, exámenes.nota Lo anterior hace que en una sola ventana EXAMINAR se vean campos de dos tablas relacionadas. Los campos de EXÁMENES, dado que no es la tabla seleccionada, deben ser calificados con el nombre de la tabla. Pero observe que ahora, para cada alumno, sólo se ve un examen. Esto se debe a que la relación es 1 a 1. Para corregir esto, salga de la ventana EXAMINAR con ESC. 13. Seleccione ALUMNOS en ALIAS y pulse el botón 1 A VARIOS. Aparece el diálogo CREAR RELACIONES UNO A VARIOS. En ALIAS SECUNDARIOS seleccione EXÁMENES, pulse MOVER y luego ACEPTAR. Observe el cuadro RELACIONES. 14. Vuelva a repetir lo que hizo en la ventana COMANDOS. Vea la presentación de la ventana EXAMINAR. Salga con ESC. 15. Para volver la relación al tipo 1 a 1, seleccione ALUMNOS y pulse 1 A VARIOS. Seleccione Exámenes en Alias seleccionados y pulse ELIMINAR o ELIMINAR TODOS. Observe el cuadro RELACIONES. 16. Seleccione EXÁMENES en ALIAS y pulse CERRAR. 17. Pulse ESC o el botón de cierre, para cerrar el diálogo SESIÓN DE DATOS. 18. En la ventana COMANDOS, emita DISPLAY STATUS. Hay información sobre la tabla Alumnos, que sigue abierta, pero no sobre EXÁMENES, que fue cerrado con el botón CERRAR. Cerrar el diálogo SESIÓN DE DATOS no cierra las tablas abiertas. 19. Vuelva a emitir VENTANA – SESIÓN DE DATOS. Aparece la tabla ALUMNOS en ALIAS, porque sigue abierta. 20. Seleccione ALUMNOS y pulse CERRAR. Cierre la sesión de datos y vuelva a emitir DISPLAY STATUS. Ahora no hay ninguna tabla abierta. Las relaciones pueden ser "cableados" bastante complejos. Por ejemplo, puede establecer una relación de ALUMNOS a EXÁMENES y de EXÁMENES a MATERIAS. Luego puede ver cada tabla en su propia ventana EXAMINAR, disponiéndolas adecuadamente. Si cambia de registro en la ventana de ALUMNOS, notará que cambian —48— Edmundo A. Cáceres — Tablas, Bases de Datos e Índices — 2008 los exámenes de la ventana respectiva y cambiará la única materia visible en la ventana correspondiente. Esto se debe a que cada examen es de una sola materia. Esa única materia será la correspondiente al primer examen. Si cambia de registro en la ventana de Exámenes, verá que cambia el nombre de la materia. Dejamos que usted practique lo que se indica en el párrafo anterior, tomando como guía lo explicado en los números anteriores. —49—