Sie sind auf Seite 1von 50

OpenQM

3.4-11
1.0.0

Guía Tutorial

1
Guía Tutorial

© 2016 Ladybridge Systems Ltd

Todos los derechos reservados. Ninguna parte de esta obra puede ser reproducida de ninguna forma ni por ningún medio -
gráfico, electrónico o mecánico, incluyendo fotocopias, grabaciones, grabaciones o sistemas de almacenamiento y
recuperación de información - sin el permiso por escrito del editor.

Los productos a los que se hace referencia en este documento pueden ser marcas comerciales y/o marcas comerciales
registradas de los respectivos propietarios. El editor y el autor no reclaman estas marcas.

Si bien se han tomado todas las precauciones en la preparación de este documento, el editor y el autor no asumen ninguna
responsabilidad por errores u omisiones, o por daños resultantes del uso de la información contenida en este documento o
del uso de programas y código fuente que puedan acompañarlo. En ningún caso el editor y el autor serán responsables de
cualquier pérdida de beneficios o cualquier otro daño comercial causado o presuntamente causado directa o
indirectamente por este documento.
Agradecimientos especiales a:
Editor
Los usuarios del producto OpenQM que han contribuido con
temas y sugerencias para este manual.
Ladybridge Systems Limited
17b Coldstream Lane Hardingstone Northampton
NN4 6DB England
Editor Técnico
Martin Phillips
Esta información siempre es muy apreciada, así que sigue
enviando comentarios a support@openqm.com.
Gráfico de la portada

Ishimsi

2
Tabla de Contenido
1 Introducción 4

2 Instalación y Ejecución de QM 7

3 Configuración de los Archivos de Datos 9

4 Registros de Base de Datos y Marca de Caracteres 11

5 Diccionarios 14

6 Visualización de los Datos 20

7 Conversión y Formato 22

8 Registros de Diccionarios Tipo I 23

9 Procesamiento de Consultas 30

10 Creación de un Menú de Informes 38

11 Una Simple Solicitud de Gestión de Préstamos 41

3
1.- Introducción
Bienvenido a la Guía del Tutorial de QM. Este documento lo lleva paso a
paso a través de la construcción de una aplicación sencilla para mostrar
muchas de las características de la base de datos QM MultiValor.
Claramente, un breve tutorial no puede mostrar todo. Hay mucho más para
que usted descubra por sí mismo una vez que haya dominado los principios
básicos.
En este tutorial vamos a crear una base de datos de biblioteca simple,
construir informes para ver el contenido de los archivos y desarrollar un
pequeño programa de aplicación para manejar préstamos y devoluciones.
¿Qué es una Base de Datos de MultiValor?
Hay muchas diferentes bases de datos en el mercado, pero todas ellas caen en
un pequeño número de tipos básicos. Una de ellas es la Base de Datos
Relacional como Oracle o Access. Una base de datos relacional contiene los
datos en forma de tablas de la misma manera que podíamos almacenar la
información como tablas escritas en papel.
La aplicación que vamos a construir en este tutorial es una base de datos para
una biblioteca. Una de las tablas requeridas para esta aplicación puede ser una
lista de los lectores que usan la biblioteca. Podríamos imaginar algo como
esto.
Id del Lector Nombre Dirección Préstamo Fecha vencimiento
1 A Smith 14 High Street 1737 21 Nov 00
2 R Jones 7 Bank Road 4823 27 Nov 00
3 T Harris 4 George Street
4 L Williams 5 Earl Street 2543 1 Dec 00
En esta simple tabla, cada fila representa un lector y cada columna algunos
datos asociados con ese lector. El lector número 3 actualmente no tiene ningún
libro en préstamo.
Las bases de datos relacionales se construyen siguiendo un conjunto de reglas
conocidas como las leyes de la normalización. Una de ellas, la primera ley,
establece que no es posible que tengamos datos repetidos. En términos
prácticos esto significa que no podemos agregar columnas adicionales a la
derecha de la tabla para permitir que un lector pida prestado más de un libro.

4
Id Nombre Direc Préstamo Fecha Préstamo Fecha
Lector ción vencimient vencimiento
o
1 A Smith
14 1737 21 Nov 00 7584 21 Nov 00
High
2 R Jones 7 4823 27 Nov 00
Street
3 T Harris Bank
4
4 L Williams Road
Georg
5 Earl 2543 1 Dec 00 5473 30 Nov 00
eStreet
Hay muchas razones por las que esto no está permitido, sobre todo basado en
Street
la forma en que los datos serán almacenados por el sistema informático. Si
debemos observar la Primera Ley de Normalización, debemos reconstruir
nuestros datos de alguna manera para eliminar las columnas adicionales. Una
forma sería dividir un lector que tiene varios libros en préstamo a través de
varias filas de nuestra tabla.
Id del Nombre Dirección Préstamo Fecha Vencimiento
Lector
1 A Smith 14 High Street 1737 21 Nov 00
1-1 A Smith 14 High Street 7584 21 Nov 00
2 R Jones 7 Bank Road 4823 27 Nov 00
3 T Harris 4 George Street
4 L Williams 5 Earl Street 2543 1 Dec 00
4-1 L Williams 5 Earl Street 5473 30 Nov 00

Hay muchas otras maneras en que podríamos rediseñar nuestra tabla para
cumplir con las Leyes de Normalización, pero todas ellas tienen implicaciones
de desempeño en la base de datos.
Una base de datos MultiValor rompe la Primera Ley de Normalización al
permitir que múltiples valores se almacenen en una sola celda de la tabla.
Nuestra tabla de ejemplo ahora se convierte en:
Id del Lector Nombre Dirección Préstamo Fecha de Vencimiento
1 A Smith 14 High Street 1737 21 Nov 00
2 R Jones 7 Bank Road 4823
7584 27
21 Nov 00
3 T Harris 4 George Street
4 L Williams 5 Earl Street 2543 1 Dec 00
5473 30 Nov 00
5
Tenga en cuenta cómo se relacionan los valores de las columnas del préstamo
y la fecha de vencimiento. Para cualquier lector en particular, el primer
número de préstamo pertenece a la primera fecha de vencimiento, el segundo
número de préstamo pertenece a la segunda fecha de vencimiento y así
sucesivamente.
Al adoptar este modelo de datos en lugar de utilizar columnas adicionales, el
modelo de datos no impone ningún límite al número de libros que un lector
puede tener al mismo tiempo.
Esta forma extendida del modelo de base de datos relacional está en el
corazón de la base de datos QM.
Ha llegado el momento de introducir una terminología. Una aplicación típica
tendrá muchas tablas, tal vez cientos o incluso miles (nuestra base de datos
tutorial tiene tres!). Cada tabla se almacena como un archivo. Las filas de
nuestra tabla se conocen como registros y las columnas como campos. Los
datos almacenados en un campo pueden estar formados por varios valores y
éstos pueden dividirse en subvalores, aunque nuestra base de datos tutorial no
usará subvalores. La relación entre los valores en diferentes campos (por
ejemplo, la fecha de préstamo y de vencimiento anterior) se denomina
asociación.
Cada registro almacenado en un archivo debe tener un identificador de
registro único por el cual pueda ser identificado. En el ejemplo anterior, el
número de lector sería el id de registro. Aunque estos suelen ser números,
pueden ser cualquier secuencia de hasta 63 caracteres (este límite puede ser
incrementado por el administrador del sistema). Aunque hay un límite al
número de registros que un archivo puede contener, es muy poco probable
que afecte a cualquier aplicación real.
Cada archivo normalmente tiene dos partes. La parte de datos contiene los
registros de datos reales. La parte del diccionario contiene registros que
describen la estructura de los registros en la parte de datos y le indica al
procesador de consultas cómo mostrar los datos del archivo. Discutiremos los
diccionarios con más detalle más adelante

