7.3 Consultas a la base de datos.
 

La sintaxis básica de una consulta de selección es la siguiente:

SELECT Campos
FROM Tabla

En donde campos es la lista de campos que se deseen recuperar y tabla es el origen de los mismos, por ejemplo:

SELECT Nombre, Teléfono
FROM Clientes

Esta sentencia devuelve un conjunto de resultados con el campo nombre y teléfono de la tabla clientes.

Devolver Literales

En determinadas ocasiones nos puede interesar incluir una columna con un texto fijo en una consulta de selección, por ejemplo, supongamos que tenemos una tabla de empleados y deseamos recuperar las tarifas semanales de los electricistas, podríamos realizar la siguiente consulta:

SELECT
Empleados.Nombre, 'Tarifa semanal: ', Empleados.TarifaHora * 40
FROM Empleados
WHERE Empleados.Cargo = 'Electricista'

Ordenar los registros

Adicionalmente se puede especificar el orden en que se desean recuperar los registros de las tablas mediante la cláusula ORDER BY Lista de Campos. En donde Lista de campos representa los campos a ordenar.

Ejemplo:

SELECT CodigoPostal, Nombre, Telefono
FROM Clientes
ORDER BY Nombre

Esta consulta devuelve los campos CodigoPostal, Nombre, Telefono de la tabla Clientes ordenados por el campo Nombre.
Se pueden ordenar los registros por mas de un campo, como por ejemplo:

SELECT CodigoPostal, Nombre, Telefono
FROM Clientes
ORDER BY CodigoPostal, Nombre

Incluso se puede especificar el orden de los registros: ascendente mediante la cláusula (ASC - se toma este valor por defecto) ó descendente (DESC)

SELECT CodigoPostal, Nombre, Telefono
FROM Clientes
ORDER BY CodigoPostal DESC , Nombre ASC

Uso de Indices de las tablas

Si deseamos que la sentecia SQL utilice un índice para mostrar los resultados se puede utilizar la palabra reservada INDEX de la siguiente forma:

SELECT ... FROM Tabla (INDEX=Indice) ...

Normalmente los motores de las bases de datos deciden que indice se debe utilizar para la consulta, para ello utilizan criterios de rendimiento y sobre todo los campos de búsqueda especificados en la cláusula WHERE. Si se desea forzar a no utilizar ningún índice utilizaremos la siguiente sintaxis:
SELECT ... FROM Tabla (INDEX=0) ..
.
Consultas con Predicado

El predicado se incluye entre la cláusula y el primer nombre del campo a recuperar, los posibles predicados son:

Predicado Descripción
ALL Devuelve todos los campos de la tabla
DISTINCT Omite los registros cuyos campos seleccionados coincidan totalmente.

 

ALL

Si no se incluye ninguno de los predicados se asume ALL. El Motor de base de datos selecciona todos los registros que cumplen las condiciones de la instrucción SQL y devuelve todos y cada uno de sus campos. No es conveniente abusar de este predicado ya que obligamos al motor de la base de datos a analizar la estructura de la tabla para averiguar los campos que contiene, es mucho más rápido indicar el listado de campos deseados.

SELECT ALL
FROM Empleados

SELECT * FROM
Empleados

DISTINCT

Omite los registros que contienen datos duplicados en los campos seleccionados. Para que los valores de cada campo listado en la instrucción SELECT se incluyan en la consulta deben ser únicos. Por ejemplo, varios empleados listados en la tabla Empleados pueden tener el mismo apellido. Si dos registros contienen López en el campo Apellido, la siguiente instrucción SQL devuelve un único registro:

SELECT DISTINCT Apellido
FROM Empleados

Con otras palabras el predicado DISTINCT devuelve aquellos registros cuyos campos indicados en la cláusula SELECT posean un contenido diferente. El resultado de una consulta que utiliza DISTINCT no es actualizable y no refleja los cambios subsiguientes realizados por otros usuarios.

ALIAS

En determinadas circunstancias es necesario asignar un nombre a alguna columna determinada de un conjunto devuelto, otras veces por simple capricho o porque estamos recuperando datos de diferentes tablas y resultan tener un campo con igual nombre. Para resolver todas ellas tenemos la palabra reservada AS que se encarga de asignar el nombre que deseamos a la columna deseada. Tomado como referencia el ejemplo anterior podemos hacer que la columna devuelta por la consulta, en lugar de llamarse apellido (igual que el campo devuelto) se llame Empleado. En este caso procederíamos de la siguiente forma:

SELECT DISTINCT Apellido AS Empleado
FROM Empleados

AS no es una palabra reservada de ANSI, existen diferentes sistemas de asignar los alias en función del motor de bases de datos. En ORACLE para asignar un alias a un campo hay que hacerlo de la siguiente forma:

