Práctica sobre consultas y vistas

Anuncio
Edmundo Cáceres
Práctica sobre consultas y vistas
2008
Edmundo A. Cáceres — Práctica sobre consultas y Vistas — 2008
Consultas
Ejercicio 1
Cree una consulta con los campos ART y NOM de la tabla ART, que muestre los nombres de los artículos ordenados alfabéticamente, de menor a mayor.
1. Cree una consulta. Puede hacerlo con ARCHIVO – NUEVO – CONSULTA– NUEVO ARCHIVO. Otra forma
es ubicarse en la categoría CONSULTAS de un proyecto, pulsar el botón NUEVO y después el botón
NUEVA CONSULTA. Una tercera forma es emitir el comando CREATE QUERY seguido por el nombre que
va a tener la nueva consulta. Se abre el DISEÑADOR DE CONSULTAS, en blanco. Dado que suponemos que cuenta con el proyecto FAC, use la segunda forma.
Toda consulta trabaja sobre una o más tablas y/o vistas de entrada. Por ello, junto al diseñador se
abrirá un diálogo para seleccionar una de estas entradas. Si hay alguna base de datos (BD) abierta, el diálogo será AGREGAR TABLA O VISTA, para elegir lo necesitado. Si no hay una BD abierta, el
diálogo será ABRIR, para agregar la primera tabla. Luego se cierra este diálogo, que es reemplazado por AGREGAR TABLA O VISTA, siempre que la tabla abierta sea de BD. Esto se debe a que VFP obtiene de la primera tabla agregada información sobre la BD a que pertenece: esto explica el reemplazo del diálogo, dado que el segundo es más práctico y permite elegir la categoría VISTAS. Este
segundo diálogo permanece abierto para seguir agregando tablas o vistas, mediante el botón
AGREGAR. Para cerrarlo se usa el botón CERRAR. Este diálogo se puede abrir posteriormente en
cualquier momento, eligiendo la opción AGREGAR TABLA del menú contextual sobre el DISEÑADOR DE
CONSULTAS.
El botón OTRAS de AGREGAR TABLA O VISTA sirve para elegir tablas que no pertenezcan a las BD
abiertas, las cuales aparecen en la cuadro combinado BASES DE DATOS. El botón OTRAS presenta el
diálogo ABRIR. Estas tablas adicionales pueden ser libres o de otras BD. En el segundo caso, se
abrirá la tabla y la BD a que pertenece, agregándose el nombre de ésta a la lista del cuadro combinado.
En AGREGAR TABLA O VISTA, bajo el nombre SELECCIONAR hay dos botones: TABLAS y VISTAS. Estos
botones cambian lo que muestra el cuadro de lista cuya etiqueta dirá TABLAS EN LA BASE DE DATOS y
VISTAS EN LA BASE DE DATOS.
2. Agregue la tabla ART, que se verá como un cursor en el panel superior (entorno) del DISEÑADOR DE
CONSULTAS.
Cada tabla o vista agregada se representa en el panel superior como cursor. En cada uno se listan
verticalmente sus campos, precedidos por un asterisco, que representa todos los campos del cursor. Todos los campos de los cursores agregados aparecen en el cuadro CAMPOS DISPONIBLES de la
ficha CAMPOS, prefijados con el nombre del cursor respectivo.
3. En la ficha CAMPOS, transfiera los campos ART.ART y ART.NOM de la lista CAMPOS DISPONIBLES a la
lista CAMPOS SELECCIONADOS.
Usando CAMPOS DISPONIBLES, la transferencia de un campo se puede hacer seleccionándolo y pulsando el botón AGREGAR, dándole doble click o arrastrándolo a la lista CAMPOS SELECCIONADOS.
Usando el cursor, se puede hacer con doble click o arrastrándolo.
Para transferir todos los campos de todos los cursores se usa el botón AGREGAR TODOS. Para transferir todos los campos de un solo cursor se usa el asterisco, con doble click o arrastre.
Para transferir a la vez algunos campos, se los selecciona en CAMPOS DISPONIBLES o en un cursor y
se usa el botón AGREGAR o el arrastre.
—1—
Edmundo A. Cáceres — Práctica sobre consultas y Vistas — 2008
La devolución de un campo de CAMPOS SELECCIONADOS a CAMPOS DISPONIBLES se hace seleccionándolo y pulsando QUITAR, dándole doble click o arrastrándolo.
La devolución de todos los campos se hace con el botón QUITAR TODOS.
Para devolver algunos campos de un mismo cursor, se los selecciona y se pulsa QUITAR o se los
arrastra.
Los campos seleccionados son los que la consulta va a producir, contenidos en un cursor que se
verá en la ventana EXAMINAR. En este primer ejemplo no veremos que la consulta hace gran cosa,
porque lo mismo podríamos lograr examinando la tabla ART. Sin embargo, a medida que avancemos, veremos que tienen mucha potencia.
4. Seleccione la ficha ORDENAR POR y transfiera el campo NOM de CAMPOS SELECCIONADOS a
CRITERIOS DE ORDENACIÓN. Los recursos para transferir campos son análogos a los explicados antes. En OPCIONES DE ORDEN active el botón ASCENDENTE.
Las consultas permiten ordenar los registros del cursor de salida por uno o varios de sus campos.
En este caso, solamente ordenamos por uno sólo, NOM. Note que los campos por los que podemos
ordenar son los que componen el cursor de salida, no los de los cursores de entrada: los campos
para ordenar son los seleccionados en la ficha CAMPOS.
5. Ejecute la consulta, eligiendo EJECUTAR CONSULTA en el menú contextual o en el menú CONSULTA.
Veremos el resultado en una ventana EXAMINAR, de sólo lectura. Compruebe esto tratando de modificar el contenido de cualquier campo: se nos dará el mensaje El control es de sólo lectura. Veremos luego que el resultado de las vistas también es un cursor que se ve en la ventana EXAMINAR,
pero que permite modificar el valor de los campos.
6. Salga de la ventana EXAMINAR con ESC.
7. Guarde la consulta con el nombre CON1 y luego ciérrela.
Para guardar puede usar ARCHIVO – GUARDAR o ARCHIVO – GUARDAR COMO. Si el archivo aún no está guardado, GUARDAR llamará al diálogo GUARDAR COMO. Si ya está guardado, guardará las nuevas modificaciones. CTRL + S es igual a ARCHIVO – GUARDAR. Cierre el diseñador con ARCHIVO –
CERRAR o con ESC. Si pulsa ESC y aún no ha guardado el archivo, VFP preguntará si lo quiere
guardar. Si contesta que sí, se presenta el diálogo GUARDAR COMO y después se cierra el diseñador. Otra forma de guardar y salir es con CTRL + W, que pide un nombre para el archivo si todavía
no lo tiene.
Ejercicio 2
Cree la consulta CON2, similar a CON1, pero que liste solamente los artículos cuyo código de artículo
(campo ART), comience con la letra C.
1. Para aprovechar el trabajo realizado en CON1, seleccione este archivo en el proyecto FAC y pulse
MODIFICAR. Esto abrirá CON1 en el DISEÑADOR DE CONSULTAS.
2. Dé el comando ARCHIVO – GUARDAR COMO. En el diálogo de igual nombre, denomine CON2 al duplicado a crear. Después de eso, verá que la consulta que queda en el diseñador es CON2, de modo
que vamos a trabajar sobre ella. Para saber sobre qué consulta está trabajando, lea la barra de título del diseñador.
3. Seleccione la ficha FILTRO. En NOMBRE DE CAMPO elija ART.ART. En CRITERIOS elija el operador = y
en EJEMPLO escriba "C".
4. Guarde la consulta con CTRL + S y luego ejecútela. Salga con ESC de la ventana EXAMINAR y vuelva
a dar ESC para salir del diseñador.
—2—
Edmundo A. Cáceres — Práctica sobre consultas y Vistas — 2008
5. La nueva consulta no aparece en el proyecto, porque si bien fue creada y modificada, no fue agregada a él. Para hacerlo, en el ámbito CONSULTAS del proyecto pulse AGREGAR. En el diálogo ABRIR
seleccione el archivo CON2 y pulse ACEPTAR. Luego de ello, la nueva consulta quedará registrada
en el proyecto y se verá dentro del ámbito CONSULTAS.
La ficha FILTROS sirve para hacer que algunos registros de entrada entren al proceso de la consulta
y otros no. Para ello se usa un campo, que se compara contra un valor. Si el resultado lógico de la
comparación es verdadero, el registro entra al proceso; de lo contrario, el registro se ignora y no influye en el cursor resultante.
Que lo establecido en la ficha FILTROS afecta los registros de entrada se pone de manifiesto en la
lista NOMBRE DE CAMPO, donde se ofrecen todos los campos de entrada, es decir, los mismos de la
lista CAMPOS DISPONIBLES de la ficha CAMPOS o los que se ven en los cursores de entrada. En este
ejercicio, el filtro se aplica al campo ART, que también figura en la lista CAMPOS SELECCIONADOS. Pero podríamos haber aplicado el filtro al campo PRE, que no es un campo seleccionado para confeccionar el cursor de salida.
La ficha FILTROS permite descartar registros de entrada usando cualquiera de sus campos o expresiones construidas sobre ellos, sin darles salida en el cursor resultante. Este campo o expresión se
escribe en NOMBRE DE CAMPO.
El filtro establecido en una consulta es estático: permanece fijo mientras no lo modifiquemos en la
consulta. Puede darse el caso que usted diseñe la consulta CON2 para que la ejecuten otras personas que no saben nada de diseño. Cuando se quiera que la consulta dé por resultado los registros cuyo código de artículo comience con la letra A, B, D, etc., cualquier otra letra distinta a C, usted, el único experto en este tema, tendrá que modificar CON2. Ahora bien, ¿qué pasará cuando
usted no esté presente, porque está enfermo o de vacaciones? Los demás no podrán obtener lo
que deseen, hasta que usted no regrese. Este problema no puede solucionarse en las consultas,
sino en las vistas, que usan una técnica llamada parametrización, tema que veremos posteriormente.
En CRITERIOS aparecen distintos operadores, para comparar si un campo es igual, menor, mayor,
etc., que el valor escrito en EJEMPLO. El botón NO sirve para negar el operador elegido, obteniendo
no igual (distinto), no menor (mayor o igual), no mayor (menor o igual), etc.
El operador =, aplicado a caracteres, considera la igualdad parcial del valor del campo y del ejemplo, de izquierda a derecha, hasta que se acaba el ejemplo. Por ello, en el ejercicio, los valores
C01, C02, C03, etc., del campo ART, son iguales al valor del ejemplo, C. El operador = puede aplicarse a campos o expresiones numéricas, de fecha, de fecha–hora y lógicas.
El operador == da por iguales los valores del campo y del ejemplo cuando son totalmente iguales,
no parcialmente iguales.
El operador BETWEEN compara el valor de un campo con un intervalo de valores, que se expresan
en EJEMPLO indicando el menor y el mayor, separados por una coma. Así, si en EJEMPLO hubiera
escrito A,D, en el resultado vería todos los artículos cuyo código comienzan con A, B, C y D.
El operador IN compara el valor de un campo con un conjunto de valores no sucesivos, que se expresan en EJEMPLO listándolos, separados por comas. Si en EJEMPLO hubiera escrito A, C, F, sólo
vería los artículos cuyo código comienzan con A, C y F. No hace falta que los valores sean escritos
en orden: podría haberlos indicado como A,F,C, como F,A,C o como F,C,A.
El operador LIKE sirve para introducir comodines en el valor de EJEMPLO. A diferencia de los conocidos comodines ? y *, SQL usa _ (subrayado) para representar cualquier valor en una posición
específica y % (porcentaje) para representar cualquier valor en en una o más posiciones. Por
ejemplo, para filtrar los nombres de artículo que comienzan con A, LIKE exige expresar en EJEMPLO
—3—
Edmundo A. Cáceres — Práctica sobre consultas y Vistas — 2008
la expresión A% o "A%". Para filtrar los nombres que tienen una a minúscula en la segunda posición, el filtro se escribe _a% o "_a%". Para filtrar los nombres que tienen dos a minúsculas en cualquier posición, el filtro es %a%a% o "%a%a%". Los ejemplos dados evidencian que LIKE distingue
entre mayúsculas y minúsculas.
No comentamos el operador IS NULL, porque no nos interesa trabajar con valores nulos.
Dado que el campo ART es de caracteres, SQL entiende que sólo se puede comparar contra caracteres, por lo que, si no se escribe entre comillas el valor de EJEMPLO, lo corrige y lo encierra entre
comillas. Para evitar problemas, escríbalo siempre entre comillas.
El botón M / M sirve para distinguir entre mayúsculas y minúsculas, cuando no se activa. Si no lo activa y escribe c, no se listará ningún artículo que comience con c minúscula. Si lo activa y escribe C
o c, listará todos los artículos que comiencen con esa letra.
Ejercicio 3
Se quiere una consulta CON3 que muestre los artículos cuyo precio, aumentado un 15%, supere $180.
Los campos de salida serán ART, NOM y el nuevo precio.
1. Cree una nueva consulta. Agregue la tabla ART. En la ficha CAMPOS, agregue los campos ART y
NOM.
. Cree la expresión
2. En FUNCIONES Y EXPRESIONES, llame al GENERADOR DE EXPRESIONES con
ART.PRE * 1.15. Cierre el generador. La expresión queda en FUNCIONES Y EXPRESIONES.
3. Pulse el botón AGREGAR. Esto transfiere la expresión a CAMPOS SELECCIONADOS, como un campo
calculado.
4. Seleccione la ficha FILTROS. En NOMBRE DE CAMPO seleccione <EXPRESIÓN…>. En el GENERADOR DE
EXPRESIONES escriba ART.PRE * 1.15. En CRITERIOS seleccione > y en EJEMPLO escriba 180.
5. Ejecute la consulta. La columna del nuevo precio dice Exp_1 (o Exp_2, o Exp_3, etc., según la cantidad de campos calculados agregados como campo seleccionado). Este título de la columna no es
para nada claro, por lo que conviene darle otro más apropiado.
6. En la ficha CAMPOS, seleccione la expresión. Pulse el botón QUITAR, para sacar el campo calculado
de CAMPOS SELECCIONADOS y devolverlo a FUNCIONES Y EXPRESIONES. Pulse . En el GENERADOR
DE EXPRESIONES, corrija la expresión por ART.PRE * 1.15 AS NUEVO_PRECIO. Cierre el generador.
Transfiera la expresión corregida a CAMPOS SELECCIONADOS con el botón AGREGAR.
7. Vuelva a ejecutar la consulta. Ahora la última columna tiene un nombre apropiado. Hemos escrito
Nuevo_precio y no Nuevo precio, porque los nombres de campo no aceptan blancos. El guión bajo
salva este problema.
8. Guarde la consulta con el nombre CON3. Para evitar perder el trabajo en caso de corte de energía,
podría haberla guardado en cualquier paso intermedio, repitiendo la operación cada tanto con con
CTRL + S. No olvide guardarla cuando todo esté concluido con éxito.
El título de la tercera columna está bien y es completo, pero las otras columnas son ART y NOM,
igual al nombre de los campos. Corrijamos estos títulos, para que tengan nombres completos.
9. En la ficha CAMPOS devuelva los campos ART y NOM. En FUNCIONES Y EXPRESIONES escriba ART.ART
AS ARTÍCULO y transfiérala a CAMPOS SELECCIONADOS.
10. Haga lo mismo para el campo NOM, escribiendo la expresión ART.NOM AS NOMBRE.
11. En CAMPOS SELECCIONADOS aparecen tres campos calculados, pero no en el orden con que se desea que aparezcan en la ventana EXAMINAR. El que está más arriba será la primera columna, el que
—4—
Edmundo A. Cáceres — Práctica sobre consultas y Vistas — 2008
le sigue será la segunda, y así. Para reordenarlos, mueva la disposición de los campos seleccionados tomándolos de los botones que los preceden y arrastrándolos hacia arriba o abajo.
12. Ejecute la consulta y guárdela cuando esté bien.
Ejercicio 4
Se quiere una consulta CON4 que muestre todos los campos de la tabla LINFAC, agregando un campo
calculado con el producto del precio por la cantidad. De este modo obtendremos el parcial de cada artículo que compone cada factura. El resultado debe estar ordenado por número de factura y dentro de
cada número por el código de artículo.
1. Cree una consulta. Agregue la tabla LINFAC. En la ficha CAMPOS, agregue todos los campos a
CAMPOS SELECCIONADOS.
2. En FUNCIONES Y EXPRESIONES escriba LINFAC.PRE * LINFAC.CAN AS PARCIAL y agréguela a CAMPOS
SELECCIONADOS.
3. En la ficha ORDENAR POR, agregue el campo FAC a CRITERIOS
CENDENTE. Agregue luego el campo ART en orden ASCENDENTE.
DE ORDENACIÓN,
con orden AS-
Si quisiéramos construir un índice por los mismos conceptos para la tabla LINFAC, deberíamos usar
la expresión STR(LIFAC.FAC,8,0) + LINFAC.ART e indicar si el orden va a ser ascendente o descentente. El orden se aplica a la totalidad de la expresión, es decir, a cada componente. En las consultas cada componente puede tener su propio orden.
Note que, aunque existiera tal índice, SQL no lo tiene en cuenta, por lo que hay que establecer el
orden en la ficha ORDENAR POR.
4. Guarde y ejecute la consulta.
Ejercicio 5
La consulta CON4 muestra los totales parciales de cada factura, pero no el total general de ellas. Se
quiere una consulta, CON5, con el campo FAC y un campo calculado con la suma de los productos parciales entre cantidad y precio, para obtener el total general de cada factura. Los registros de salida deben estar ordenados por factura.
1. Cree una nueva consulta. Agregue la tabla LINFAC. Haga de FAC un campo seleccionado.
2. Agregue como campo seleccionado la expresión SUM(LINFAC.CAN * LINFAC.PRE) AS TOTAL.
3. Guarde y ejecute la consulta CON5.
Observe que la ventana EXAMINAR muestra un solo registro. ¿Por qué? La función SUM( ) suma la
expresión numérica contenida o calculada en cada registro. Esto lo hace con todos los registros de
la tabla LINFAC. Cuando ya no hay más registros a procesar, da por resultado un solo registro, con
el total de lo calculado. Por eso se dice que SUM( ) es una función de agrupamiento.
Si observa el registro resultante, el campo FAC se refiere a una sola factura, pero el campo TOTAL
es el importe de todas las facturas. La información de FAC es incoherente, porque usted eligió este
dato para la salida. La incoherencia la genera usted, no SQL. Como SQL debe dar salida a un número de factura, habiendo muchas facturas dará el número de la última que encuentre.
Felizmente, dado que usted quiere el total de cada factura, hay una manera de lograrlo.
4. En la ficha AGRUPAR POR, transfiera el campo FAC de CAMPOS DISPONIBLES a CAMPOS AGRUPADOS.
5. Ejecute la consulta. Ahora sí los resultados son los esperados.
Observe que CAMPOS DISPONIBLES le ofrece agrupar por cualquier campo de la tabla, esté o no seleccionado como salida. Si usa para agrupar un campo que no va a figurar en la salida, SQL lo
—5—
Edmundo A. Cáceres — Práctica sobre consultas y Vistas — 2008
agregar por su cuenta a CAMPOS SELECCIONADOS de la ficha CAMPOS. Pero si usted quiere agrupar
por él pero no tenerlo en la salida, puede eliminarlo de esa lista.
Quede claro, entonces, que el agrupamiento afecta los registros de entrada. En el ejemplo, como
se quiere un total por cada factura, SQL ordena los registros de entrada de modo que primero queden todos los correspondientes a la factura 1, formando un grupo, luego todos los correspondientes
a la factura 2, etc. Teniendo los registros ordenados de esa manera, SQL puede dar un total correcto de la factura 1, que muestra como un único registro en la salida. Lo mismo para la factura 2,
etc.
Insistamos en cómo trabaja el agrupamiento. Cuando se agrupa, SQL ordena los registros de entrada por el criterio de ordenamiento, formando grupos. Luego, para todos los registros de un grupo
de entrada, produce un solo registro de salida con lo calculado. Pone en cero lo calculado y repite
el proceso para el grupo siguiente, produciendo otro registro de salida.
La dicho en el párrafo anterior se aclara más ejemplificando con datos. Suponga que la tabla
LINFAC tiene los siguiente registros, en orden de grabación.
Linfac
Fac Art Can Pre
1 A05 5
10
2 B01 4
15
3 D03 1
20
1 C02 2
40
2 A05 2
10
1 A04 4
25
3 A02 1
90
3 A06 2
45
2 C01 5
50
Como debe agrupar por FAC, SQL ordena internamente los registros de entrada por tal campo,
quedando:
Linfac ordenada
Fac Art Can Pre
1 A05 5
10
1 C02 2
40
1 A04 4
25
2 B01 4
15
2 A05 2
10
2 C01 5
50
3 D03 1
20
3 A02 1
90
3 A06 2
45
Ahora puede calcular la expresión SUM(LINFAC.PRE * LINFAC.CAN)
grupo de la factura 1, el cálculo irá incrementándose como sigue:
Linfac ordenada
Fac Art Can Pre
1 A05 5
10
1 C02 2
40
1 A04 4
25
AS
TOTAL. Comenzando por el
Cálculos
Linfac.pre * Linfac.can SUM(Linfac.pre * Linfac.can)
50
50
80
130
100
230
—6—
Edmundo A. Cáceres — Práctica sobre consultas y Vistas — 2008
Cuando SQL llega a la factura 2, es porque se ha acabado completamente la factura 1. Entonces
genera un registro de salida para la factura 1.
Cursor de salida
Fac
Total
1
230
Con la factura 2 hace lo mismo:
Linfac ordenada
Fac Art Can Pre
2 B01 4
15
2 A05 2
10
2 C01 5
50
Cálculos
Linfac.pre * Linfac.can SUM(Linfac.pre * Linfac.can)
60
60
20
80
250
330
SQL genera un nuevo registro y lo agrega al cursor de salida:
Cursor de salida
Fac
Total
1
230
2
330
Finalmente, con la factura 3, SQL realiza los siguientes cálculos:
Linfac ordenada
Fac Art Can Pre
3 D03 1
20
3 A02 1
90
3 A06 2
45
Cálculos
Linfac.pre * Linfac.can SUM(Linfac.pre * Linfac.can)
20
20
90
110
90
200
SQL agrega el total de la factura 3 al cursor de salida, en un nuevo registro:
Cursor de salida
Fac
Total
1
230
2
330
3
200
Aunque no hemos usado la ficha ORDENAR POR, los registros salen ordenados por factura. Esto es
porque SQL, para hacer el cálculo, previamente ordenó internamente los registros de entrada por
factura, como se ha indicado. Las entradas, entonces, tienen el orden necesitado para la salida. Si
se necesitara otro orden para la salida, por ejemplo por TOTAL descendente, se puede hacer sin
ningún inconveniente usando ORDENAR POR, que, como se ha dicho, ordena los registros de salida.
Otra advertencia es que el agrupamiento se puede hacer por más de un campo. Por ejemplo, en la
tabla ENCFAC podríamos agrupar por los campos CLI y FEC. Cada grupo esaría formado por el valor
conjunto de ambos campos, de modo que, a los efectos del cálculo, es lo mismo la combinación
CLI – FEC que FEC – CLI. Sin embargo, a los efectos del orden interno, que puede ser aprovechado
sin usar la ficha ORDENAR POR, no es lo mismo. Por ello, en CAMPOS AGRUPADOS, cada campo tiene
un botón que permite arrastrarlo hacia arriba o abajo, logrando el ordenamiento adecuado: el campo que está arriba es el que tiene mayor prioridad, la cual desciende por los demás campos de
modo jerárquico.
Ejercicio 6
Se quiere una consulta CON6 que haga básicamente lo mismo que CON5, pero que solamente genere
registros de totales para las facturas cuyos importes superen $1000.
—7—
Edmundo A. Cáceres — Práctica sobre consultas y Vistas — 2008
1. Abra CON5 y guárdela como CON6. Cierre CON5. Agregue CON6 al proyecto y ábrala para modificarla.
2. En la ficha AGRUPAR POR pulse el botón CONDICIONES. Esto trae un diálogo de igual nombre, que
sirve para filtrar registros de salida.
3. En NOMBRE DEL CAMPO elija el campo calculado TOTAL. En CRITERIOS elija el operador >=. En
EJEMPLO escriba 1000.
4. Ejecute y guarde la consulta.
El botón CONDICIONES de la ficha AGRUPAR POR sirve para establecer filtros para los registros de salida. Si usted quiere poner filtros a los totales de factura, no puede hacerlo en la ficha FILTROS, porque los filtros establecidos en ella se aplican a los registros de entrada. Como los totales son una
suma de los productos precio por cantidad de los registros componentes de cada factura, no existen como datos de la entrada, sino que resultan de cálculos aplicados a cada grupo. Por ello los totales deben filtrarse en los registros de salida, para lo cual existe el diálogo CONDICIONES.
Ejercicio 7
Se quiere CON7 que haga lo mismo que CON5, pero que muestre las 10 facturas cuyo totales sean los
mayores.
1. Guarde CON5 como CON7. Agregue CON7 al proyecto y entre a modificarla.
2. En la ficha ORDENAR POR, agregue SUM(LINFAC.PRE * LINFAC.CAN)
ORDENACIÓN, con opción de orden DESCENDENTE.
AS
TOTAL a CRITERIOS
DE
3. Ejecute la consulta.
Aparecen todos los registros, ordenados de mayor a menor por TOTAL. Pero nosotros queremos solamente los 10 primeros registros de esa salida, que tienen los totales mayores.
4. En la ficha VARIOS, desactive el botón TODOS de REGISTROS INCLUIDOS y escriba 10 en NÚMERO DE
REGISTROS.
5. Ejecute la consulta y guárdela.
Si en lugar de los 10 mejores quisiera el 10% de los registros, deberá activar el botón PORCENTAJE.
Ejercicio 8
Cree CON8 para obtener el total vendido de cada artículo.
1. Cree una nueva consulta. Agregue la tabla LINFAC. Seleccione como salida el campo ART y la expresión SUM(LINFAC.PRE * LINFAC.CAN) AS VENDIDO.
2. Agrupe por el campo ART.
3. Ejecute y guarde la consulta.
Ejercicio 9
Cree CON9 para obtener todos los campos de la tabla LINFAC, agregando en cada registro el nombre de
cada artículo, que debe tomar de la tabla ART.
1. Cree una consulta. Agregue la tabla LINFAC. Agregue todos los campos.
2. En el DISEÑADOR DE CONSULTAS, pulse el botón secundario y elija AGREGAR TABLA.
3. En el diálogo AGREGAR TABLA O VISTA, selecciones la tabla ART y pulse ACEPTAR. Esto abre el diálogo CONDICIÓN DE COMBINACIÓN, en el que se propone una combinación interna entre LINFAC.ART y
ART.ART. Pulse ACEPTAR. Cierre el diálogo AGREGAR TABLA O VISTA.
—8—
Edmundo A. Cáceres — Práctica sobre consultas y Vistas — 2008
SQL puede fabricar salidas combinando dos tablas. Combinar es parecido a relacionar las tablas,
pero no igual. SQL no maneja relaciones. Las combinaciones consideran situaciones que las relaciones no tienen en cuenta.
Para combinar dos tablas, ambas deben tener algo común. En el ejemplo, lo común es el campo
ART, que está en ambas tablas. Lo común no es que se llamen igual, sino que tengan datos referidos a lo mismo. Si en una tabla el campo se llamara ART y en la otra se llamara ARTIC, la combinación también podría hacerse, porque ambos contienen códigos de artículo.
Al definir la combinación, se indica un campo de una tabla a la izquierda y un campo de otra tabla a
la derecha. Esto permite hablar de tabla izquierda y tabla derecha. Fíjese que izquierda y derecha
hacen referencia a cómo se definen las tablas en el diálogo CONDICIÓN DE COMBINACIÓN, no a como
se ven en el entorno. En este panel, los cursores se pueden arrastrar a cualquier lado, de modo
que hablar de tabla izquierda o derecha no tiene sentido, porque el arrastre puede poner la tabla
izquierda a la derecha, una tabla bajo la otra, etc.
Hay varios tipos de combinaciones. El tipo interna indica que SQL se va a preocupar por fabricar
una salida cada vez que un registro de la tabla izquierda coincida con otro de la tabla derecha por
el campo ART. Si un registro de la tabla izquierda no tiene un registro coincidente en la tabla derecha, se ignora. Sería el caso de un código de artículo vendido que fuera erróneo, porque no podríamos vender algo que no esté en la lista oficial de los artículos que comercializamos (tabla ART).
Simétricamente, si un registro de la tabla derecha no tiene un registro coincidente en la tabla izquierda, también se ignora. Sería el caso de un artículo de la lista oficial que no se hubiera vendido
nunca.
Sean las tablas LINFAC y ART, con registros hipotéticos. Los registros de una tabla sin coincidencia
en la otra aparecen oscurecidos.
Fac
1
1
2
2
2
3
3
Linfac
Art Can Pre
A05 5
10
A04 4
25
A09 4
15
A05 2
10
C01 5
50
A02 1
90
A06 2
45
Art
A01
A02
A03
A04
A05
A06
A07
Art
Nom
Camisa
Pantalón
Corbata
Pañuelo
Cinto
Zapatos
Medias
SQL producirá la salida siguiente:
Cursor de salida
Fac Art Can Pre
Nom
1 A05 5
10 Cinto
1 A04 4
25 Pañuelo
2 A05 2
10 Cinto
3 A02 1
90 Pantalón
3 A06 2
45 Zapatos
Observe que el registro de ART con código de artículo A05 aparece en las facturas 1 y 2 de LINFAC.
Esto significa que el registro de ART se combina con cada uno de los registros de LINFAC, produciendo dos registros en el cursor de salida.
Como no hemos ordenado la salida por código de artículo ni por nombre, es confuso. Mejor hubiera
sido ordenar por alguno de estos campos.
—9—
Edmundo A. Cáceres — Práctica sobre consultas y Vistas — 2008
4. Guarde y ejecute la consulta.
Ejercicio 10
Cree CON10 para calcular el importe total vendido de cada artículo. La salida debe ordenarse por nombre de artículo.
1. Cree una nueva consulta.
2. Agregue la tabla ART y luego la tabla LINFAC.
3. En el diálogo CONDICIÓN DE COMBINACIÓN, acepte la propuesta de combinar internamente ART.ART
con LINFAC.ART. Cierre el diálogo AGREGAR TABLA O VISTA.
A los efectos de lograr el propósito de la consulta, en este caso es indistinto cuál tabla estará a la
izquierda y cual a la derecha.
4. En la ficha CAMPOS agregue como campos seleccionados ART.ART, ART.NOM y la expresión
SUM(LINFAC.CAN * LINFAC.PRE) AS VENDIDO.
5. En agrupar por agregue ART.ART como campo agrupado.
6. En ORDENAR POR agregue ART.NOM como criterio de ordenación.
7. Guarde y ejecute la consulta.
Hemos agrupado por código de artículo y hemos ordenado la salida por nombre de artículo. ¿Podríamos haber agrupado por el nombre? En el caso del ejercicio sí, porque todos los nombres son
diferentes. Pero en la mayoría de los casos, como clientes, alumnos, socios, etc., es muy común
que dos o más clientes, alumnos, etc., tengan códigos distintos, pero se llamen igual. Por ejemplo,
sea que los clientes con código 15 y 49 se llamen Juan Carlos González. Si agrupáramos por nombre, daríamos un solo total para Juan Carlos González, lo cual sería un error. Lo correcto sería
agrupar por código de cliente, que es el identificador de cada uno y nunca se repite. Si el código de
cliente se repitiera, dejaría de ser identificador.
Con las tablas del ejemplo anterior, SQL ordenaría las tablas por ART, para poder agrupar:
Linfac
Fac Art Can Pre
3 A02 1
90
1 A04 4
25
1 A05 5
10
2 A05 2
10
3 A06 2
45
2 A09 4
15
2 C01 5
50
Art
A01
A02
A03
A04
A05
A06
A07
Art
Nom
Camisa
Pantalón
Corbata
Pañuelo
Cinto
Zapatos
Medias
Luego produciría la combinación siguiente:
Fac
3
1
1
2
3
Combinación
Art Can Pre
A02 1
90
A04 4
25
A05 5
10
A05 2
10
A06 2
45
Nom
Pantalón
Pañuelo
Cinto
Cinto
Zapatos
Posteriormente agruparía, produciendo lo siguiente, con los campos solicitados:
— 10 —
Edmundo A. Cáceres — Práctica sobre consultas y Vistas — 2008
Art
A02
A04
A05
A06
Nom
Vendido
Pantalón
90
Pañuelo
100
Cinto
70
Zapatos
90
Finalmente ordenaría por NOM y obtendría el cursor definitivo:
Art
A05
A02
A04
A06
Nom
Vendido
Cinto
70
Pantalón
90
Pañuelo
100
Zapatos
90
Ejercicio 11
Cree CON11 para calcular la cantidad de unidades totales vendidas de cada artículo. Ordene la salida
por nombre de artículo.
1. La consulta a crear es similar a CON10, de modo que créela a partir de ella y agréguela al proyecto.
2. Lo que varía con respecto a CON10 es que no debe calcular el importe total de ventas por artículo,
sino el total de unidades vendidas de cada uno. Elimine el campo seleccionado SUM(LINFAC.CAN *
LINFAC.PRE) AS VENDIDO, reemplazándolo por SUM(LINFAC.CAN) AS UNIDADES.
3. Ejecute y guarde la consulta.
Ejercicio 12
Cree CON12 para que muestre los campos FAC, FEC, CLI de ENCFAC y el total de cada factura.
1. Cree una nueva consulta. Agregue las tablas ENCFAC y LINFAC, combinándolas internamente por el
campo FAC.
2. Agregue como seleccionados los campos FAC, FEC y CLI. Agregue también la expresión
SUM(LINFAC.PRE * LINFAC.CAN) AS IMPORTE.
3. Agrupe por ENCFAC.FAC.
4. Guarde y ejecute la consulta.
Ejercicio 13
En una nueva consulta CON13, realice lo mismo que en CON12, pero agregando el nombre de cada
cliente, que debe tomar de la tabla CLI.
1. Cree CON13 a partir de CON12. Agregue CON12 al proyecto y modifíquela.
2. Agregue la tabla CLI. Acepte en principio la combinación interna ENCFAC.CLI con CLI.CLI. Veremos
que esto produce errores, porque cuando hay más de dos tablas en el panel de entorno, se debe
observar una regla.
3. Agregue CLI.NOM a campos seleccionados. Reubique los campos, para que el código de cliente
salga junto al nombre.
4. Guarde y ejecute la consulta.
Aunque el código de cliente varía, siempre aparece el mismo nombre de cliente. Obviamente hay
un error, debido a las combinaciones. Active la ficha COMBINACIÓN y verá lo siguiente:
— 11 —
Edmundo A. Cáceres — Práctica sobre consultas y Vistas — 2008
Tipo
Nombre de campo No Criterios
Valor
Lógico
Inner Join Encfac.fac
=
Linfac.fac
Inner Join Encfac.cli
=
Cli.cli
Hay dos líneas, una por combinación. Cada botón abre el diálogo CONDICIÓN DE COMBINACIÓN para la combinación correspondiente, permitiendo modificarla. En TIPO hay una lista desplegable para
cada combinación, para elegir su tipo, que se ofrecen en inglés: Inner Join quiere decir combinación interna. En NOMBRE DE CAMPO se define la tabla izquierda y su campo de combinación. En
CRITERIOS, en principio, debe definir el operador =, que es el ofrecido inicialmente. En VALOR se define la tabla derecha con su campo. NO niega el criterio, que por lo dicho, en principio no se usa,
pues negaría el =, dando distinto. LÓGICO sirve para elegir los operadores AND y OR, permitiendo
lograr combinaciones compuestas.
Cuando hay varias tablas, la que está a la derecha en una combinación debe estar a la izquierda
en la combinación siguiente. Esta regla no se ha observado y es lo que produce el error. El esquema de combinaciones, aplicando la regla, debe ser el siguiente:
Tipo
Nombre de campo No Criterios
Valor
Lógico
Inner Join Cli.cli
=
Encfac.cli
Inner Join Encfac.fac
=
Linfac.fac
Otra forma de combinar las tablas, también correcta, es:
Tipo
Nombre de campo No Criterios
Valor
Lógico
Inner Join Linfac.fac
=
Encfac.fac
Inner Join Encfac.cli
=
Cli.cli
Usemos el primer equema. Hay varias formas de corregir el error. Una es seleccionar cada línea de
combinación en el panel de entorno, pulsar la tecla SUPRIMIR y trazarla de nuevo, arrastrando del
campo de la tabla izquierda al campo de la tabla derecha. Recuerde que izquierda y derecha no se
refieren a cómo están dispuestos los cursores en el panel, sino a las tablas de partida y llegada,
respectivamente. Para no confundirse, puede mover los cursores para que visualmente queden a la
izquierda y derecha, de acuerdo al arrastre.
Otra forma es eliminar cada línea en la ficha COMBINACIÓN, ubicándose en ella y pulsando el botón
QUITAR. Posteriormente se puede construir cada combinación definiendo su tipo y las tablas y campos izquierdos y derechos.
Otra forma es pulsar el botón de cada combinación y tratar de modificarla en el diálogo
CONDICIÓN DE COMBINACIÓN. Esto no siempre es posible, porque como la condición ya está definida
y se la quiere editar, las posibilidades de tablas izquierdas son todas las que no estén como tabla
derecha, porque una tabla no se puede combinar consigo misma. Lo mismo sucede con la tabla
derecha. Pero si fuera posible usar este diálogo, quizás resulte que las combinaciones están correctas pero mal ubicadas, infringiendo la regla. Queda todavía el recurso de intercambiarlas, arrastrándolas hacia arriba o hacia abajo con el botón que aparece a la izquierda de cada combinación.
Use la primera o segunda formas para corregir el error y lograr el primer esquema.
5. Guarde y ejecute la consulta.
Ejercicio 14
Cree Con14 para que muestre el nombre de los clientes y el total comprado por cada uno. Ordene por
nombre.
1. Cree una nueva consulta. Agregue las tablas CLI, ENCFAC y LINFAC. Dado que las combinaciones
propuestas son correctas, acéptelas.
— 12 —
Edmundo A. Cáceres — Práctica sobre consultas y Vistas — 2008
2. Agregue como campo de salida CLI.NOM y SUM(LINFAC.CAN * LINFAC.PRE) AS COMPRADO.
3. Agrupe por CLI.CLI.
4. Ordene por CLI.NOM.
5. Guarde y ejecute la consulta.
Ejercicio 15
Cree CON15 para obtener lo comprado por cada cliente en cada factura. Se debe ordenar por nombre
de cliente y número de factura.
1. Cree una nueva consulta. Agregue las tablas CLI, ENCFAC y LINFAC. Acepte las combinaciones propuestas, porque son correctas.
2. Agregue como salida CLI.NOM, ENCFAC.FAC y SUM(LINFAC.CAN * LINFAC.PRE) AS COMPRADO.
3. Agrupe por CLI.CLI y ENCFAC.FAC.
4. Ordene por CLI.NOM y ENCFAC.FAC.
5. Guarde y ejecute la consulta.
Ejercicio 16
Cree CON16 para obtener el total de ventas en cada provincia. Ordene por nombre de provincia.
1. Cree una nueva consulta. Agregue las tablas PROV, CLI, ENCFAC y LINFAC. Las condiciones de
combinación pueden ser como indica cualquiera de los siguientes esquemas:
Prov.prv
= Cli.prv
Linfac.fac = Encfac.fac
Cli.cli
= Encfac.cli
Encfac.cli = Cli.cli
Encfac.fac = Linfac.fac
Cli.prv
= Prov.prv
¿Para qué usar cuatro tablas, si cuando la información a obtener proviene solamente de dos? Porque, para poder llegar de PROV a LINFAC, las tablas con la información necesitada, debemos usar
como "puentes" las tablas CLI y ENCFAC.
2. Agregue como salida PROV.NOM y SUM(LINFAC.PRE*LINFAC.CAN) AS VENTAS.
3. Agrupe por PROV.PRV. También podría agrupar por PROV.NOM, porque ningún nombre de provincia
se repite.
4. Ordene por PROV.NOM.
5. Ejecute y guarde la consulta.
Ejercicio 17
Cree CON17 para que calcule cuántas compras ha hecho cada cliente, sabiendo que cada factura es
una compra. Incluya el nombre del cliente y ordene la salida por este concepto.
1. Cree una nueva consulta. Agregue las tablas ENCFAC y CLI, combiándolas por el campo CLI.
2. Agregue como salida el campo CLI.NOM y la expresión COUNT(ENCFAC.FAC) AS FACTURAS.
La función COUNT( ) suma 1 por cada factura de cada cliente, obteniendo cuántas son.
3. Agrupe por CLI.CLI o por ENCFAC.CLI.
4. Ordene por CLI.NOM.
5. Guarde y ejecute la consulta.
— 13 —
Edmundo A. Cáceres — Práctica sobre consultas y Vistas — 2008
Ejercicio 18
Cree CON18 para saber cuánto ha vendido cada vendedor de cada artículo.
1. Cree una nueva consulta. Agregue las tablas VEN, ENCFAC, LINFAC y ART. Las combinaciones pueden ser cualquiera de los dos esquemas siguientes:
Ven.ven
= Encfac.ven
Encfac.fac = Linfac.fac
Linfac.art = Art.art
Art.art
= Linfac.art
Linfac.fac = Encfac.fac
Encfac.ven = Ven.ven
2. Agregue como campos de salida las expresiones VEN.NOM AS VENDEDOR, ART.NOM AS ARTÍCULO y
SUM(LINFAC.CAN*LINFAC.PRE) AS PRODUCCIÓN.
3. Dado que conviene no usar los nombres para agrupar, debe usar los campos VEN y ART. Tiene varias posibilidades:
Primer campo (arriba)
Ven.ven
Ven.ven
Encfac.ven
Encfac.ven
Linfac.art
Linfac.art
Art.art
Art.art
Segundo campo (abajo)
Linfac.art
Art.art
Linfac.art
Art.art
Ven.ven
Encfac.ven
Ven.ven
Encfac.ven
Cualquiera de las posibilidades anteriores es válida, porque se producirá un grupo por cada valor
diferente de ambos componentes. El orden final de los registros se hará por los nombres de vendedor y de artículo.
4. Ordene por nombre de vendedor y nombre de artículo.
5. Guarde y ejecute la consulta.
Ejercicio 19
Se quiere una consulta CON19 que calcule el total de ventas de cada vendedor a cada cliente. Debe
dar el nombre del vendedor, el nombre del cliente y el total.
El esquema de combinaciones desde un punto de vista lógica sería:
Ven.ven
= Encfac.ven
Encfac.fac = Linfac.fac
Encfac.cli = Cli.cli
Esquemáticamente, los cursores y combinaciones se verían así (se muestran los nombres de los cursores y de los campos de combinación):
Ven
Ven
Encfac
Fac
Ven
Cli
Linfac
Fac
Cli
Cli
Este entorno es dificultoso de establecer, porque habría que eliminar las combinaciones y volverlas a
trazar por arrastre. Lo que es peor, la consulta no funcionaría, debido a que no se cumple la regla: la
tabla derecha de la segunda combinación no es la tabla izquierda de la tercera.
El problema se soluciona si ENCFAC se agregar otra vez al entorno. Una tabla se puede agregar varias
veces, sin confundir a SQL, porque les da un alias diferente: la primera vez el alias será igual al nombre
— 14 —
Edmundo A. Cáceres — Práctica sobre consultas y Vistas — 2008
de la tabla, ENCFAC; pero en adelante el alias será ENCFAC_A, ENCFAC_B, etc. El esquema de combinación correcto, entonces, es:
Ven.ven
Encfac.fac
Linfac.fac
Encfac_a.cli
=
=
=
=
Encfac.ven
Linfac.fac
Encfac_a.fac
Cli.cli
Los cursores quedarán como las perlas de un collar, unidos por una cadena de combinaciones:
Ven
Ven
Encfac
Ven
Fac
Linfac
Encfac_a
Cli
Fac
Fac
Cli
Cli
La disposición generalizada del dibujo expresa la regla, que llamamos regla de la cadena.
La solución indicada funciona en este caso, porque la tercera combinación es 1 – 1: cada valor de factura en los registros de LINFAC tiene un solo registro correspondiente en ENCFAC_A. Si fuera una combinación 1 – N, SQL no la podría manejar adecuadamente y produciría resultados erróneos, por lo que
habría que buscar otra solución.
1. Cree una nueva consulta. Agregue las tablas y combinaciones del último esquema.
2. Seleccione como campos las expresiones VEN.NOM
LINFAC.PRE * LINFAC.CAN ) AS IMPORTE.
AS
VENDEDOR, CLI.NOM
AS
CLIENTE y SUM(
3. Agrupe por VEN.VEN y CLI.CLI o por CLI.CLI y VEN.VEN.
4. Elimine en la ficha CAMPOS los campos seleccionados VEN.VEN y CLI.CLI, para que no aparezcan en
el cursor de salida.
5. Ordene por VEN.NOM y CLI.NOM.
6. Guarde la consulta y ejecútela.
Ejercicio 20
Se quiere una consulta que calcule el total vendido de cada artículo, por cada vendedor, a cada cliente.
Un esquema de combinaciones, lógico pero complicado e ineficaz, sería:
Ven.ven
Encfac.fac
Linfac.fac
Art.art
Linfac_a.fac
Encfac_a.cli
=
=
=
=
=
=
Encfac.ven
Linfac.fac
Art.art
Linfac_a.art
Encfac_a.fac
Cli.cli
Este esquema produce resultados erróneos, porque se producen combinaciones 1 – N incorrectas.
Veamos dónde está el error.
Sea que el artículo A01 se ha vendido en las facturas 15 y 28, como único artículo en cada factura. La
factura 15 tiene vendedor 8 y cliente 14. La factura 28 tiene vendedor 55 y cliente 49. Esto queda más
claro en el siguiente cuadro:
Factura Vendedor Cliente Único
15
8
14
A01
28
55
49
A01
Cuando se procesa la factura 15 del vendedor 8 se producen las siguientes combinaciones:
— 15 —
Edmundo A. Cáceres — Práctica sobre consultas y Vistas — 2008
Ven
Ven
8
8
Encfac
Ven Fac
8
15
8
15
Linfac
Fac Art
15 A01
15 A01
Art
Art
A01
A01
Linfac_a
Art Fac
A01 15
A01 28
Encfac_a
Fac Cli
15 14
28 49
Cli
Cli
14
49
Al combinar ART con LINFAC_A, SQL combina el artículo A01 de ART con cada aparición de tal código
en LINFAC_A, olvidando que debe pertenecer al vendedor 8 y a la factura 15. Esto produce cálculos
erróneos, pues se atribuye a la factura 15 el importe de la factura 28.
Para solucionar este problema, conviene dividir el problema en dos consultas. La primera, que llamaremos CON20A, producirá una tabla de salida con los campos VEN.NOM, CLI.CLI, ART.NOM y
SUM(LINFAC.CAN * LINFAC.PRE) AS IMPORTE. La segunda, que llamaremos CON20B, tendrá como entrada
la tabla resultante de CON20A y la tabla CLI, dando como resultado los campos anteriores, pero reemplazanco CLI.CLI con CLI.NOM.
Cuando se presentan combinaciones similares a las explicadas, más que analizar las causas de error
conviene dividir el problema en dos o más consultas. Veremos más tarde que las vistas son más adecuadas que las consultas para estos casos.
Creemos primero la consulta CON20A.
1. Cree una consulta. Agregue las tablas VEN, ENCFAC, LINFAC y ART. Combínelas como indican las
tres primeras líneas del esquema anterior, es decir:
Ven.ven
= Encfac.ven
Encfac.fac = Linfac.fac
Linfac.fac = Art.art
2. Agregue como salida los campos VEN.NOM
SUM(LINFAC.CAN * LINFAC.PRE) AS IMPORTE.
AS
VENDEDOR, ENCFAC.CLI, ART.NOM
AS
ARTÍCULO y
3. Agrupe por VEN.VEN, ENCFAC.CLI y ART.ART.
4. Ejecute la consulta para ver los resultados en la ventana EXAMINAR.
5. En el menú CONSULTA, seleccione DESTINO DE LA CONSULTA.
6. En el diálogo DESTINO DE LA CONSULTA pulse el botón TABLA. Aparece el campo NOMBRE DE TABLA.
Escriba CON20A y pulse ACEPTAR.
7. Ejecute la consulta para generar la tabla CON20A y guarde la consulta como CON20A.
Por defecto, las consultas producen un cursor que se ve en la ventana EXAMINAR. Ese cursor tiene
un nombre que calcula SQL a partir del reloj del sistema, de modo que nunca obtiene dos nombres
iguales. Los cursores son similares a las tablas en estructura, pero no admiten índices y son destruidos automáticamente cuando se da cualquier comando que cierre las tablas abiertas o cuando
se sale de VFP. Tienen extensión TMP, abreviatura de temporal.
Puede suceder que el usuario necesite que la consulta no produzca ese cursor, sino que cree un
cursor o una tabla con los nombres que él les dé. Las consultas permiten tales salidas, definiendo
los destinos CURSOR y TABLA, que solicitan un nombre. Estos cursores o tablas no van a la ventana
EXAMINAR, pero quedan abiertos. Al darse un comando para cerrar las tablas, lo cursores, como se
ha dicho, desaparecen, pero las tablas quedan en disco.
La tabla que produce una ejecución de la consulta es generada nuevamente por otra ejecución, sin
que se advierta que ya existe.
Creemos finalmente la consulta CON20B.
1. Cree una consulta. Agregue las tablas CON20A y CLI. Combine por el campo CLI.
— 16 —
Edmundo A. Cáceres — Práctica sobre consultas y Vistas — 2008
2. Agregue como salida los campos CON20A.VENDEDOR,CLI.NOM
CON20A.IMPORTE.
AS
CLIENTE, CON20A.ARTÍCULO y
3. Ordene por VENDEDOR, CLIENTE y ARTÍCULO.
4. Guarde la consulta como CON20B y ejecútela.
Dividir el problema ha simplificado la tarea. Pero trabajar con una tabla generada por una consulta tiene
inconvenientes. Primero, para tener una versión actualizada de la tabla CON20A, debemos ejecutar la
consulta CON20A antes de ejecutar CON20B. Si olvidamos hacerlo, SQL buscará la tabla existente, lo
cual puede dar resultados desactualizados. Segundo, si eliminamos la tabla CON20A para ganar espacio, necesariamente deberemos ejecutar la consulta CON20A antes de CON20B, que usa esa tabla como
entrada.
Veremos más adelante que estos inconvenientes se evitan con las vistas.
Ejercicio 21
Hemos visto que las consultas son muy versátiles para combinar tablas y obtener gran variedad de resultados. Una pregunta que usted puede plantear es si los formularios y los informes pueden aprovechar el producto de las consultas. La respuesta es afirmativa. Para ilustrar someramente esta respuesta
vamos a desarrollar algunos ejemplos.
Vamos a crear un formulario que contenga un GRID cuyo RECORDSOURCE sea el cursor resultante de
una consulta. Los campos del Grid serán los campos del cursor, para lo cual debemos crear primero la
consulta. Esos campos serán código de cliente, número de factura y total general de factura. Primero
creemos la consulta.
1. Cree una consulta. Agregue las tablas ENCFAC y LINFAC, combinadas por el campo FAC.
2. Agregue como salida ENCFAC.CLI, ENCFAC.FAC y SUM(LINFAC.CAN * LINFAC.PRE) AS IMPORTE.
3. Agrupe por ENCFAC.CLI y ENCFAC.FAC.
4. Ejecute la consulta, para ver el resultado en le ventana EXAMINAR.
5. Elija CURSOR como destino de la consulta y llame CON21 a ese cursor.
6. Guarde la consulta como CON21.
7. Ejecute CON21. Ahora no aparece el resultado en la ventana EXAMINAR. El resultado se ha enviado
al cursor CON21, que debe todavía estar abierto.
8. Compruebe que el cursor está abierto: abra la ventana SESIÓN DE DATOS y observe que en el listado
ALIAS figura Con21. Seleccione el cursor y pulse CERRAR. Salga de SESIÓN DE DATOS con ESC.
Continuemos ahora con el formulario.
9. Cree un formulario.
10. Agregue un GRID. Configure las siguientes propiedades:
Objeto
Grid
Propiedad
RecordSourceType
RecorSource
ColumnCount
DeleteMark
ScrollBars
Width
Column1 ControlSource
Width
— 17 —
Valor
3 – Consulta (.QPR)
Con21
3
.F. – Falso
2 - Vertical
195
Cli
50
Edmundo A. Cáceres — Práctica sobre consultas y Vistas — 2008
Header Caption
Column2 ControlSource
Width
Header Caption
Column3 ControlSource
Width
Header Caption
Cliente
Fac
50
Factura
Importe
60
Importe
El valor 3 – CONSULTA (.QPR) de RECORDSOURCETYPE indica que se va a usar como entrada el resultado de una consulta. El nombre de ella se escribe en RECORDSOURCE. El valor CONTROLSOURCE
de cada columna es cada campo del cursor CON21 generado por la consulta. Oserve que los campos definidos en CONTROLSOURCE no están prefijados con el alias del cursor. Hemos observado
que, colocándoselo, a veces se producen resultados incorrectos.
11. Agregue un botón de comando, con CAPTION y NAME SALIR.
12. Pulse doble click en el botón SALIR y en el evento CLICK de ese objeto escriba:
close tables all
thisform.release
13. Guarde el formulario con el nombre CON21 y ejecútelo.
Hemos introducido el botón SALIR no sólo para que sea más fácil de pulsar que el botón de cierre
del formulario, sino para que cierre las tablas y cursores abiertos con el comando CLOSE TABLES ALL.
Aunque es innecesario cerrar el cursor CON21, lo hemos hecho para que compruebe, luego de ejecutar el formulario, que ya no aparece en la ventana SESIÓN DE DATOS.
Ejercicio 22
El sencillo formulario CON21 es poco práctico, porque el GRID no muestra el nombre de los clientes, sino los códigos. Por otro lado, el GRID muestra todos los códigos de cliente, y no uno en particular que
nos interese.
Sería preferible un formulario que presente en un LISTBOX, COMBOBOX o GRID los nombres de los clientes y sus códigos, en orden alfabético, tomándolos de la tabla CLI. Elegido un cliente específico, otro
GRID, mostraría todas sus facturas, con las fechas e importes. Podríamos usar una consulta para construir un cursor con los campos a mostrar en cada columna de este segundo GRID, más el campo CLI,
para filtrar el cliente a mostrar.
Creemos primero la consulta.
1. Cree una consulta. Agregue las tablas ENCFAC y LINFAC.
2. Agregue como salida ENCFAC.FAC, ENCFAC.FEC, SUM(LINFAC.CAN * LINFAC.PRE)
ENCFAC.CLI.
AS IMPORTE
y
3. Agrupe por ENCFAC.CLI y ENCFAC.FAC.
4. Ejecute la consulta para controlar los resultados en la ventana EXAMINAR.
5. Envíe el resultado de la consulta al cursor CON22.
6. Guarde la consulta como CON22.
Ahora creemos el formulario.
1. Cree un formulario, que se llamará CON22. Agréguele un LISTBOX, un GRID y un botón de comando.
2. En el entorno de datos agregue la tabla CLI. Establezca la propiedad ORDER al índice NOM.
3. Defina las siguientes propiedades:
— 18 —
Edmundo A. Cáceres — Práctica sobre consultas y Vistas — 2008
Objeto
ListBox
Propiedad
ColumnWidths
ColumnCount
RowSource
RowSourceType
Width
Grid
RecordSource
RecordSourceType
ColumnCount
DeleteMark
ScrollBars
Width
Column1
ControlSource
Width
Header
Caption
Column2
ControlSource
Width
Header
Caption
Column3
ControlSource
InputMask
Width
Header
Caption
CommandButton Caption
Name
Valor
150,0
2
Cli.Nom,Cli
6 - Campos
178
Con22
3 – Consulta (.QPR)
2
.F. - Falso
2 - Vertical
248
Fac
60
Factura
Fec
75
Fecha
Importe
999,999.99
80
Importe
Salir
Salir
Puede preguntarse por qué no definir las propiedades que subordinarían el GRID a la tabla CLI. El
problema radica en que no se puede definir la propiedad CHILDORDER, porque siendo el cursor
CON22 de lectura, no se puede crear un índice para él.
Debemos, en consecuencia, apelar a un filtro de registros sobre el cursor. Este filtro se aplicará cada vez que se elija un cliente en el LISTBOX, en el evento CLICK de este objeto.
4. En el evento CLICK del LISTBOX, escriba:
select con22
set filter to cli=cli.cli
go top
thisform.grid1.refresh
5. En el evento CLICK del botón SALIR, escriba:
close tables all
thisform.release
6. Ejecute el formulario. Guárdelo como CON22.
Ejercicio 23
Veamos otra forma de realizar lo mismo que hace CON22, pero sin definir el entorno de datos y usando
comandos para crear el cursor CON23 y abrir la tabla CLI.
1. Cree el formulario CON23 a partir del formulario CON22.
2. Abra el entorno de datos y elimine el cursor de la tabla CLI.
3. En el GRID, cambie el valor de la propiedad RECORDSOURCETYPE por 1 – ALIAS y el de la propiedad
RECORDSOURCE por CON23.
— 19 —
Edmundo A. Cáceres — Práctica sobre consultas y Vistas — 2008
4. En el evento LOAD del formulario, escriba:
close tables all
use cli in 0 order nom noupdate
En el menú VENTANA elija la ventana ADMINISTRADOR DE PROYECTOS – FAC. Seleccione la consulta
CON22 y pulse el botón MODIFICAR. En el DISEÑADOR DE CONSULTAS pulse el botón secundario y elija
VER SQL. Se abre la ventana CON22.QPR [SÓLO LECTURA], donde aparece el comando SELECT producido por lo definido en el diseñador. Seleccione todo el texto y cópielo. Cierre la ventana y el diseñador con ESC. Vuelva a la ventana CÓDIGO del evento LOAD del formulario. Al final del texto pegue el comando Select de SQL. Corrija la última línea, reemplazando CON22 por CON23. El texto
definitivo debe quedar como sigue:
close tables all
use cli in 0 order nom noupdate
SELECT Encfac.fac, Encfac.fec, SUM(Linfac.can*Linfac.pre) AS importe,;
Encfac.cli;
FROM fac!encfac INNER JOIN fac!linfac ;
ON Encfac.fac = Linfac.fac;
GROUP BY Encfac.cli, Encfac.fac;
INTO CURSOR con23
5. En el evento CLICK del LISTBOX, modifique la primera línea, cambiando CON22 por CON23.
6. Ejecute el formulario.
Hemos creado la consulta CON23 sin necesidad de usar el diseñador correspondiente. Esto se debe a que el diseñador de consultas produce en definitiva un comando SELECT de SQL, que es lo
esencial. El diseñador es un recurso intermedio que facilita la construcción de SELECT, pero SELECT
se puede escribir directamente. En este ejemplo, hemos copiado el SELECT correcto de la consulta
CON22, lo hemos pegado donde nos hace falta y lo hemos corregido ligeramente.
Ejercicio 24
El formulario CON23 muestra los importes comprados en cada factura del cliente elegido en el LISTBOX,
pero no el total general de esos importes. Este podría aparecer al pie del GRID, en un TEXTBOX. Para
calcularlo, podríamos duplicar el comando SELECT, con leves modificaciones. El primer SELECT sería
igual al original, cambiando el nombre del cursor a CON24A. El segundo SELECT produciría el cursor
CON24B, que debería agrupar solamente por cliente.
1. Cree CON24 a partir de CON23.
2. Corriga la propiedad RECORDSOURCE de GRID1 por CON24A.
3. Entre a la ventana CÓDIGO del evento LOAD del formulario, seleccione todo el comando SELECT, cópielo y péguelo al final. Corrija las líneas que se ven en negrita en el texto definitivo siguiente:
close tables all
use cli in 0 order nom noupdate
SELECT Encfac.fac, Encfac.fec, SUM(Linfac.pre*Linfac.can) AS importe,;
Encfac.cli;
FROM fac!encfac INNER JOIN fac!linfac ;
ON Encfac.fac = Linfac.fac;
GROUP BY Encfac.cli, Encfac.fac;
INTO CURSOR con24a
SELECT Encfac.cli, SUM(Linfac.pre*Linfac.can) AS general;
FROM fac!encfac INNER JOIN fac!linfac ;
ON Encfac.fac = Linfac.fac;
GROUP BY Encfac.cli;
INTO CURSOR con24b
4. Agregue un LABEL y un TEXTBOX al pie del GRID. Modifique las siguiente propiedades:
— 20 —
Edmundo A. Cáceres — Práctica sobre consultas y Vistas — 2008
Objeto
Label
Propiedad
Caption
AutoSize
InputMask
Width
TextBox ControlSource
Name
Valor
Total general
.T. – Verdadero
999,999,999.99
100
con24b.general
general
5. Modifique el evento CLICK del LISTBOX, para que quede como sigue:
select con24a
set filter to cli=cli.cli
go top
thisform.grid1.refresh
select con24b
set filter to cli=cli.cli
go top
thisform.general.refresh
6. Ejecute el formulario.
Vistas
Ejercicio 1
Cree la vista VIS1 para que produzca un cursor con solamente los artículos cuyo código de artículo
(campo ART) se indique al momento de la ejecución.
Este ejercicio es similar al Ejercicio 2 de Consultas. Cada vez que se examina, CON2 da salida a los artículos cuyo nombre comienza con C. Lo mismo se puede hacer en las vistas, pero para darles mayor
flexibilidad se las puede construir con parámetros. Los parámetros son cualquier nombre válido precedido por un signo ? que se usan para construir filtros sobre los registros de entrada y de salida. Se colocan en la columna EJEMPLO de la ficha FILTRO y del diálogo CONDICIONES. Cada vez que se examina
una vista que posee parámetros, antes de comenzar a trabajar, SQL pide un valor específico para cada
parámetro.
1. Ubíquese en la categoría VISTAS LOCALES y pulse el botón NUEVO. Esto abre el DISEÑADOR
VISTAS, que es muy parecido al diseñador de consultas, aunque hay algunas diferencias.
DE
2. Agregue la tabla ART. En la ficha CAMPOS agregue los campos ART.ART y ART.NOM.
3. Seleccione la ficha FILTRO. En NOMBRE DE CAMPO elija ART.ART. En CRITERIOS elija el operador = y
en EJEMPLO escriba ?INICIAL.
4. Guarde la consulta con CTRL + S, llamándola VIS1.
5. Examínela con EJECUTAR CONSULTA del menú secundario. Aparece el diálogo PARÁMETRO DE VISTA,
con el texto Escriba un valor para Inicial. En el campo en blanco escriba "C". Pulse ACEPTAR. Ahora
se abre la ventana EXAMINAR, con los registros cuyo nombre comienza con C. Salga con ESC.
6. Vuelva a examinar la vista, pero ahora escriba el valor A para el parámetro. El proceso se repite,
pero los registros mostrados comienzan ahora con A.
7. Salga del diseñador. VIS1 aparece registrada en la categoría VISTAS LOCALES.
A diferencia de las consultas, las vistas no se guardan en archivos por separado, sino en la base
de datos actual. Las consultas pueden agregarse a un proyecto. También pueden quitarse de él,
— 21 —
Edmundo A. Cáceres — Práctica sobre consultas y Vistas — 2008
permaneciendo como archivos independientes. Las vistas no pueden agregarse a una base de datos, sino crearse en ellas; si se quitan, se eliminan definitivamente.
Las vistas tienen como destino único un cursor que se ve en la ventana EXAMINAR. SQL crea el
nombre de este cursor desde el reloj de la computadora. A diferencia de las consultas, el cursor es
de lectura y escritura, es decir, permite modificar campos, agregar nuevos registros o marcarlos para destruir. Para probar esta propiedad, examine la vista otra vez.
De lo dicho en el párrafo anterior, surge inmediatamente la pregunta sobre el sentido de las altas,
bajas y cambios en un cursor que va a desaparecer al dar un comando que cierre tablas. La respuesta es que existe la posibilidad de mandar a las tablas de entrada las modificaciones hechas en
el cursor. Veremos este tema más adelante.
Al reconocer que INICIAL es un parámetro, porque va precedido por un signo de pregunta, SQL pide
el valor que le queremos dar en el diálogo PARÁMETRO DE VISTA. Para que nos indique cuál es el tipo de datos del parámetro, debemos hacer lo que dice el punto siguiente.
8. Para indicar el tipo de datos del parámetro, emita el comando CONSULTA – PARÁMETROS DE VISTA.
Esto abre el diálogo de igual nombre. En la columna NOMBRE escriba INICIAL. En la columna TIPO
seleccione CARÁCTER.
9. Examine la vista.
Ahora el diálogo PARÁMETRO DE VISTA es más específico, pues dice Escriba un valor de tipo carácter
para Inicial. Esta especificación es más útil, porque nos orienta sobre si debemos introducir números, caracteres, fechas, etc. Cuando una vista usa muchos parámetros, habrá uno de estos diálogos para cada uno, donde la aclaración del tipo de datos facilita la tarea.
10. Guarde los cambios.
Note que, al estar activo el diseñador de vistas, no aparece ningún menú VISTA, sino el ya conocido
CONSULTA. Del mismo modo, para producir la vista, no hay una opción EJECUTAR VISTA, sino la ya
conocida EJECUTAR CONSULTA.
Ejercicio 2
Cree la vista VIS2 para que muestre las facturas de un vendedor y un cliente parametrizados. Trabaje
solamente con la tabla ENCFAC. Ordene la salida por factura.
1. Cree una vista. Agregue la tabla ENCFAC y todos sus campos.
2. En la ficha FILTRO, escriba los filtros siguientes:
Encfac.ven
Encfac.cli
=
?Vendedor
=
?Cliente
3. En CONSULTA – PARÁMETROS DE VISTA especifique que VENDEDOR y CLIENTE son numéricos.
4. En ORDENAR POR seleccione el campo ENCFAC.FAC.
5. Guarde y examine la vista. Aparecen dos diálogos PARÁMETRO DE VISTA, uno por parámetro.
6. En el diseñador, con el botón secundario pulse VER SQL. Aunque usted no lo ha definido, el operador que une ambos filtros es AND, por ser el operador por defecto. Ello se ve en la cláusula WHERE
del comando SELECT, donde dice:
Ejercicio 3
WHERE Encfac.cli = ?Cliente;
AND Encfac.ven = ?Vendedor
Cree la vista VIS3, similar a VIS2, pero que agregue el importe total vendido por el vendedor al cliente.
Trabaje solamente con las tablas ENCFAC y LINFAC. Ordene la salida por factura.
— 22 —
Edmundo A. Cáceres — Práctica sobre consultas y Vistas — 2008
1. Cree VIS2 a partir de VIS1.
2. Agregue la tabla LINFAC, combinándola con ENCFAC por el campo FAC.
3. Agregue SUM(LINFAC.CAN * LINFAC.PRE) AS TOTAL como campo de salida.
4. Guarde y examine la vista.
Note que no ha hecho falta agrupar por vendedor y cliente, porque los filtros han reducido el universo
de registros a los de un solo vendedor y un solo cliente.
Ejercicio 4
Cree la vista VIS4 que muestre los campos ART, NOM y PRE de la tabla ART y permita actualizar indirectamente el campo PRE de tal tabla. Con indirectamente queremos decir que, si cambiamos el campo
PRE del cursor de salida, ese cambio modifique el valor PRE de la tabla ART. ¿En qué registro de la tabla ART se producirá ese cambio indirecto? Pues exactamente en el registro que origina el registro que
modificamos en el cursor de salida.
Primero, vamos a corregir el campo PRE de la tabla ART, exigiendo mediante la regla de validación que
no pueda ser nulo ni negativo. Si esto sucede, queremos que VFP dé el mensaje "Precio debe contener
un valor positivo". Esta modificación la introducimos para explicar una característica de las vistas.
1. En el ADMINISTRADOR DE PROYECTOS elija la tabla ART y pulse el botón MODIFICAR.
2. En la ficha CAMPOS del DISEÑADOR DE TABLAS elija el campo PRE.
3. En REGLA de validación escriba la expresión PRE > 0.
4. En MENSAJE de validación escriba "PRECIO DEBE CONTENER UN VALOR POSITIVO".
5. Pulse ACEPTAR.
6. Examine la tabla ART. Ubíquese en algún campo PRE y escriba 0. Al tratar de salir del campo, aparecerá el mensaje de error. Pulse el botón VOLVER, para reponer el valor anterior. Este experimento
ha servido para ver cómo funciona una regla de validación de campo.
Ahora cree la vista VIS4.
1. Agregue la tabla ART al panel de entorno.
2. Agregue todos los campos a CAMPOS SELECCIONADOS.
3. Seleccione PRE en CAMPOS SELECCIONADOS y pulse el botón PROPIEDADES. Esto abre el diálogo
PROPIEDADES DEL CAMPO DE LA VISTA.
Dado que queremos que el campo PRE pueda ser modificado en el cursor de salida, mandando el
nuevo valor a la tabla ART, podría suceder que en el cursor reemplacemos un precio por un valor
nulo o negativo. Pero el cursor funcionaría incorrectamente si aceptara esto, ya que estaría en
desacuerdo con la tabla. Lo correcto sería que el cursor tuviera una regla y un mensaje de validación del campo PRE, similares a los que tiene el campo PRE de la tabla ART.
Para eso, precisamente, sirve el diálogo PROPIEDADES DEL CAMPO DE LA VISTA. Funcionalmente es
exactamente igual a las posibilidades que se ven en la ficha CAMPOS de una tabla base, debajo de
las definiciones de campos, tipos, anchos, etc. En el DISEÑADOR DE TABLAS elegimos el campo en la
columna NOMBRE. Como en el diálogo PROPIEDADES DEL CAMPO DE LA VISTA no aparece esa columna, la forma de elegirlo es abriendo la lista desplegable CAMPO y seleccionando el deseado.
4. Abra la lista CAMPO y elija ART.PRE.
5. En REGLA escriba PRE > 0.
6. En MENSAJE escriba "PRECIO DEBE CONTENER UN VALOR POSITIVO".
— 23 —
Edmundo A. Cáceres — Práctica sobre consultas y Vistas — 2008
Ahora entenderá para qué modificamos inicialmente la tabla ART, introduciendo una regla y un
mensaje de validación para el campo PRE. No sería congruente que, en la tabla, el campo PRE estuviera sujeto a una regla de validación y una vista permitiera modificar indirectamente su contenido sin observar tal regla.
Como los cursores de salida permiten modificar cualquier campo, nos queda definir que sólo las
modificaciones del campo PRE del cursor se envíen al campo PRE de la tabla ART.
7. Seleccione la ficha CRITERIOS DE ACTUALIZACIÓN del DISEÑADOR DE VISTAS.
En la lista desplegable TABLA aparece ART. Esta lista muestra las tablas del panel de entorno. En
este ejercicio, sólo trabajamos con la tabla ART, por lo que no aparece ninguna otra.
El cuadro central está dividido en tres columnas, una encabezada por un ícono
, otra por un íco-
no
y la última llamada NOMBRE DEL CAMPO. En esta última columna se ven los campos del cursor, uno por línea.
La columna Llave muestra una tilde en la línea de ART. Esto indica que este campo se va a usar
como clave para buscar en la tabla de entrada ART el registro cuyo campo PRE debe ser modificado
con el valor modificado en el campo PRE del cursor. Que sea clave quiere decir que identifique el
registro a modificar de modo inequívoco.
El campo ART es precisamente el campo clave de la tabla ART, que nos ha permitido construir el
índice principal de esa tabla. Nótese que, sin hacer nosotros nada, este campo apareció con tilde
en la columna Llave. Esto se debe a que hay un índice principal por él. Si en lugar de principal fuera un índice candidato, VFP no supone que es clave. Esta es una diferencia de funcionamiento entre índices principales e índices candidatos.
La columna Lápiz muestra una tilde en la línea de NOM y otra en la línea de PRE. Esto indica que
las modificaciones en los valos de estos campos se van a enviar a la tabla. En principio, SQL supone que todos los campos, excepto los campos clave, van a ser de este tipo. En nuestro caso,
como sólo queremos que esto suceda con el campo PRE, deberemos destildar el campo NOM.
Nótese que la línea de ART no tiene tilde en la columna Lápiz. Esto se debe a una actitud prudente
de SQL. Aunque los cambios de clave se pueden enviar a la tabla, esto puede traer varios problemas que necesitan ser tratados adecuadamente. Como es un tema complejo, nos limitamos a recomendar seguir con la prudencia de SQL, es decir, nunca hacer actualizables los campos clave.
Si por equivocación destildamos campos clave y no recordamos cuáles son, podemos recurrir al
botón RESTABLECER CLAVES, que vuelve a marcarlos, teniendo en cuenta que forman la expresión
de índices principales.
Si destildamos campos actualizables y queremos volver a marcarlos todos, el botón ACTUALIZAR
TODOS realiza esta tarea.
El hecho de marcar algunos o todos los campos como actualizables no los hace inmediatamente
tales, sino que es necesario poner en vigencia esta modalidad. Para ello se usa la casilla de verificación ENVIAR ACTUALIZACIONES (SQL).
La porción derecha de la ficha CRITERIOS DE ACTUALIZACIÓN, que incluye los rubros LA CLÁUSULA
SQL WHERE INCLUYE y ACTUALIZAR USANDO no nos interesan, por referirse principalmente a vistas
remotas.
8. Controle que tenga tilde la columna Llave en el campo ART y la columna LÁPIZ solamente en el
campo PRE.
9. Active la casilla ENVIAR ACTUALIZACIONES (SQL).
— 24 —
Edmundo A. Cáceres — Práctica sobre consultas y Vistas — 2008
10. Guarde y examine la vista.
Tome nota de algunos códigos de artículo y modifique el precio. Cierre la vista. Examine la tabla
ART y compruebe que los precios que modificó en el cursor de salida han cambiado también en la
tabla.
Si quiere comprobar el efecto de ENVIAR ACTUALIZACIONES (SQL), modifique la vista VIS4 desactivando esta casilla. Si examina nuevamente la vista y cambia otros precios, cuando salga de ella y
examine la tabla, verá que tales cambios no la han modificado.
Ejercicio 5
Veamos cómo realizar una vista que realice lo mismo que la consulta del Ejercicio 20. Éste calcula el
total vendido de cada artículo, por cada vendedor, a cada cliente. Para lograr este propósito, diseñamos dos consultas, CON20A y CON20B, que creaban una tabla "inevitable", CON20A. Trabajando con
vistas esa tabla es innecesaria. Por otro lado sería imposible de crearla, porque las vistas tienen como
único destino un cursor de nombre no controlable que se ve en la ventana EXAMINAR.
Cree primero la vista VIS5A.
1. Agregue las tablas VEN, ENCFAC, LINFAC y ART. Combínelas como indica este esquema:
Ven.ven
= Encfac.ven
Encfac.fac = Linfac.fac
Linfac.fac = Art.art
2. Agregue como salida los campos VEN.NOM
SUM(LINFAC.CAN * LINFAC.PRE) AS IMPORTE.
AS
VENDEDOR, CLI.CLI, ART.NOM
AS
ARTÍCULO y
3. Agrupe por VEN.VEN, ENCFAC.CLI y ART.ART. Elimine estos campos de CAMPOS SELECCIONADOS de la
ficha CAMPOS.
4. Examine la vista para ver los resultados en la ventana EXAMINAR.
Cree ahora cree la vista VIS5B.
1. Agregue la vista VIS5A y la tabla CLI. Combine por el campo CLI.
2. Agregue como salida los campos VIS5A.VENDEDOR,CLI.NOM
VIS5A.IMPORTE.
AS
CLIENTE, VIS5A.ARTÍCULO y
3. Ordene por VENDEDOR, CLIENTE y ARTÍCULO.
4. Examine la vista.
Cuando una vista 2 incluye en el panel de entorno otra vista 1, SQL debe ejecutar la vista 1 previamente a ejecutar la vista 2, puesto que una de sus entradas es precisamente el cursor resultante
de la vista 1. Esta inclusión de una vista dentro de otra puede repetirse varias veces.
La inclusión de vistas permite ir obteniendo cursores de salida que quedan abiertos (recuerde que
se eliminan si se emite un comando para cerrar las tablas abiertas, comandos que en la ejecución
sucesiva no se utilizan). Si una vista 1 produce un cursor 1, éste queda abierto y puede ser tomado
como entrada para una vista 2; si ésta produce como salida un cursor 2, puede tomarse como entrada para una vista 3, y así sucesivamente.
Técnicamente, una vista es un comando Select de SQL. En el caso de una vista que incluye otra
vista, es en realidad un comando Select que incluye otro comando Select.
El empleo inmediato de un cursor generado por una vista como entrada de otra vista evita generar
tablas y preocuparse por eliminarlas.
— 25 —
Edmundo A. Cáceres — Práctica sobre consultas y Vistas — 2008
Ejercicio 6
Creemos un formulario similar a una factura impresa en papel. Queremos elegir en un COMBOBOX la
factura a desplegar. Cuando se haga esto, se verá la fecha, el nombre del cliente y el total de la factura
en respectivos TEXTBOXES. El detalle de cada artículo vendido, incluyendo código, nombre, cantidad,
precio e importe parcial, se verán en un GRID.
Las opciones del ComboBox se construirán a partir de una vista, que contendrá los campos factura, fecha, cliente e importe total de la factura.
El aspecto del formulario será como el siguiente:
Creemos la vista VIS6 con los campos indicados. Esta vista no puede ser la hija de una relación temporal , porque necesitaría un índice que no sabemos generar. Pero sí puede ser la madre de una relación
temporal, porque una relación temporal necesita uno o más campos de la tabla madre y un índice en la
tabla hija. Las tablas hijas van a ser CLI, para obtener el nombre del cliente, y LINFAC, para obtener las
líneas componentes de la factura. Cuando elijamos una factura en el COMBOBOX, podremos "refrescar"
directamente los campos fecha e importe total, porque serán parte del mismo registro del cursor producido por la vista, e indirectamente el nombre del cliente y el GRID, por relaciones temporales con las tablas CLI y LINFAC. Notemos que, para obtener la descripción de los artículos, deberemos trazar una relación temporal de LINFAC a ART, relación que se materializará en cada registro del Grid y que no interviene en la subordinación de CLI y LINFAC a VIS6.
1. Cree la nueva vista agregando las tablas ENCFAC y LINFAC al panel de entorno, combinándolas por
el campo común FAC.
2. Seleccione los campos FAC, FEC, CLI y SUM(LINFAC.CAN * LINFAC.PRE) AS IMPTOT.
— 26 —
Edmundo A. Cáceres — Práctica sobre consultas y Vistas — 2008
3. Agrupe por ENCFAC.FAC (o por LINFAC.FAC).
4. Guarde la vista como Vis6 y ejecútela para controlar que todo va bien.
Cree ahora el formulario.
1. Agregue los objetos que muestra el gráfico anterior.
2. Defina las siguientes propiedades:
Objeto
Form1
Label1
ComboBox
Label2
TextBox1
Label3
TextBox2
Grid1
Column1
Header1
Column2
Header1
Column3
Header1
Column4
Header1
Column5
Label4
Propiedad
Caption
Caption
AutoSize
RowSource
RowSourceType
ColumnCount
ColumnWidths
Caption
AutoSize
ControlSource
Name
Caption
AutoSize
ControlSource
Name
Width
RecordSource
ColumnCount
DeleteMark
ScrollBars
Name
ControlSource
Width
Alignment
Caption
ControlSource
Width
Alignment
Caption
ControlSource
Width
Alignment
Caption
ControlSource
Alignment
Caption
ControlSource
Alignment
Caption
AutoSize
Caption
— 27 —
Valor
Despliegue de facturas
Factura
.T. – Verdadero
Vis6.Fac
6 – Campos
1
75
Fecha
.T. – Verdadero
Vis6.Fec
Fecha
Cliente
.T. – Verdadero
Cli.Nom
Cliente
200
Linfac
5
.F.
2- Vertical
Linfac
Linfac.Art
30
2 – Medio centro
Art
Art.Nom
200
2 – Medio centro
Descripción
Linfac.Can
60
2 – Medio centro
Cantidad
Linfac.Pre
2 – Medio centro
Precio
linfac.can*linfac.pre
2 – Medio centro
Importe
.T. – Verdadero
Total
Edmundo A. Cáceres — Práctica sobre consultas y Vistas — 2008
TextBox3
ControlSource
InputMask
Name
CommandButton1 Autosize
Caption
Name
Vis6.Imptot
999,999.99
Imptot
.T. – Verdadero
Salir
Salir
3. En el entorno de datos agregue la vista Vis6 y las tablas Cli, Linfac y Art.
4. Trace las siguientes relaciones:
Tabla madre
Vis6
Vis6
Linfac
Campo
Fac
Cli
Art
Tabla hija
Linfac
Cli
Art
5. En el evento CLICK del COMBOBOX, escriba:
thisform.fecha.refresh
thisform.cliente.refresh
thisform.imptot.refresh
6. En el evento Click del CommandButton, escriba:
thisform.release
7. Guarde el formulario como Vis6 y ejecútelo.
— 28 —
Índice
Fac
Cli
Art
Descargar