6
2.- Instalación y Ejecución de QM
Si aún no ha instalado QM en su sistema, ahora es el momento de hacerlo. El
proceso de instalación varía según el medio en el que se suministró QM. En
todos los casos, el proceso comienza con la ejecución del archivo de
extracción automática apropiado para su sistema operativo.
Abrir una sesión de QMConsole
Se puede acceder a la base de datos de QM de varias maneras. En esta guía
tutorial usaremos una sesión de consola. Esta es una conexión a QM desde el
sistema en el que está instalado. Otros métodos permiten la conexión a través
de una red.
En los sistemas Windows, una vez que QM se haya instalado correctamente,
el grupo de programas elegido durante la instalación (normalmente QM)
contendrá un elemento denominado "QM console". Al hacer clic en este
elemento se abrirá una ventana de consola. Verá una línea de derechos de
autor y una línea de licencia específica del sitio.
En otros sistemas, inicie sesión y, a continuación, escriba qm en el símbolo
del sistema.
Las aplicaciones QM se dividen en Cuentas que pueden usarse para
representar diferentes aplicaciones o versiones de la misma aplicación (por
ejemplo, desarrollo, prueba, producción). Al entrar en QM como se ha
descrito anteriormente, se le pedirá un nombre de cuenta QM. La única
cuenta que siempre existe es la cuenta de administrador del sistema
(QMSYS). Aunque este tutorial se puede completar en esta cuenta, lo mejor
es crear una nueva cuenta específicamente para este propósito.
Cuando haya ingresado el nombre de una cuenta existente, verá una línea que
muestra los dos puntos que es el símbolo del sistema QM. Cuando vea este
mensaje, QM espera que escriba un comando.
Para crear una cuenta de prueba, escriba
CREATE.ACCOUNT TEST C:\TEST
Donde TEST es el nombre que debe darse a la cuenta y C:\TEST es un
nombre de ruta adecuado para su nueva cuenta. En este ejemplo se muestra
una ruta de estilo Windows.
Observe cómo los datos introducidos aparecen en mayúsculas. Por razones
históricas relacionadas con la compatibilidad con otras bases de datos de
7
valores múltiples, los comandos QM suelen estar en mayúsculas. Para evitar
la necesidad de utilizar la tecla de bloqueo de mayúsculas a medida que se
mueve de ventana a ventana, la entrada de teclado normalmente es "invertida"
para que las letras introducidas en minúsculas aparezcan en mayúsculas y
viceversa. Esto se puede desactivar si lo prefiere (consulte el comando
PTERM para más detalles). En la mayoría de los casos, QM aceptará
comandos en mayúsculas o minúsculas.
Ahora que ha creado su cuenta de prueba, puede moveré a ella escribiendo.
LOGTO TEST
Cuando quiera salir de la sesión de tutorial, puede dejar QM escribiendo.
QUIT
en el símbolo del sistema QM. Si desea volver a su cuenta de prueba más
tarde, puede ingresar el nuevo nombre de cuenta al iniciar la sesión.
Entonces, ¿Qué podemos hacer en el indicador de comandos? QM tiene más
de 150 comandos integrados que nos permiten desarrollar y ejecutar
aplicaciones. Este tutorial presentará algunos de los comandos más
importantes.
Hay un extenso sistema de ayuda basado en Windows al que se puede
acceder seleccionando el elemento "QM help" del grupo de programas QM
o tecleando HELP en el símbolo del sistema.

8
3.- Configuración de los Archivos de Datos
Nuestra base de datos tendrá sólo tres archivos
TITLES Detalles de un libro por título
BOOKS Detalles de una copia individual de un libro
READERS Detalles de los lectores que utilizan la biblioteca
Almacenamos la información de TÍTLES y BOOKS por separado ya que
podemos tener más de una copia de un libro.
Para crear estos tres archivos, escriba los comandos
CREATE.FILE TITLES
CREATE.FILE BOOKS
CREATE.FILE READERS
Observe cómo QM crea una parte de datos y de diccionario para el archivo.
También agrega un registro denominado @ID al diccionario para darnos una
vista predeterminada del ID del registro. Aunque vamos a configurar
elementos de diccionario alternativos para los id de registro, el elemento
@ID no se debe eliminar ya que algunas partes de QM dependen de que esté
allí.
Tipos de archivo
QM tiene dos tipos distintos de archivo; Archivos de Directorio y
Archivos Dinámicos. De forma predeterminada, los archivos se crean
como dinámicos. Crearemos un archivo de directorio más adelante.
Un archivo de directorio es representado por un directorio del sistema
operativo y los registros dentro de él por los archivos del sistema operativo.
La clave de registro es el nombre del archivo que contiene los datos para el
registro, excepto cuando se trata de un nombre no válido, en cuyo caso QM
realiza una asignación automática de nombres. Los archivos de directorio
generalmente sólo se utilizan para mantener los programas QMBasic, los
archivos COMO (Command Output) y las listas de selección almacenadas.
Un archivo dinámico también está representado por un directorio de
sistema operativo, pero los registros dentro de él se almacenan en un
formato de archivo de acceso rápido en este directorio. Los usuarios no
deben colocar ningún otro archivo en el directorio ni realizar ninguna
modificación en los archivos colocados allí por QM. Los archivos
dinámicos se llaman así debido a la reconfiguración dinámica del archivo
9
que se realiza automáticamente para compensar los cambios en el tamaño
del archivo y la distribución de registros. Los usuarios tienen cierto control
sobre cómo se realiza esta reconfiguración estableciendo una serie de
parámetros de configuración. En la mayoría de los casos, éstos se pueden
dejar en sus valores por defecto.

10
4.- Registros de Base de Datos y Marca de Caracteres
Un registro de base de datos puede tener cualquier número de campos
(columnas de tabla). El registro entero y los campos constituyentes son de
longitud variable, no habiendo ninguna restricción aplicada por QM. Puede
existir un registro en la base de datos sin datos.
Considere el ejemplo de la tabla READERS anterior. Ignorando la columna
de fecha de vencimiento, que almacenaremos en otra parte de nuestra
aplicación, la entrada para el lector 1 es:
Lector id Nombre Dirección Préstamo
1 A Smith 14 High Street 1737
7584

Internamente, esto se almacena como una cadena de caracteres donde los


límites entre los campos individuales están representados por un carácter
especial conocido como marca de campo. Del mismo modo, dentro del
campo de préstamo, los valores están separados por caracteres de marca de
valor.
Los datos reales almacenados en la base de datos son así:
A SmithFM14 High StreetFM1737VM7584
El id de registro no se considera parte del registro de datos y, por tanto, no se
muestra anteriormente.
Esta representación de un registro de base de datos dividida en campos,
valores y (posiblemente) subvalores utilizando caracteres de marca se conoce
como matriz dinámica. En realidad, hay cinco caracteres de marca definidos
en QM. Puede averiguar sobre los demás desde el manual OpenQM
Reference. Mediante el uso de caracteres de marca de esta manera, los
campos almacenados en el archivo son de longitud variable sin restricciones y
un campo se puede dividir en cualquier número de valores.
En los archivos de directorio, el carácter de marca de campo interno se
sustituye por el carácter de nueva línea ASCII cuando se escribe un registro
en el disco para que los campos aparezcan como líneas cuando el registro se
ve, edite o imprima desde fuera de QM. Por el contrario, las nuevas líneas
ASCII se convierten en marcas de campo al leer un registro
Los campos, los valores dentro de un campo y los subvalores dentro de un
11
valor están numerados de uno hacia arriba. Por convención, la clave de
registro se denomina a veces campo cero aunque no forma parte de la matriz
dinámica y las referencias al campo cero sólo son reconocidas por QM en
determinados contextos.
En nuestra base de datos de demostración, nuestros archivos contendrán los
siguientes campos:
TITLES
TITLE.REF Un id de registro numérico para el título
TITLE El título actual
AUTHOR El nombre del autor. Podría haber más de un autor así
que esto será MultiValor.
SUBJECT Un código de asunto
COPIES El número de copias del libro
BOOKS
BOOK.REF El id de registro para los detalles del libro
READER El lector que tiene este libro en préstamo. En blanco si
no está en préstamo.
DATE.OUT La fecha en que se tomó el libro
READERS
READER.REF Un id de registro numérico para el lector
NAME El nombre del lector
ADDRESS La dirección del lector. Aunque un lector sólo tiene una
dirección, los campos de dirección se almacenan
normalmente como MultiValor donde cada valor
representa una línea de la dirección.
LOANS Una lista MultiValor de libros en préstamo
Hay interrelaciones entre los archivos. Cualquier registro en el archivo
BOOKS debe estar relacionado de nuevo con su registro TITLES
correspondiente. Una manera fácil de hacer esto es usar una clave compuesta
donde las copias del libro descrito por TITLES registro 7, por ejemplo, se
darían identificadores de archivo de BOOKS de 7-1, 7-2, 7-3, etc. Muy a
menudo, Las partes componentes de una llave compuesta se rellenan con los
12
ceros delanteros para hacerlos de longitud fija. No lo haremos en nuestra
base de datos de ejemplo
El campo READER del archivo BOOKS contiene el ID de registro de la
entrada de archivo READERS para el lector que tiene el libro en préstamo
(si lo hay). El campo LOANS del archivo READERS proporciona el enlace
inverso al contener el id de registro de BOKKS de los libros en préstamo.