SELECT Apellido AS "Empleado"
FROM Empleados

También podemos asignar alias a las tablas dentro de la consulta de selección, en esta caso hay que tener en cuenta que en todas las referencias que deseemos hacer a dicha tabla se ha de utilizar el alias en lugar del nombre. Esta técnica será de gran utilidad más adelante cuando se estudien las vinculaciones entre tablas.
Por ejemplo:

SELECT Apellido AS Empleado
FROM Empleados AS Trabajadores

Para asignar alias a las tablas en ORACLE y SQL-SERVER los alias se asignan escribiendo el nombre de la tabla, dejando un espacio en blanco y escribiendo el Alias (se asignan dentro de la cláusula FROM).

SELECT Trabajadores.Apellido (1) AS Empleado
FROM Empleados Trabajadores

(1)Esta nomenclatura [Tabla].[Campo] se debe utilizar cuando se está recuperando un campo cuyo nombre se repite en varias de las tablas que se utilizan en la sentencia. No obstante cuando en la sentencia se emplean varias tablas es aconsejable utilizar esta nomenclatura para evitar el trabajo que supone al motor de datos averiguar en que tabla está cada uno de los campos indicados en la cláusua SELECT.


Gestión y elección de los índices

Los índices son campos elegidos arbitrariamente por el constructor de la base de datos que permiten la búsqueda a partir de dicho campo a una velocidad notablemente superior. Sin embargo, esta ventaja se ve contrarrestada por el hecho de ocupar mucha más memoria (el doble más o menos) y de requerir para su inserción y actualización un tiempo de proceso superior.

Evidentemente, no podemos indexar todos los campos de una tabla extensa ya que doblamos el tamaño de la base de datos. Igualmente, tampoco sirve de mucho el indexar todos los campos en una tabla pequeña ya que las selecciones pueden efectuarse rápidamente de todos modos.

Un caso en el que los índices pueden resultar muy útiles es cuando realizamos peticiones simultáneas sobre varias tablas. En este caso, el proceso de selección puede acelerarse sensiblemente si indexamos los campos que sirven de nexo entre las dos tablas.

Los índices pueden resultar contraproducentes si los introducimos sobre campos triviales a partir de los cuales no se realiza ningún tipo de petición ya que, además del problema de memoria ya mencionado, estamos ralentizando otras tareas de la base de datos como son la edición, inserción y borrado. Es por ello que vale la pena pensarselo dos veces antes de indexar un campo que no sirve de criterio para búsquedas o que es usado con muy poca frecuencia por razones de mantenimiento.
Campos a Seleccionar.

  • En la medida de lo posible hay que evitar que las sentencias SQL estén embebidas dentro del código de la aplicación. Es mucho más eficaz usar vistas o procedimientos almacenados por que el gestor los guarda compilados. Si se trata de una sentencia embebida el gestor debe compilarla antes de ejecutarla.
  • Seleccionar exclusivamente aquellos que se necesiten
  • No utilizar nunca SELECT * por que el gestor debe leer primero la estructura de la tabla antes de ejecutar la sentencia
  • Si utilizas varias tablas en la consulta especifica siempre a que tabla pertenece cada campo, le ahorras al gestor el tiempo de localizar a que tabla pertenece el campo. En lugar de SELECT Nombre, Factura FROM Clientes, Facturacion WHERE IdCliente = IdClienteFacturado, usa: SELECT Clientes.Nombre, Facturacion.Factura WHERE Clientes.IdCliente = Facturacion.IdClienteFacturado.
    Campos de Filtro
  • Se procurará elegir en la cláusula WHERE aquellos campos que formen parte de la clave del archivo por el cual interrogamos. Además se especificarán en el mismo orden en el que estén definidos en la clave.
  • Interrogar siempre por campos que sean clave.
  • Si deseamos interrogar por campos pertenecientes a indices compuestos es mejor utilizar todos los campos de todos los indices. Supongamos que tenemos un índice formado por el campo NOMBRE y el campo APELLIDO y otro índice formado por el campo EDAD. La sentencia WHERE NOMBRE='Juan' AND APELLIDO Like '%' AND EDAD = 20 sería más optima que WHERE NOMBRE = 'Juan' AND EDAD = 20 por que el gestor, en este segundo caso, no puede usar el primer índice y ambas sentencias son equivalentes por que la condición APELLIDO Like '%' devolvería todos los registros.

Creación de Índices.
Si se utiliza el motor de datos Jet de Microsoft sólo se pueden crear índices en bases de datos del mismo motor. La sintaxis para crear un índice en ua tabla ya definida en la siguiente:

CREATE [ UNIQUE ] INDEX índice
ON Tabla (campo [ASC|DESC][, campo [ASC|DESC], ...])

Donde:

índice Es el nombre del índice a crear.
tabla Es el nombre de una tabla existente en la que se creará el índice.
campo Es el nombre del campo o lista de campos que constituyen el índice.
ASC|DESC Indica el orden de los valores de los campos ASC indica un orden ascendente (valor predeterminado) y DESC un orden descendente.

UNIQUE
Indica que el índice no puede contener valores duplicados.

CREATE INDEX
MiIndice
ON
Empleados (nombre, Telefono)
(Crea un índice llamado MiIndice en la tabla empleados con los campos nombre y Teléfono.)

CREATE UNIQUE INDEX
MiIndice
ON Empleados (IdEmpleado) (Crea un índice en la tabla Empleados utilizando el campo IdEmpleado,

Operadores Lógicos

Los operadores lógicos soportados por SQL son: AND, OR y Not. A excepción de los dos últimos todos poseen la siguiente sintaxis:
<expresión1> operador <expresión2>

En donde expresión1 y expresión2 son las condiciones a evaluar, el resultado de la operación varía en función del operador lógico. La tabla adjunta muestra los diferentes posibles resultados:

Si a cualquiera de las anteriores condiciones le anteponemos el operador NOT el resultado de la operación será el contrario al devuelto sin el operador NOT.
El último operador denominado Is se emplea para comparar dos variables de tipo objeto <Objeto1> Is <Objeto2>. este operador devuelve verdad si los dos objetos son iguales.

SELECT * FROM Empleados
WHERE Edad > 25 AND Edad < 50

SELECT * FROM Empleados
WHERE (Edad > 25 AND Edad < 50) OR Sueldo = 100

SELECT * FROM Empleados
WHERE NOT Estado = 'Soltero'

SELECT * FROM Empleados
WHERE (Sueldo > 100 AND Sueldo < 500) OR
(Ciudad = 'Mexico' AND Estado = 'Casado')
Valores Nulos
En muchas ocasiones es necesario emplear como criterio de seleccion valores nulos en los campos. Podemos emplear el operacion IS NULL para realizar esta operación. Por ejemplo:

SELECT * FROM
Empleados WHERE DNI IS NULL
Intervalos de Valores
Para indicar que deseamos recuperar los registros según el intervalo de valores de un campo emplearemos el operador Between cuya sintaxis es:
campo [Not] Between valor1 And valor2 (la condición Not es opcional)
En este caso la consulta devolvería los registros que contengan en "campo" un valor incluido en el intervalo valor1, valor2 (ambos inclusive). Si anteponemos la condición Not devolverá aquellos valores no incluidos en el intervalo.

SELECT * FROM Pedidos
WHERE CodPostal Between 28000 And 28999

El Operador In

Este operador devuelve aquellos registros cuyo campo indicado coincide con alguno de los en una lista. Su sintaxis es:
expresión [Not] In(valor1, valor2, . . .)

SELECT * FROM Pedidos
WHERE Ciudad In ('Mexico', 'Monterrey', 'Sevilla')

La cláusula WHERE

La cláusula WHERE puede usarse para determinar qué registros de las tablas enumeradas en la cláusula FROM aparecerán en los resultados de la instrucción SELECT. Después de escribir esta cláusula se deben especificar las condiciones expuestas en los apartados anteriores. Si no se emplea esta cláusula, la consulta devolverá todas las filas de la tabla. WHERE es opcional, pero cuando aparece debe ir a continuación de FROM.

SELECT Apellidos, Salario
FROM Empleados
WHERE Salario = 21000

SELECT IdProducto, Existencias
FROM Productos
WHERE Existencias <= NuevoPedido

SELECT Apellidos, Nombre
FROM Empleados
WHERE Apellidos = 'King'

SELECT Apellidos, Nombre
FROM Empleados
WHERE Apellidos Like 'S*'

SELECT Apellidos, Salario
FROM Empleados
WHERE Salario Between 200 And 300


Cláusula ORDER BY
Esta cláusula se utiliza en un comando SELECT para producir como resultado una relación en un orden específico. En general, la relación resultado no se garantiza que esté en un orden particular. De ahí que la cláusula ORDER BY se utilice para ordenar el resultado en alguna secuencia particular antes de que los datos sean desplegados.

AL igual que la cláusula ORDER del comando CREATE INDEX el argumento puede ser ya sea ASC o DESC. ASC es el valor por defecto.

También es posible identificar columnas por su número de columna en lugar de su nombre, esto es, por la posición ordinal (de izquierda a derecha) de la columna en cuestión dentro de la tabla resultado. Esta característica hace posible ordenar un resultado en base a una columna que no tiene nombre.

Ejemplo:

SELECT RUT, NOMBRE
FROM CHOFER
WHERE SYSDATE < FECHA_LCENCIA_HASTA
ORDER BY 2 DESC