13
5.- Diccionarios
Cada archivo normalmente tiene un diccionario asociado que describe la
estructura de los registros de datos almacenados en el archivo y la forma
predeterminada en la que el procesador de consultas debe presentar los datos
en un informe.
El diccionario contiene registros de varios tipos, cada uno identificado por un
código en el primer campo de la entrada. Los principales tipos de registro son:
D Una entrada de tipo D define un campo de datos presente en el
archivo y especifica su ubicación y cómo se mostrará en un
informe.
I Una entrada de tipo I define un valor que puede calcularse a partir
de los datos del archivo y especifica cómo se mostrará en un
informe.
PH Una entrada de tipo PH es una frase que puede ser sustituida en una
oración de procesamiento de consultas. Hay algunas frases
reservadas que controlan las acciones predeterminadas del
procesador de consultas.
X Una entrada de tipo X es un elemento de almacenamiento
misceláneo y puede utilizarse para cualquier propósito.
Un diccionario normalmente contiene un registro de tipo D para describir
cada campo de los registros de la base de datos. Un solo campo puede ser
descrito por varios registros de diccionario para proporcionar formas
alternativas de ver los datos. El registro utilizado por el procesador de
consultas depende de cómo se redacte la consulta.
Considere nuestro archivo TITLES. Cada registro de datos tiene cuatro
campos que contienen los atributos del orden y cada uno de estos campos
tiene un registro de diccionario correspondiente. También hay un registro de
diccionario para describir el ID del registro. El nombre del registro de
diccionario es el nombre por el cual el procesador de consultas se referirá al
campo.
Los registros de diccionario de tipo D normalmente constan de 7 campos. El
propósito y el contenido de cada campo de diccionario se muestran en el
siguiente ejemplo en el que la primera columna muestra el nombre
convencional del campo del diccionario, la segunda es el número del campo
14
del diccionario y las columnas restantes muestran lo que contendría la entrada
del diccionario para describir el Registro de identificación y los cuatro
campos de datos.
Los diccionarios de nuestros tres archivos contienen los elementos de tipo D
que se muestran a continuación. TITLES
TITLES
TITLE.REF TITLE AUTHOR SUBJECT COPIES
Type 1 D D D D D
Loc 2 0 1 2 3 4
Conv 3
Name 4 Ref Titulo Autor Asunto Copias
Format 5 5R 25T 15T 15L 2R
SM 6 S S M S S
Assoc 7
BOOKS
BOOK.RE READER DATE.OUT
Type 1 D
F D D
Loc 2 0 1 2
Conv 3 D2DMY[,A3]
Name 4 Ref Lector Fecha Salida
Format 5 8R 5R 9R
SM 6 S S S
Assoc 7
READERS
READER.RE NAME ADDRESS LOAN
Type 1 D
F D D D
Loc 2 0 1 2 3
Conv 3
Name 4 Ref Nombre Direccion Prestamo
Format 5 5R 20T 20T 8R
SM 6 S S M M
Assoc 7
El papel de cada campo de diccionario se describe a continuación:
Type El campo Type contiene el tipo de entrada del diccionario, D para una
descripción de un campo dentro del registro de la base de datos. El código Type
15
puede ser seguido opcionalmente por un texto descriptivo.
Loc El campo Location contiene la posición del campo dentro del registro
de la base de datos. El registro id se muestra como campo cero en los
diccionarios.
Conv Los datos a veces se almacenan en un formato interno. El código
Conversion describe la conversión que se realizará antes de que los datos se
muestren en un informe. Los códigos de Conversion se discuten más adelante.
En el archivo BOOKS, el campo DATE.OUT tiene un código de conversión
para especificar cómo se mostrará la fecha.
Name El campo Name contiene el encabezado de columna predeterminado
que se utilizará en los informes.
Format El campo Format especifica el número de columnas usadas para
mostrar estos datos y cómo los datos deben alinearse dentro del ancho dado.
Los códigos de formato se discuten más adelante.
SM Este indicador indica si el campo es siempre de valor único (S)
o puede ser MultiValor (M). En nuestro archivo TITLES, por
ejemplo, el campo AUTHOR puede ser MultiValor.
Assoc Utilizado solo con campos MultiValor, este campo muestra la
relación entre los campos MultiValor asociados. Todos los
campos que tienen la misma palabra en este campo de
diccionario se asocian entre sí. Hasta ahora, nuestros
diccionarios no requieren ninguna asociación. Esto cambiará
más tarde.
Podemos utilizar cualquier herramienta de edición conveniente para crear los
elementos del diccionario. El editor MODIFY es ideal para este propósito.
Realice los siguientes pasos para configurar los diccionarios.
Escriba:
MODIFY DICT TITLES
En el indicador "Id:", ingrese el nombre del registro de diccionario que se va a
crear. La primera de nuestras tablas anteriores es TITLE.REF.
MODIFY muestra una lista de campos de diccionario. Los números junto a
los nombres de campo son sólo para referencia y no son necesariamente las
posiciones de campo reales.
Aparece un mensaje en la parte inferior de la pantalla para el valor Tipo/Desc.
16
Introduzca "D" y pulse la tecla de retorno. El valor introducido se muestra en
la parte superior de la pantalla y MODIFY se mueve para solicitar el
siguiente campo. Continúe introduciendo datos hasta que se hayan introducido
siete campos de diccionario. No se preocupe si comete un error; Puedes
corregirlo más tarde.
Una vez introducidos los siete campos, aparece el mensaje de acción. La
respuesta a esto puede ser:
 Un número que identifica un campo mostrado para ser modificado.
 FI para archivar el registro.
 Q para salir del registro, descartando todos los datos ingresados.
 ? para ayuda.
Para registros con más campos que caben en una sola página, hay dos
respuestas adicionales disponibles:
 N para la siguiente página
 P para la página anterior
Puede desplazarse al indicador de acción desde la entrada de datos
introduciendo Ctrl-X (La tecla Ctrl-X es como la tecla Shift: presione y
mantenga presionada la tecla Ctrl, presione X, luego suelte ambas teclas)
Corrija cualquier error en los datos mostrados y luego archive el registro
escribiendo FI en el indicador de acción. El indicador "Id:" aparece de nuevo.
Introduzca el siguiente ID de registro de diccionario que se va a crear
(TITLE). Continúe de esta manera hasta que todos los elementos diccionario
del archivo TITLES se han creado. Para dejar MODIFY, ingrese una
respuesta en blanco al mensaje "Id:"
Utilice MODIFY nuevamente para ingresar las definiciones del diccionario
para los archivos BOOKS y READERS.
Puede ver sus diccionarios escribiendo, por ejemplo,
LIST DICT TITLES
Ahora que ha introducido las definiciones del diccionario, puede utilizar
MODIFY para introducir algunos datos en los archivos. Escriba:
MODIFY TITLES
Una vez más, recibirá un mensaje de identificador de registro, pero esta vez
utilizará el nombre de archivo como la solicitud. Este aviso predeterminado
17
puede cambiarse como se describe en la descripción de MODIFY en el
Manual de Referencia de QM.
Introduzca "1" como id para el primer registro de título. La lista de campos
mostrada tiene tres elementos para el título, el asunto y las copias. El cuarto
elemento se muestra con un prefijo de número ligeramente diferente, ya que
esto conduce a una segunda pantalla para el campo MultiValor. Observe
cómo el texto introducido como el nombre de visualización de campo en el
diccionario se utiliza como el indicador.
Introduzca un título de libro y un asunto adecuados y establezca el campo de
copias en 1. La pantalla cambiará para permitir la entrada de varios autores.
Introduzca el (los) autor (es) del libro, utilizando el formulario "apellido,
nombre" para corresponder con la forma en que nuestras consultas
funcionarán más tarde.
Cuando se han introducido todos los autores, aparece el mensaje de acción de
campo de valores múltiples. Esto permite la entrada de:
 Un número de artículo correspondiente a una línea que se va a cambiar
 In para insertar una línea por encima de la linea n
 Dn para eliminar la linea n
 E para extender (agregar nuevos elementos al final)
Para una lista de varias páginas, la solicitud también
 N para pasar a la página siguiente
 P para pasar a la página anterior
Si no se requieren cambios, simplemente presione la tecla RETURN para
regresar a la primera pantalla. Como antes, realice cualquier corrección y, a
continuación, introduzca FI para archivar el registro
Introduzca otros dos títulos de libro. El libro número 2 debe tener dos copias,
libro 3 debe tener una copia.
Ahora use MODIFY para entrar los registros correspondientes a BOOKS.
Recuerde que estos son marcados por la clave del archivo TITLES con un
sufijo del número de copia. Nuestros registros serán 1-1, 2-1, 2-2, 3-1.
El Libro 1-1 está en préstamo al lector 2. Introduzca una fecha adecuada
para el préstamo.
El Libro 2-1 no está en préstamo (dejar el lector y la fecha en blanco).

18
El libro 2-2 está prestado al lector 3.
El libro 3-1 está prestado al lector 2.
Este patrón de préstamo asegura que tenemos libros que están en préstamo y
no en préstamo y los lectores que no tienen libros, un libro o dos libros en
préstamo.
Por último, utilice MODIFY para ingresar los elementos del archivo
READERS, asegurándose de que los préstamos son correctos.
El Lector 1 no tiene libros en préstamo
El lector 2 tiene los libros 1-1 y 3-1 en préstamo
El lector 3 tiene el libro 2-2 en préstamo
Introduzca los nombres en el formulario "apellido, iniciales" sin puntos
después de las iniciales (por ejemplo, "Smith, A J").
¡Eso es! Ahora tiene un conjunto de datos para experimentar con el
procesador de consultas QM y como inicio para la aplicación de préstamos
simples. Siéntase libre de agregar más datos, pero tenga cuidado de que la
interrelación entre los registros en diferentes archivos se mantenga
correctamente.

19
6.- Visualización de los Datos
Escriba "LIST TITLES" para ver el archivo TITLES. Esta consulta nos
muestra los ids de los registros del archivo TITLES pero no es de mucha
utilidad. Podríamos ampliar la consulta agregando los nombres de los campos
que nos gustaría ver:
LIST TITLES TITLE AUTHOR SUBJECT COPIES
Esto está mejor, pero el procesador de consultas nos está mostrando la vista
predeterminada del ID de registro como la primera columna en lugar de la que
creamos con un encabezado de columna agradable. Trate de añadir nuestra
propia definición del ID de registro como el primer campo de la consulta:
LIST TITLES TITLE.REF TITLE AUTHOR SUBJECT COPIES
Consejo: Puede usar la tecla de cursor arriba para regresar al comando
anterior y luego editarlo usando las teclas de cursor izquierda y
derecha, borrar, retroceso, etc.
Ahora tenemos la columna que nos gustaría, pero todavía tenemos la vista
predeterminada del ID de registro. Agregue la palabra clave ID.SUP a la
consulta para suprimir este elemento predeterminado:
LIST TITLES TITLE.REF TITLE AUTHOR SUBJECT COPIES
ID.SUP
Esto parece un informe útil, pero no queremos tener que escribir la lista de
campos cada vez que producimos un informe. En su lugar, podemos
configurar una frase de lista predeterminada en el diccionario para decirle al
procesador de consultas lo que queremos ver si no se listan campos de
visualización en el comando.
Para ello, utilice MODIFY en el diccionario del archivo TITLES para
agregar un elemento denominado @. El campo Type/Desc debe ser PH para
mostrar que se trata de una entrada de frase. En una frase, el campo 2 contiene
la expansión de la frase y los campos restantes no se utilizan. En el indicador
F2, escriba
TITLE.REF TITLE AUTHOR SUBJECT COPIES ID.SUP
En el indicador F3, escriba Ctrl-X para saltar al indicador de acción. Presente
su nueva frase. Ahora intenta
LIST TITLES

20
El procesador de consultas utiliza su frase para determinar los campos que se
mostrarán. Tenga en cuenta que si incluye cualquier nombre de campo para
mostrar en el comando, la frase no se utiliza:
LIST TITLES AUTHOR
Configurar frases de lista predeterminadas para los otros archivos:
BOOKS: BOOK.REF READER DATE.OUT ID.SUP
READERS: READER.REF NAME ADDRESS LOANS ID.SUP
Compruebe que los informes son como usted esperaría.

21
7.- Conversión y Formato
Códigos de conversión
El campo de fecha de nuestro archivo BOOKS utilizó un código de
conversión para especificar cómo se mostrarían los datos. Las fechas suelen
guardarse como un número de días a partir del 31 de diciembre de 1967,
siendo el día cero. Todas las fechas posteriores son números positivos, todas
las fechas anteriores son números negativos. El código de conversión en el
diccionario indica a MODIFY que el campo es una fecha y, cuando se
introduce la fecha, se convierte automáticamente en su forma interna. Cuando
la fecha se emite mediante MODIFY o por el procesador de consultas, se
realiza la conversión inversa para mostrar una fecha significativa. El código de
conversión especifica la forma exacta en la que debe aparecer la fecha y tiene
muchas posibilidades.
Las fechas son sólo un tipo de datos que normalmente se almacena en alguna
forma interna especial. Otros ejemplos son los tiempos (almacenados como
segundos desde la medianoche) y los pesos y medidas (almacenados escalados
para eliminar el punto decimal). Hay muchos otros códigos de conversión y
los usuarios pueden agregar sus propios. Los códigos de conversión se
discuten en detalle en el QM Reference Manual.
Formato Especificaciones
La especificación de formato en el campo 5 de la entrada del diccionario
indica al procesador de consultas cuántas columnas se van a asignar a través
del informe para los datos y dónde en este ancho de campo deben mostrarse
los datos. Por ejemplo, nuestro ID de registro de archivo TITLES se emite
utilizando una especificación de formato "5R" que muestra los datos
justificados a la derecha en un campo de cinco caracteres de ancho. El formato
de campo SUBJECT es "15L", dejando justificar los datos en un campo de 15
caracteres de ancho. El TITLE utiliza una especificación de formato de
"25T". Esto es similar a "25L", pero intentará romper entre las palabras si los
datos deben dividirse en varias líneas.
Las especificaciones de formato contienen varias otras funciones como se
describe en QM Reference Manual.

22
8,- Registros de Diccionario tipo I
Como nuestros diccionarios destacan hasta ahora,, podemos construir
consultas sencillas para mostrar los datos de cualquiera de nuestros tres
archivos. Es posible que desee listar el archivo BOOKS, mostrando el título
de cada libro. Esto requiere acceso a los datos de dos archivos.
Un comando de procesador de consultas sólo puede referirse directamente a un
solo archivo. Para reunir datos de otros archivos o para otros valores
calculados, usamos elementos de diccionario de tipo I.
Un registro de diccionario de tipo I define un cálculo basado en datos de los
registros de archivos de datos. Una vez que se define un elemento de tipo I, se
puede hacer referencia en los comandos del procesador de consultas
exactamente como si se tratara de un campo de datos real (tipo D). Los
elementos de tipo I se conocen a veces como atributos virtuales, un término
que hace hincapié en el hecho de que sus valores no se almacenan físicamente
en la base de datos
Un elemento de diccionario de tipo I difiere de un elemento de tipo D sólo en
que el campo 1 contiene el código de tipo I y el campo 2 contiene el cálculo
real que se va a realizar. Los campos restantes son como para una entrada de
tipo D.
La expresión en un registro de diccionario de tipo I es en realidad un pequeño
programa QMBasic y puede utilizar la mayoría de las construcciones que
pueden aparecer en el lado derecho de una asignación en el lenguaje de
programación completo. En este tutorial introduciremos algunas
construcciones simples de expresión de tipo I sin entrar en demasiados detalles
de cómo funcionan. Necesitará leer las secciones iniciales de la sección
QMBasic del QM Reference Manual para obtener una mejor comprensión de
las expresiones de tipo I.
Cálculo de la Fecha de Vencimiento
Nuestro archivo de BOOKS incluye un campo de DATE.OUT que gurda la
fecha en la cual un libro fue prestado. Es posible que desee saber la fecha en
que se debe devolver. Asumiendo un período de préstamo simple de tres
semanas, esto se puede calcular agregando 21 días a la fecha de vencimiento.
Una expresión de tipo I para hacer esto podría escribirse como:
DATE.OUT + 21

23
Esto no es perfecto. Un libro que no está en préstamo tiene una fecha en
blanco fuera del campo. En un cálculo aritmético, un campo en blanco se trata
como cero y, por lo tanto, todos los libros que no están en préstamo parecerían
ser devueltos el día 21 (21 de enero de 1968).
La sintaxis de expresión nos permite manejar esto añadiendo un elemento
condicional:
IF DATE.OUT THEN DATE.OUT + 21 ELSE ""
Utilice MODIFY para introducir un elemento DATE.DUE en el
diccionario BOOKS. Esto debe leers asi:
Type/Desc: I
Loc: IF DATE.OUT THEN DATE.OUT + 21 ELSE ""
Conv: D2DMY[,A3]
Name: Date due
Format: 9R
S/M: S
Assoc:
Modifique la frase @ para incluir este campo. Cuando selecciona el elemento
2 (el campo LOC) de esta frase en MODIFY, puede utilizar las teclas de
cursor izquierda y derecha, etc. para desplazarse por los datos. No es
necesario volver a escribir la frase completa.
Intente LIST BOOKS para ver su elemento de tipo I en acción.
Obtención del Título del Libro para un Informe del Archivo de BOOKS
Éste requiere acceso a un segundo archivo (el archivo TITLES). Recuerde
que los id de registro en nuestro archivo BOOKS son el id de archivo
TITLES con un sufijo añadido para identificar la copia.
Construiremos dos ítems de tipo I aquí. El primero (TITLE.REF) calculará el
id del archivo TITLES extrayendo la primera parte del id del registro
compuesto. El segundo (TITLE) buscará el título real del libro, utilizando el
elemento TITLE.REF para identificar el registro. Observe cómo esto implica
el uso del resultado de un valor calculado en otro cálculo.
El registro de diccionario tipo I TITLE.REF debe leer:
Type/Desc: I
Loc: @ID["-", 1, 1]

24
Conv:
Name: TitleRef
Format: 5R
S/M: S
Assoc:
La expresión en el campo LOC extrae el primer componente separado por
guion del ID de registro compuesto. Consulte la descripción de la sintaxis
de expresiones en el QM Reference Manual para obtener más detalles
Puede probar esto agregándolo a su diccionario de archivos de BOOKS y
escribiendo
LIST BOOKS TITLE.REF
El registro de diccionario tipo I TITLE debe leer
Type/Desc: I
Loc: TRANS(TITLES,TITLE.REF,TITLE,"X")
Conv:
Name: Title
Format: 25T
S/M: S
Assoc:
La función TRANS() en el campo LOC se utiliza para buscar datos de otro
archivo. Los cuatro elementos dentro de los corchetes son:
 El nombre del archivo del cual se va a obtener el artículo.
 El nombre de un elemento definido en este diccionario que da el id del
registro a leer del archivo de destino.
 El nombre de un elemento de tipo D definido en el diccionario del
archivo de destino que identifica los datos a devolver.
 Un código de error que determina la acción si no se puede encontrar el
elemento. En este caso, "X" especifica que se debe devolver un
resultado en blanco.
Consulte la descripción de la función TRANS() en el QM Reference Manual
para obtener más detalles.
Agregue este nuevo ítem de tipo I al diccionario de su archivo BOOKS y
pruébelo.
Sería útil ser capaz de obtener el nombre del lector que tiene un libro en
25
préstamo. Compruebe si puede crear un elemento de tipo I denominado
NAME en el diccionario del archivo BOOKS para hacer esto. La solución
está en la página siguiente.
El registro de diccionario tipo I NAME debería leer
Type/Desc: I
Loc: TRANS(READERS,READER,NAME,"X")
Conv:
Name: Reader Name
Format: 20T
S/M: S
Assoc:
Añadir esto a su diccionario de BOOKS y probarlo.
También podríamos encontrar útil el poder listar las fechas en que los libros
fueron prestados a un lector en particular. Podemos hacer esto agregando un
elemento de tipo I denominado DATE.OUT al diccionario de archivos
READERS, como el que se muestra a continuación.
Type/Desc: I
Loc: TRANS(BOOKS,LOANS,DATE.OUT,"X")
Conv: D2DMY[,A3]
Name: Date out
Format: 9R
S/M: M
Assoc:
Esto es muy similar a la forma en que buscamos el nombre del lector usando
un ítem de tipo I en el diccionario de BOOKS. Hay, sin embargo, una
característica muy importante mostrada por esta expresión. Un lector puede
tener más de un libro en préstamo. El campo LOANS del archivo READERS
tiene varios valores. La función TRANS() en la expresión anterior, por lo
tanto, tiene una lista MultiValor de identificadores del archivo BOOKS como
su elemento LOANS y procesará la lista entera en una operación, devolviendo
una lista MultiValor de fechas correspondiente. Dado que el elemento de
préstamos es MultiValor, el elemento de tipo I DATE.OUT también debe ser
MultiValor.
Añade este nuevo tipo I a tu diccionario del archivo READERS y pruébalo.

26
Ahora tenemos dos elementos de MultiValor en el diccionario de archivos
READERS donde los datos tienen una relación valor por valor. El primer
valor en el campo LOANS está relacionado con el primer valor en el campo
DATE.OUT. Los segundos y posteriores valores tienen la misma relación.
Esta relación debe definirse mediante la creación de una asociación.
Para ello, se requieren dos pasos. En primer lugar, debemos pensar en un
nombre para la asociación e insertarlo en el campo Assoc (campo 7) de los
elementos del diccionario para LOANS y DATE.OUT. En segundo lugar,
debemos crear una entrada de tipo PH (frase) con el nombre de la asociación y
con una lista separada por espacios de los campos que son miembros de la
asociación en el campo 2 (LOC).
Por ejemplo, podríamos elegir llamar a esta asociación BOOKS.OUT.
Utilizamos MODIFY para agregar este nombre al campo Assoc de los
elementos LOANS y DATE.OUT. Estos se convierten ahora en lo que se
muestra a continuación;
LOANS:
Type/Desc: D
Loc: 3
Conv:
Name: Loans
Format: 8R
S/M: M
Assoc: BOOKS.OUT
DATE.OUT:
Type/Desc: I
Loc: TRANS(BOOKS,LOANS,DATE.OUT,"X")
Conv: D2DMY[,A3]
Name: Date out
Format: 9R
S/M: M
Assoc: BOOKS.OUT
La frase que define la asociación es:
BOOKS.OUT:
Type/Desc: ph
27
Loc: LOANS DATE.OUT
Realice estos cambios en el diccionario de su archivo READERS. Al ingresar
la frase, recuerde que al teclear Ctrl-X en el indicador CONV después que se
haya ingresado el campo LOC saltará al indicador de acción.
¿Por qué necesitamos definir las asociaciones de esta manera?
El procesador de consultas y algunos otros componentes como MODIFY
necesitan saber acerca de la asociación para que puedan emparejar
correctamente los elementos asociados. Muy a menudo, el olvido de definir la
asociación no tiene ningún efecto en el trabajo que hacemos, pero a veces
obtendremos los resultados incorrectos de los informes de consulta.
Teniendo una frase que enumera a los miembros de la asociación podemos
comenzar de cualquier miembro, utilice el campo Assoc para encontrar la
frase y por lo tanto encuentre todos los otros artículos asociados. Esto elimina
la necesidad de escanear todo el diccionario buscando elementos asociados.
Evidentemente, debemos asegurarnos de que este enlace bidireccional de los
elementos asociados se mantenga correctamente si modificamos el
diccionario.
Hay una última expresión de tipo I que agregar a nuestros diccionarios.
Podríamos también encontrar útil poder enumerar los títulos de todos los libros
prestados a un lector particular. Podemos hacerlo añadiendo un elemento de
tipo I denominado TITLE al diccionario de archivos READERS como el que
se muestra a continuación.
Type/Desc: I
Loc: TRANS(TITLES,FIELDS(LOANS,"-
",1),TITLE,"X")
Conv:
Name: Titles on loan
Format: 25T
S/M: M
Assoc: BOOKS.OUT
La función FIELDS() en el segundo argumento de la función TRANS()
toma una lista de MultiValor de LOANS y extrae sólo el primer
componente separado de guiones. Una vez más, puede obtener más
información sobre esta función, así como muchas otras funciones de

28
manipulación de MultiValor desde el QM Reference Manual.
Observe cómo este elemento es también un miembro de la asociación
BOOKS.OUT. No olvide añadirlo a la lista en la frase de BOOKS.OUT.
Ahora tenemos un conjunto completo de elementos de diccionario para
manejar el resto de este tutorial. Siéntase libre de agregar nuevos elementos si
desea explorar otras posibilidades.
QM incluye un par de comandos para configurar y eliminar los archivos de
demostración.
Estos le permitirán trabajar con estos archivos de nuevo en el futuro sin tener
que pasar por todo el proceso de instalación de archivos. Los comandos son:
SETUP.DEMO Crea o restablece los archivos de demostración
DELETE.DEMO Elimina los archivos de demostración

29
9.- Procesamiento de Consultas
En esta sección veremos algunas de las características básicas del procesador
de consultas QM. Hay mucho más que descubrir por ti mismo cuando mires a
través de los manuales.
El procesador de consultas nos permite extraer datos de los archivos de base
de datos para todos los propósitos, desde consultas simples hasta informes
complejos. Tiene muchas características para especificar qué datos se van a
extraer y cómo se van a presentar esos datos.
Hay muchos comandos del procesador de consultas (verbos). El más
importante es LIST que produce informes ya sea en la pantalla del terminal o
en una impresora.
Todos los verbos de procesador de consultas comparten un formato general
común aunque no todos los elementos son aplicables a todos los verbos. Este
formato es:
verb filename selection.clause sort.clause
display.clause options
donde:
verb Es el verb (verbo) del procesador de consultas que se
utilizará.
filename Especifica el archivo a procesar. Una oración de
procesador de consultas sólo puede hacer referencia
a un solo archivo aunque el diccionario de ese
archivo puede incluir atributos virtuales para
recuperar datos de otros archivos. El filename o
(nombre de archivo) puede ser prefijado por DICT
para procesar la parte del diccionario del archivo
selection.clause Especifica qué registros deben incluirse en el
informe. QM ofrece una amplia gama de métodos
para seleccionar registros. Si se omite, se despliegan
todos los registros.
sort.clause Especifica el orden en que se van a enviar los datos
reportados. Si se omite, los registros se informan en
el orden en que se encuentran en el archivo.
display.clause Especifica los campos que se mostrarán en el
30
informe y, opcionalmente, reemplaza los detalles del
diccionario de cómo se van a convertir, formatear,
etc. Si se omite, se indica un conjunto
predeterminado de campos.
options Son varias opciones adicionales para controlar el
diseño de página, destino de salida, etc.
Las cláusulas que siguen al nombre de archivo son todas opcionales y
pueden aparecer en cualquier orden. Las únicas características específicas
del pedido son que los campos se mostrarán de izquierda a derecha en el
informe en el orden en el que se especifican en la oración de consulta y se
aplicarán cláusulas de selección o clasificación múltiples en el orden en que
aparecen.
Todo el procesamiento de comandos en QM se controla a través del archivo
VOC (vocabulario). Esto define los nombres de los verbos, palabras clave que
controlan sus acciones, archivos, etc. El VOC se discute en detalle en el
manual Introduction to QM.
Durante el procesamiento de una sentencia de consulta, cada palabra y
símbolo en la línea de comandos se mira primero en el diccionario del archivo
que se está procesando y luego, si no se encuentra allí, en el archivo VOC.
Los elementos citados siempre se tratan como valores literales.
La Cláusula de Selección
La cláusula de selección más simple consiste en uno o más identificadores de
registro. Éstos deben ser citados si existe el riesgo de que también puedan
aparecer como elementos de diccionario o VOC.
Por ejemplo:
LIST TITLES 1 3
El segundo método para seleccionar los registros a procesar es mediante el uso
de la cláusula WITH. Esto prueba cada registro con algunos criterios de
selección para determinar si debe incluirse en el informe.
Hay muchos métodos de selección disponibles en la cláusula WITH. La más
utilizada es una prueba de un valor de campo contra un valor literal u otro
campo. Por ejemplo,
LIST TITLES WITH COPIES > 1
Los campos nombrados en una cláusula WITH deben definirse en el
31
diccionario o en el VOC como elementos de tipo D o I.
Los operadores relacionales disponibles son:
= EQ
# NE <> ><
< LT LESS BEFORE
> GT GREAT AFTER
ER
<= LE =<
>= GE =>

Cuando se utiliza un operador relacional para comparar un campo que tiene un


código de conversión con un valor literal, el valor literal se convierte en la
forma interna del campo y la comparación posterior se realiza utilizando
valores internos. Esto significa que, por ejemplo, una fecha literal se puede
introducir en cualquier formato reconocible en lugar de sólo en la forma dada
por el código de conversión.
LIST BOOKS WITH DATE.OUT AFTER '1 JUL 00' LIST
TITLES WITH SUBJECT = 'Art'
Si el campo nombrado en una cláusula WITH es MultiValor, al menos uno
de los valores debe coincidir con la prueba para el registro que se incluirá en el
informe. Por ejemplo:
LIST TITLES WITH AUTHOR = 'Smith, Alan'
La consulta anterior mostraría todos los registros en el archivo TITLES que
incluya el autor dado, incluso si el libro tiene más de un autor.
Es posible que desee seleccionar registros en los que todos los valores de un
campo MultiValor cumplan los criterios de selección. Esto se puede hacer
usando la construcción WITH EVERY. Por ejemplo:
LIST READERS WITH EVERY DATE.OUT > '1 JUL 00'
Esta consulta muestra a los lectores donde todos los libros en préstamo fueron
sacados después del 1 de julio 2000.
Se pueden incluir varias condiciones utilizando las palabras clave AND u OR
en la oración de consulta. Por ejemplo:
32
LIST TITLES WITH SUBJECT = 'Art' AND AUTHOR =
'Smith, Alan'
LIST TITLES WITH SUBJECT = 'Art' OR SUBJECT =
'History'
Multiple conditions can also be included by using more than one WITH
clause.
LIST TITLES WITH SUBJECT = 'Art' WITH AUTHOR =
'Smith, Alan'
Este es equivalente al primero de los ejemplos anteriores.
La Coincidencia de Patrones
Otro componente de cláusula WITH utilizado comúnmente es la concordancia
de patrones para probar la estructura general de una cadena de caracteres en
lugar de su contenido exacto. La forma general de esto es:
WITH field LIKE template
donde
field Es el campo a ser comparado.
template Es el patrón contra el cual se compara el campo.
La plantilla consta de uno o más elementos concatenados de la siguiente lista.
... Cero o más caracteres de cualquier tipo
0X Cero o más caracteres de cualquier tipo
nX Exactamente n caracteres de cualquier tipo
n-mX Entre n y m caracteres de cualquier tipo
0A Cero o más caracteres alfabéticos
nA Exactamente n caracteres alfabéticos
n-mA Entre n y m caracteres alfabéticos
0N Cero o más caracteres numéricos
nN Exactamente n caracteres numéricos
n-mN Entre n y m caracteres numéricos
"string" Una cadena literal que debe coincidir exactamente. Pueden
utilizarse comillas simples o dobles.
33
Los valores n y m son números enteros con cualquier número de dígitos. Debe
ser mayor o igual que n.
Los patrones 0A, nA, 0N, nN y "cadena" pueden estar precedidos por un tilde
(~) para invertir la condición de coincidencia. Por ejemplo, ~ 4N coincide con
cuatro caracteres no numéricos como ABCD (no una cadena que no sea
cuatro caracteres numéricos como 12C4).
Ejemplos:
LIST READERS WITH NAME LIKE Smith...
LIST TITLES WITH TITLE LIKE ...Concise...
El procesador de consultas tiene muchas formas cortas. Entre los más útiles,
un operador relacional o una palabra clave LIKE no precedida
inmediatamente por un nombre de campo utiliza el mismo campo que la
prueba anterior o el ID de registro si ésta es la primera prueba.
Ejemplos:
LIST BOOKS WITH DATE.OUT AFTER '1 APR 00' AND
BEFORE '1 MAY 00'
LIST TITLES > 10
Un operador seguido de una lista de valores prueba cada uno a su vez en una
relación de OR implícita. Ejemplos:
LIST TITLES WITH SUBJECT = Art History
LIST READERS WITH NAME LIKE Smith... Jones...
Tenga en cuenta que el primer ejemplo anterior informa libros con un tema de
Arte o Historia. Si queríamos encontrar libros sobre historia del arte, la
consulta sería:
LIST TITLES WITH SUBJECT = 'Art history'
Tenga en cuenta también que los operadores de comparación del procesador
de consultas son sensibles a mayúsculas y minúsculas. Podemos trabajar
alrededor de esto usando las características no discutidas en este tutorial.
La Cláusula de Clasificación (SORT)
La cláusula de (Sort) clasificación especifica el orden en el que aparecerán los
registros reportados. En su forma más comúnmente utilizada, es introducida
por la palabra clave BY.

34
Ejemplo:
LIST BOOKS BY DATE.OUT
La palabra clave BY.DSND realiza una clasificación descendente.
Ejemplo;
LIST BOOKS BY.DSND DATE.OUT
Una sola consulta puede contener varias cláusulas de ordenación. Se aplican
de izquierda a derecha, se aplican clases posteriores donde dos o más registros
tienen los mismos valores en los campos para las clases anteriores.
Ejemplo:
LIST TITLES BY SUBJECT BY TITLE
El verbo SORT es equivalente a LIST con un componente final BY @ID.
Así, las dos consultas siguientes producen una salida idéntica
SORT TITLES BY SUBJECT
LIST TITLES BY SUBJECT BY @ID
No utilice SORT a menos que realmente desee ordenar por ID de registro.
La Cláusula Display
La cláusula Display determina qué campos aparecerán en el informe y cómo
se mostrarán.
En su forma más simple, la cláusula Display consta de una lista de nombres de
campo. Estos aparecerán en el informe de izquierda a derecha en el orden en
que aparecen en la oración de consulta. La vista predeterminada del ID de
registro, definida por el registro de diccionario @ID, siempre aparece como la
primera columna del informe, a menos que se suprima mediante la palabra
clave ID.SUP.
Ejemplos
LIST TITLES TITLE SUBJECT
LIST READERS NAME ADDRESS ID.SUP
Hay varias palabras clave no discutidas en este tutorial que pueden seguir un
nombre de campo para reemplazar la definición de diccionario para código de
conversión, código de formato, encabezado de columna, etc.
Si una oración de consulta no contiene nombres de campo, el procesador de

35
consultas busca en el diccionario una entrada de tipo PH (frase) denominada
@. Si se encuentra, se adjunta al final de la oración de consulta. Normalmente,
esta frase contiene una lista predeterminada de campos que se mostrarán, pero
también puede incluir otros elementos de oración de consulta. Si no hay una
frase @, sólo se mostrará el ID del registro.
Opciones de informes
Hay muchas opciones para modificar el formato de un informe. Estos incluyen
el establecimiento de encabezados de páginas y pie de páginas, especificando
márgenes y espaciamiento de columnas, puntos de interrupción y mucho más
La única opción discutida en este tutorial es la palabra clave LPTR.
Si la oración de consulta incluye la palabra clave LPTR, el informe se dirige a
una impresora en lugar del terminal. La impresora que se utiliza depende de la
forma en que se configura el sistema.
Los comandos QM y el software de aplicación envían su salida a una unidad
de impresión numerada. El destino real de cada unidad de impresión se
establece mediante el comando SETPTR, a menudo desde el párrafo LOGIN
u otro guion de inicialización.
Usado solo, la palabra clave LPTR hace que el procesador de consultas envíe
su salida a la unidad de impresión 0, la unidad de impresión predeterminada.
Alternativamente, la palabra clave LPTR puede ir seguida de un número de
unidad de impresión.
Cuando se utiliza la palabra clave LPTR y la oración de consulta no
contiene nombres de campo, el procesador de consultas busca primero una
frase llamada @LPTR como su frase de lista predeterminada y, si no se
encuentra, para la frase @. Esto permite que se muestre un conjunto
diferente de campos predeterminados en un informe impreso de uno que se
muestra en la pantalla.
Seleccionar Listas
Cada sesión de QM tiene a su disposición once listas de selección numeradas
en las que pueden crearse listas de identificadores de registro para su posterior
procesamiento. Las listas están numeradas de 0 a 10. La lista 0 se conoce
como la lista de selección predeterminada.
El procesador de consultas incluye un verbo SELECT que realiza la fase de
selección de una consulta pero guarda la lista generada de ID de registro sin
36
producir un informe. El verbo SELECT toma las mismas cláusulas de
selección y clasificación que LIST.
Muchos verbos QM, incluyendo todos los verbos del procesador de consultas,
comprueban si hay una lista de selección predeterminada activa y, si se
encuentra, utilice esta opción para proporcionar una lista de elementos a
procesar. Debido a los peligros de los efectos no deseados si una lista se deja
activa por accidente, el indicador de mandatos cambia a :: cuando la lista de
selección predeterminada está activa.
El verbo SELECT construye la lista 0 de forma predeterminada. Se puede
crear una lista alternativa utilizando la cláusula TO para especificar el número
de lista de destino. Del mismo modo, todos los verbos del procesador de
consultas tienen una cláusula FROM opcional para especificar la lista de
fuentes.
Ejemplos
SELECT TITLES WITH COPIES > 1
LIST TITLES
Este par de comandos es equivalente a:
LIST TITLES WITH COPIES > 1
Hay veces en las que podríamos realizar un SELECT en un archivo para
generar una lista de identificadores de registro para procesar en algún otro
archivo.
SELECT TITLES WITH SUBJECT = Art
DELETE TITLES
Este par de comandos borra todos los libros de arte de nuestro archivo
TITLES. ¡No lo hagas!

37
10.- Creación de un Menú de Informes
QM incluye un sistema fácil de usar para generar menús como parte de una
aplicación. Vamos a usar esto para construir un front end simple a nuestros
informes.
Para ingresar al editor de menús, escriba:
MED
Aparece un mensaje pidiendo que el nombre del archivo contenga el menú.
Guardaremos nuestro menú en el archivo VOC que se puede seleccionar
simplemente pulsando la tecla de retorno para ingresar una respuesta en
blanco.
El siguiente mensaje solicita el nombre del menú. Introduzca "LIB" ya que
esta es nuestra aplicación de biblioteca. Se le pedirá que confirme que desea
crear un nuevo menú.
La pantalla muestra ahora cinco líneas en las que se puede introducir texto
correspondiente a los siguientes aspectos del menú:
Title La línea del título que aparecerá en el menú
Subr El nombre de una subrutina que se utilizará para validar el
acceso de un usuario a cada opción de menú. Esto es opcional y
lo dejaremos en blanco.
Prompt El texto de solicitud de opción aparecerá al pie del menú.
Dejaremos esto en blanco para usar el texto del mensaje
predeterminado.
Exits Una lista separada por comas de los códigos que se pueden
utilizar para salir del menú a lo que se inició. No utilizaremos
esta función.
Stops Una lista de códigos separados por comas que se pueden utilizar
para salir del menú al símbolo del sistema. No utilizaremos esta
función.
A medida que trabaja a través de la entrada de datos, aparece un breve mensaje
de ayuda al pie de la pantalla.
Introduzca un título de menú adecuado tal como "Menú del Sistema de
Biblioteca" y presione repetidamente la tecla de retorno hasta que aparezcan
otras líneas pidiendo los detalles del primer elemento de menú. Estos detalles
38
son:
Text El texto del elemento de menú
Action El comando a ejecutar cuando se selecciona esta acción. Si el
comando termina con un punto y coma, el procesador del menú
emitirá un mensaje de "Presione volver para continuar" antes de
volver al menú. Esto será necesario en todos nuestros elementos
de menú de generación de informes.
Help Un mensaje de ayuda de línea única opcional para este elemento
de menú
Access Se pasa una clave a la subrutina de control de acceso. No
estamos utilizando esta función, por lo que este campo puede
dejarse en blanco.
Hide Determina si las opciones inaccesibles se muestran o se ocultan.
Dado que no estamos utilizando el control de acceso, esto puede dejarse en
blanco.
Introduzca tres elementos de menú para listar nuestros tres archivos de
base de datos. Una solución simple se muestra a continuación.
Title: Library System Menu
Subr:
Prompt:
Exits:
Stops:
--------------------------------------------------
Text: Display title information
Action: LIST TITLES;
Help: Lists the TITLES file
Access:
Hide:
--------------------------------------------------
Text: Display book copy information
Action: LIST BOOKS;
39
Help: Lists the BOOKS file
Access:
Hide:
--------------------------------------------------
Text: Display reader information
Action: LIST READERS;
Help: Lists the READERS file
Access:
Hide:
Si comete un error, puede usar las teclas de cursor para desplazarse por los
datos y hacer correcciones.
El editor MED utiliza un subconjunto de las teclas de control del editor de
texto de pantalla completa SED. Puede obtener ayuda extendida para el
campo actual cuando está en MED pulsando la tecla F1. Al presionar de
nuevo F1 se muestra una pantalla de enlaces de teclas.
Una vez que esté satisfecho con su menú, puede guardarlo escribiendo
Ctrl-X seguido de: S.
Para salir de MED, escriba Ctrl-X seguido de C.
Para probar el menú, escriba su nombre (LIB) en el símbolo del sistema.

40
11.- Una Simple Solicitud de Gestión de Préstamos
La sección final de este tutorial reúne un programa QMBasic muy simple para
permitir a los lectores tomar libros en préstamo o devolverlos. En este
programa hay un manejo mínimo de la pantalla. Un programa más realista
probablemente usaría el constructor de pantalla SCRB. Si eres un
programador puedes aprender mucho más sobre el lenguaje QMBasic del QM
Reference Manual. También puede explorar la API QMClient que le permite
escribir frontends de estilo Windows a aplicaciones QM utilizando Visual
Basic.
La forma legible (programa fuente) de los programas QMBasic debe
mantenerse en un archivo de directorio. Por convención esto se llama a
menudo BP (Basic Programs). Cree un archivo BP en su cuenta de prueba
escribiendo:
CREATE.FILE BP DIRECTORY
QM proporciona dos editores de texto; ED, que es un editor basado en una
línea simple muy similar a la que se encuentra en varios otros productos de
base de datos MultiValor y SED que es un editor basado en pantalla
originalmente desarrollado para QM pero también disponible de Ladybridge
Systems para las bases de datos UniVerse y Unidata.
En este tutorial usaremos algunas de las funciones básicas de SED. Hay
muchas más que usted puede descubrir para hacer la edición mucho más fácil.
Nuestro programa se llamará LIB. Para iniciar el editor, escriba:
SED BP LIB
Se encontrará con una pantalla en blanco en la que se pueden escribir
declaraciones del programa. Las teclas de cursor se pueden utilizar para
moverse y las teclas de retroceso y borrado se pueden utilizar para eliminar
texto.
Este tutorial no se propone enseñar el lenguaje de programación QMBasic,
sino que vamos a guiarlo a través de la entrada de un programa muy simple
para mantener nuestros archivos de demostración. Los programadores
experimentados no deben tener problemas para aprender QMBasic del juego
de manual principal. Incluimos una discusión de los principios de este
programa más adelante.
El programa que vamos a montar no tiene errores de manejo. Asume, por
41
ejemplo, que las interrelaciones entre los archivos son correctas.
Introduzca el texto del programa que se muestra en las siguientes dos páginas.
Aunque hemos mostrado el programa en mayúsculas para seguir el estilo
convencional de lenguajes de programación de bases de datos MultiValor,
QM permite que los programas estén en minúsculas. Sólo los nombres de
archivo en las instrucciones OPEN deben estar en mayúsculas.
PROGRAM LIB * Open the files
OPEN 'TITLES' TO TTL.F ELSE ABORT
'Cannot open TITLES' OPEN 'BOOKS' TO
BKS.F ELSE ABORT 'Cannot open BOOKS'
OPEN 'READERS' TO RDR.F ELSE ABORT 'Cannot open
READERS'
* The main loop of the program prompts for a book
id and processes
* it. In a real application, this book id might
come from a barcode
* reader.
LOOP
DISPLAY 'Book id'
: INPUT BKS.ID
UNTIL BKS.ID = ''
* Fetch the details for this book
READU BKS.REC FROM BKS.F, BKS.ID THEN
* Read the corresponding TITLES record and
display the title
READ TTL.REC FROM TTL.F,
BKS.ID['-',1,1] THEN DISPLAY
'Book title : ' : TTL.REC<1>
END
* Extract the reader id from the BOOKS record
to decide if the
* book is out on loan or in stock.

42
RDR.ID = BKS.REC<1>
IF RDR.ID # '' THEN ;* Book is on loan
* Get the reader's details
READU RDR.REC FROM RDR.F, RDR.ID THEN
DISPLAY 'On loan to : ' : RDR.ID : ' ('
: RDR.REC<1> : ')' DISPLAY 'Date out :
' : OCONV(BKS.REC<2>, 'D2DMY[,A3]')
DISPLAY 'Return to stock' :
INPUT YN
IF UPCASE(YN) = 'Y' THEN
* Remove this book from the reader's loans
LOCATE BKS.ID IN RDR.REC<3,1>
SETTING POS THEN DEL
RDR.REC<3,POS>
END
WRITE RDR.REC TO RDR.F, RDR.ID
* Update the BOOKS file record to show the
book as in stock
BKS.REC<1> = '' ;* Clear reader field
BKS.REC<2> = '' ;* Clear date out field
END ELSE ;* Not returning, release record
lock
RELEASE RDR.F,
RDR.ID END
END
END ELSE ;* Book is in stock
* Ask for reader id to generate new loan
DISPLAY 'In stock'
DISPLAY 'Enter reader id to loan,
blank to ignore' INPUT RDR.ID
IF RDR.ID # '' THEN
43
READU RDR.REC FROM RDR.F, RDR.ID THEN
* Add this book to the reader's list of loans
RDR.REC<3,-1> = BKS.ID
WRITE RDR.REC TO RDR.F, RDR.ID
* Update the BOOKS file record to show the
book as on loan
BKS.REC<1> = RDR.ID ;* Set reader number
BKS.REC<2> = DATE() ;* Set loan date
END ELSE ;* Don't have this reader
number
RELEASE RDR.F, RDR.ID
DISPLAY 'Reader not on
file' END
END END
WRITE BKS.REC TO BKS.F, BKS.ID
END ELSE ;* Unknown book number entered -
Release the lock
RELEASE BKS.F, BKS.ID
DISPLAY 'Book is not
on file' END
DISPLAY
REPEAT
END
Una vez que haya ingresado este texto, guárdelo tecleando Ctrl-X seguido de
S y saliendo de SED escribiendo Ctrl-X seguido de C. (La misma secuencia
que para MED).
El programa ahora debe convertirse a una forma que QM puede ejecutar. Este
proceso se llama compilación y se realiza mediante el comando BASIC:
BASIC LIB
Si recibió mensajes de error, vuelva a introducir SED para corregir los errores
e intente de nuevo.

44
Una vez que su compilación se completa sin errores, puede ejecutar el
programa escribiendo:
RUN LIB
Entonces, ¿qué hace este programa? Vamos a desmontarlo paso a paso....
PROGRAM LIB
La línea PROGRAM es opcional y da un nombre al programa. El
nombre es totalmente ignorado y es sólo para documentación.
* Abrir los Archivos
OPEN 'TITLES' TO TTL.F ELSE ABORT 'No puede abrir
TITLES'
OPEN 'BOOKS' TO BKS.F ELSE ABORT 'No puede abrir
BOOKS'
OPEN 'READERS' TO RDR.F ELSE ABORT 'No puede abrir
READERS'
Las tres instrucciones OPEN abren los archivos. Cada uno incluye el nombre
de una variable de archivo (e.g. TTL.F) la cual será usada en el programa para
referirse al archivo. La cláusula ELSE del OPEN es ejecutada si falla la
apertura. En este caso una declaración ABORT es usada para terminar el
programa con un mensaje de error.
* The main loop of the program prompts for a book
id and processes
* it. In a real application, this book id might
come from a barcode
* reader. LOOP
La instrucción LOOP marca el inicio de un bucle terminado por una
instrucción REPEAT (casi en la parte inferior de nuestro programa). Cada vez
que llegamos al REPEAT, el programa salta de nuevo al LOOP para
comenzar todo de nuevo.
DISPLAY 'Book id': INPUT BKS.ID
La sentencia DISPLAY muestra el texto dado. Los dos puntos finales son una
sintaxis especial que hace que el cursor permanezca al final del texto mostrado
en lugar de moverse al principio de la siguiente línea.
La instrucción INPUT le pide al usuario que introduzca datos mostrando un
45
signo de interrogación (puede ser cambiado o suprimido) y luego toma los
datos del teclado, almacenándolos en una variable denominada BKS.ID hasta
que se presione la tecla de retorno. Podrías usar cualquier nombre de variable
que te guste. Hemos decidido adoptar una convención simple en la que nuestro
archivo BOOKS utiliza la variable de archivo BKS.F y el ID de registro se
almacena en BKS.ID
UNTIL BKS.ID = ''
La instrucción UNTIL es parte de la construcción LOOP/REPEAT. Cuando
se cumple la condición (se ingresa un identificador de libro en blanco), el
programa saltará a la instrucción que sigue a la REPEAT saliendo así del
bucle.
* Fetch the details for this book
READU BKS.REC FROM BKS.F, BKS.ID THEN
La instrucción READU lee el registro de archivo BOOKS para el ID de libro
dado. Nuestra convención de nomenclatura de variables utiliza BKS.REC
para almacenar un registro del archivo BOOKS. La instrucción READU toma
un bloqueo de actualización en el registro. Esto evita que otro usuario acceda
al mismo registro mientras realizamos nuestra actualización. Como este
programa está escrito, simplemente esperar a que terminemos. READU tiene
una opción para permitir que el programador tome su propia acción si una
lectura falla porque otro usuario tiene el registro bloqueado.
Si tenemos éxito en la lectura del registro, ejecutamos la cláusula THEN (toda
la declaración hasta END correspondiente.) Obsérvese cómo nuestra
indentación hace que este apareamiento sea fácil de ver. Si la lectura falla
porque el registro no existe, ejecutaremos la cláusula ELSE (si está presente).
En este caso, la cláusula ELSE está casi al final del programa.
* Read the corresponding TITLES record and display
the title
READ TTL.REC FROM TTL.F, BKS.ID['-',1,1] THEN
DISPLAY 'Book title : ' : TTL.REC<1> END
También necesitamos leer el registro TITLES de este libro. Aquí utilizamos
READ en lugar de READU. La instrucción READ no utiliza ningún bloqueo.
Otro usuario podría estar trabajando con una copia diferente del mismo libro
donde bloquear el registro TITLES le haría esperar. En general, bloqueamos

46
los registros que podríamos cambiar; No bloqueamos registros que
simplemente estamos viendo.
El constructo BKS.ID['-', 1,1] debería resultar familiar ya que usamos esto en
uno de nuestros registros de diccionarios tipo I antes para extraer el ID de
registro de archivo TITLES del ID de BOOKS.
La sentencia DISPLAY muestra el texto fijo (título del libro:) seguido del
título del libro. En nuestros tipos I podríamos referirnos a campos por nombre.
Los programas de QMBasic no tienen una forma automática de usar el
diccionario para buscar campos por nombre. En su lugar, usamos la
construcción de extracción de campo (por ejemplo, TTL.REC<1>) para
extraer el campo 1. Hay formas en que los programadores pueden dar nombres
a los campos, pero no lo hemos hecho aquí.
* Extract the reader id from the BOOKS record to
decide if the
* book is out on loan or in stock.
RDR.ID = BKS.REC<1>
IF RDR.ID # '' THEN ;* Book is on loan
Al examinar el campo READERS (campo 1) del registro BOOKS, sabemos
si el libro está en préstamo y, en caso afirmativo, a quién.
* Get the reader's details
READU RDR.REC FROM RDR.F, RDR.ID THEN
DISPLAY 'On loan to : ' : RDR.ID : ' (' :
RDR.REC<1> : ')' DISPLAY 'Date out : ' :
OCONV(BKS.REC<2>, 'D2DMY[,A3]')
Para un libro que está en préstamo, leemos los detalles del archivo
READERS, bloqueándolo porque probablemente estamos devolviendo el
libro a las existencias. También mostramos el identificador del lector, su
nombre y la fecha en la que el libro fue sacado. La función OCONV() realiza
la conversión de salida para mostrar la fecha en un formato útil.
DISPLAY 'Return to stock' : INPUT YN
IF UPCASE(YN) = 'Y' THEN
Ahora preguntamos si el libro debe ser devuelto a la acción. La respuesta debe
ser Y o N. Para permitir la entrada de las respuestas en mayúsculas o
47
minúsculas, usamos la función UPCASE() para convertir la respuesta en
mayúsculas antes de probar si era Y. Un programa real probablemente haría
alguna mejor validación de la respuesta.
* Remove this book from the reader's loans
LOCATE BKS.ID IN RDR.REC<3,1> SETTING POS THEN DEL
RDR.REC<3,POS>
END
El lector puede tener varios libros en préstamo. No podemos simplemente
borrar el campo LOANS del registro de READERS. En su lugar, utilizamos
la sentencia LOCATE muy potente para buscar el id del libro en la lista y la
instrucción DEL para eliminarla.
WRITE RDR.REC TO RDR.F, RDR.ID
El registro del archivo READERS ahora se puede volver a escribir en el
archivo. Esta acción liberará automáticamente el bloqueo de registro,
permitiendo que otro usuario acceda.
* Update the BOOKS file record to show the book as
in stock
BKS.REC<1> = '' ;* Clear reader field
BKS.REC<2> = '' ;* Clear date out field
También debemos borrar la identificación del lector y la fecha del registro de
BOOKS. Este registro se escribe de nuevo en el archivo en una ruta de acceso
que es común a ambos préstamos y devuelve más tarde.
END ELSE ;* Not returning, release record lock
Si el usuario introduce N en el indicador preguntando si el libro debe ser
devuelto, debemos liberar el bloqueo que mantenemos en el registro de
READERS para que otros usuarios puedan acceder a él.
RELEASE RDR.F, RDR.ID END
END
END ELSE ;* Book is in stock
Si el libro está en stock, estamos procesando un nuevo préstamo.
* Ask for reader id to generate new loan
DISPLAY 'In stock'
48
DISPLAY 'Enter reader id to loan, blank to ignore'
INPUT RDR.ID
Solicitar e ingresar el ID de lector de este préstamo.
IF RDR.ID # '' THEN
READU RDR.REC FROM RDR.F, RDR.ID THEN
Si se ingresó un ID de lector, lea el registro del archivo READERS,
bloqueándolo si lo vamos a actualizar.
* Add this book to the reader's list of loans
RDR.REC<3,-1> = BKS.ID
Esta sintaxis especial añade un nuevo valor a una lista, en este caso la lista de
préstamos por lector.
WRITE RDR.REC TO RDR.F, RDR.ID
Ahora podemos escribir el registro de los READERS para mostrar el libro
como en préstamo al lector.
* Update the BOOKS file record to show the book as
on loan
BKS.REC<1> = RDR.ID ;* Set reader number
BKS.REC<2> = DATE() ;* Set loan date
El registro del archivo BOOKS debe ser actualizado para mostrar el ID del
lector y la fecha del préstamo. La función DATE() devuelve la fecha de hoy
en forma interna.
END ELSE ;* Don't have this reader number
RELEASE RDR.F, RDR.ID
DISPLAY 'Reader not on file'
Debemos atender el error de introducir un identificador de lector no válido.
Aquí simplemente liberamos el bloqueo (aunque el registro no existiera,
hemos bloqueado el ID) y mostraremos un mensaje de error.
END END
END
WRITE BKS.REC TO BKS.F, BKS.ID
La ruta común para todas las actualizaciones escribe el registro
49
(posiblemente) modificado BOOKS en el archivo. Esto también libera el
bloqueo, dejando que otros usuarios accedan al libro. Si decidimos no
devolver un libro que está en préstamo o introducido un número de lector en
blanco o no válido para un nuevo préstamo, seguiremos realizando esta
escritura. Aunque los datos del registro BOOKS no han cambiado, esta es
una manera fácil de asegurar que también hemos liberado el bloqueo.
END ELSE ;* Unknown book number entered -
Release the lock
RELEASE BKS.F, BKS.ID
DISPLAY 'Book is not on file'
Para un número de libro no válido también debemos asegurarnos de liberar el
bloqueo.
END
DISPLAY
El procesamiento de cada ID de libro termina con la salida de una línea en
blanco para hacer que la pantalla sea más legible.
REPEAT END
Y aquí, por fin, está el final de nuestro ciclo de procesamiento y un END para
terminar el programa.

50

Das könnte Ihnen auch gefallen