El Lenguaje SQL

Como en el caso de los m�s modernos lenguajes relacionales, SQL est� basado en el c�lculo relacional de tuplas. Como resultado, toda consulta formulada utilizando el c�lculo relacional de tuplas ( o su equivalente, el �lgebra relacional) se pude formular tambi�n utilizando SQL. Hay, sin embargo, capacidades que van m�s all� del c�lculo o del �lgebra relaciona. Aqu� tenemos una lista de algunas caracter�sticas proporcionadas por SQL que no forman parte del �lgebra y del c�lculo relacionales:

Select

El comando m�s usado en SQL es la instrucci�n SELECT, que se utiliza para recuperar datos. La sintaxis es:

   SELECT [ALL|DISTINCT] 
          { * | expr_1 [AS c_alias_1] [, ... 
                [, expr_k [AS c_alias_k]]]}
   FROM table_name_1 [t_alias_1] 
        [, ... [, table_name_n [t_alias_n]]]
   [WHERE condition]
   [GROUP BY name_of_attr_i 
             [,... [, name_of_attr_j]] [HAVING condition]]
   [{UNION [ALL] | INTERSECT | EXCEPT} SELECT ...]
   [ORDER BY name_of_attr_i [ASC|DESC] 
             [, ... [, name_of_attr_j [ASC|DESC]]]];
     

Ilustraremos ahora la compleja sintaxis de la instrucci�n SELECT con varios ejemplos. Las tablas utilizadas para los ejemplos se definen en: La Base de Datos de Proveedores y Art�culos.

Select sencillas

Aqu� tenemos algunos ejemplos sencillos utilizando la instrucci�n SELECT:

Ejemplo 4. Query sencilla con cualificaci�n

Para recuperar todas las tuplas de la tabla PART donde el atributo PRICE es mayor que 10, formularemos la siguiente consulta:

   SELECT * FROM PART
     WHERE PRICE > 10;
	
y obtenemos la siguiente tabla:
                   PNO |  PNAME      |  PRICE
                  -----+-------------+--------
                    3  |  Cerrojos   |   15
                    4  |  Levas      |   25
	

Utilizando "*" en la instrucci�n SELECT solicitaremos todos los atributos de la tabla. Si queremos recuperar s�lo los atributos PNAME y PRICE de la tabla PART utilizaremos la instrucci�n:

   SELECT PNAME, PRICE 
   FROM PART
   WHERE PRICE > 10;
	
En este caso el resultado es:
                      PNAME      |  PRICE
                     ------------+--------
                      Cerrojos   |   15
                      Levas      |   25
	
N�tese que la SELECT SQL corresponde a la "proyecci�n" en �lgebra relaciona, no a la "selecci�n" (vea �lgebra Relacional para m�s detalles).

Las cualificaciones en la clausula WHERE pueden tambi�n conectarse l�gicamente utilizando las palabras claves OR, AND, y NOT:

   SELECT PNAME, PRICE 
   FROM PART
   WHERE PNAME = 'Cerrojos' AND
         (PRICE = 0 OR PRICE < 15);
	
dar� como resultado:
                      PNAME      |  PRICE
                     ------------+--------
                      Cerrojos   |   15
	

Las operaciones aritm�ticas se pueden utilizar en la lista de objetivos y en la clausula WHERE. Por ejemplo, si queremos conocer cuanto cuestan si tomamos dos piezas de un art�culo, podr�amos utilizar la siguiente consulta:

   SELECT PNAME, PRICE * 2 AS DOUBLE
   FROM PART
   WHERE PRICE * 2 < 50;
	
y obtenemos:
                      PNAME      |  DOUBLE
                     ------------+---------
                      Tornillos  |    20
                      Tuercas    |    16
                      Cerrojos   |    30
	
N�tese que la palabra DOBLE tras la palabra clave AS es el nuevo t�tulo de la segunda columna. Esta t�cnica puede utilizarse para cada elemento de la lista objetivo para asignar un nuevo t�tulo a la columna resultante. Este nuevo t�tulo recibe el calificativo de "un alias". El alias no puede utilizarse en todo el resto de la consulta.

Joins (Cruces)

El siguiente ejemplo muestra como las joins (cruces) se realizan en SQL.

Para cruzar tres tablas SUPPLIER, PART y SELLS a trav�s de sus atributos comunes, formularemos la siguiente instrucci�n:

   SELECT S.SNAME, P.PNAME
   FROM SUPPLIER S, PART P, SELLS SE
   WHERE S.SNO = SE.SNO AND
         P.PNO = SE.PNO;
      
y obtendremos la siguiente tabla como resultado:
                       SNAME | PNAME
                      -------+-------
                       Smith | Tornillos
                       Smith | Tuercas
                       Jones | Levas
                       Adams | Tornillos
                       Adams | Cerrojos
                       Blake | Tuercas
                       Blake | Cerrojos
                       Blake | Levas
      

En la clausula FROM hemos introducido un alias al nombre para cada relaci�n porque hay atributos con nombre com�n (SNO y PNO) en las relaciones. Ahora podemos distinguir entre los atributos con nombre com�n simplificando la adicci�n de un prefijo al nombre del atributo con el nombre del alias seguido de un punto. La join se calcula de la misma forma, tal como se muestra en Una Inner Join (Una Join Interna). Primero el producto cartesiano: SUPPLIER � PART � SELLS Ahora seleccionamos �nicamente aquellas tuplas que satisfagan las condiciones dadas en la clausula WHERE (es decir, los atributos con nombre com�n deben ser iguales). Finalmente eliminamos las columnas repetidas (S.SNAME, P.PNAME).

Operadores Agregados

SQL proporciona operadores agregados (como son AVG, COUNT, SUM, MIN, MAX) que toman el nombre de un atributo como argumento. El valor del operador agregado se calcula sobre todos los valores de la columna especificada en la tabla completa. Si se especifican grupos en la consulta, el c�lculo se hace s�lo sobre los valores de cada grupo (vean la siguiente secci�n).

Ejemplo 5. Aggregates

Si queremos conocer el coste promedio de todos los art�culos de la tabla PART, utilizaremos la siguiente consulta:

   SELECT AVG(PRICE) AS AVG_PRICE
   FROM PART;
	

El resultado es:

                         AVG_PRICE
                        -----------
                           14.5
	

Si queremos conocer cuantos art�culos se recogen en la tabla PART, utilizaremos la instrucci�n:

   SELECT COUNT(PNO)
   FROM PART;
	
y obtendremos:
                           COUNT
                          -------
                             4
	

Agregaci�n por Grupos

SQL nos permite particionar las tuplas de una tabla en grupos. En estas condiciones, los operadores agregados descritos antes pueden aplicarse a los grupos (es decir, el valor del operador agregado no se calculan sobre todos los valores de la columna especificada, sino sobre todos los valores de un grupo. El operador agregado se calcula individualmente para cada grupo).

El particionamiento de las tuplas en grupos se hace utilizando las palabras clave GROUP BY seguidas de una lista de atributos que definen los grupos. Si tenemos GROUP BY A1, ⃛, Ak habremos particionado la relaci�n en grupos, de tal modo que dos tuplas son del mismo grupo si y s�lo si tienen el mismo valor en sus atributos A1, ⃛, Ak.

Ejemplo 6. Agregados

Si queremos conocer cu�ntos art�culos han sido vendidos por cada proveedor formularemos la consulta:

   SELECT S.SNO, S.SNAME, COUNT(SE.PNO)
   FROM SUPPLIER S, SELLS SE
   WHERE S.SNO = SE.SNO
   GROUP BY S.SNO, S.SNAME;
	
y obtendremos:
                     SNO | SNAME | COUNT
                    -----+-------+-------
                      1  | Smith |   2
                      2  | Jones |   1
                      3  | Adams |   2
                      4  | Blake |   3
	

Demos ahora una mirada a lo que est� ocurriendo aqu�. Primero, la join de las tablas SUPPLIER y SELLS:

                  S.SNO | S.SNAME | SE.PNO
                 -------+---------+--------
                    1   |  Smith  |   1
                    1   |  Smith  |   2
                    2   |  Jones  |   4
                    3   |  Adams  |   1
                    3   |  Adams  |   3
                    4   |  Blake  |   2
                    4   |  Blake  |   3
                    4   |  Blake  |   4
	

Ahora particionamos las tuplas en grupos reuniendo todas las tuplas que tiene el mismo atributo en S.SNO y S.SNAME:

                  S.SNO | S.SNAME | SE.PNO
                 -------+---------+--------
                    1   |  Smith  |   1
                                  |   2
                 --------------------------
                    2   |  Jones  |   4
                 --------------------------
                    3   |  Adams  |   1
                                  |   3
                 --------------------------
                    4   |  Blake  |   2
                                  |   3
                                  |   4
	

En nuestro ejemplo, obtenemos cuatro grupos y ahora podemos aplicar el operador agregado COUNT para cada grupo, obteniendo el resultado total de la consulta dada anteriormente.

N�tese que para el resultado de una consulta utilizando GROUP BY y operadores agregados para dar sentido a los atributos agrupados, debemos primero obtener la lista objetivo. Los dem�s atributos que no aparecen en la clausula GROUP BY se seleccionar�n utilizando una funci�n agregada. Por otro lado, no se pueden utilizar funciones agregadas en atributos que aparecen en la clausula GROUP BY.

Having

La clausula HAVING trabaja de forma muy parecida a la clausula WHERE, y se utiliza para considerar s�lo aquellos grupos que satisfagan la cualificaci�n dada en la misma. Las expresiones permitidas en la clausula HAVING deben involucrar funcionen agregadas. Cada expresi�n que utilice s�lo atributos planos deber� recogerse en la clausula WHERE. Por otro lado, toda expresi�n que involucre funciones agregadas debe aparecer en la clausula HAVING.

Ejemplo 7. Having

Si queremos solamente los proveedores que venden m�s de un art�culo, utilizaremos la consulta:

   SELECT S.SNO, S.SNAME, COUNT(SE.PNO)
   FROM SUPPLIER S, SELLS SE
   WHERE S.SNO = SE.SNO
   GROUP BY S.SNO, S.SNAME
   HAVING COUNT(SE.PNO) > 1;
	
y obtendremos:
                     SNO | SNAME | COUNT
                    -----+-------+-------
                      1  | Smith |   2
                      3  | Adams |   2
                      4  | Blake |   3
	

Subconsultas

En las clausulas WHERE y HAVING se permite el uso de subconsultas (subselects) en cualquier lugar donde se espere un valor. En este caso, el valor debe derivar de la evaluaci�n previa de la subconsulta. El uso de subconsultas ampl�a el poder expresivo de SQL.

Ejemplo 8. Subselect

Si queremos conocer los art�culos que tienen mayor precio que el art�culo llamado 'Tornillos', utilizaremos la consulta:

   SELECT *
   FROM PART
   WHERE PRICE > (SELECT PRICE FROM PART
                  WHERE PNAME='Tornillos');
	

El resultado ser�:

                   PNO |  PNAME      |  PRICE
                  -----+-------------+--------
                    3  |  Cerrojos   |   15
                    4  |  Levas      |   25
	

Cuando revisamos la consulta anterior, podemos ver la palabra clave SELECT dos veces. La primera al principio de la consulta - a la que nos referiremos como la SELECT externa - y la segunda en la clausula WHERE, donde empieza una consulta anidada - nos referiremos a ella como la SELECT interna. Para cada tupla de la SELECT externa, la SELECT interna deber� ser evaluada. Tras cada evaluaci�n, conoceremos el precio de la tupla llamada 'Tornillos', y podremos chequear si el precio de la tupla actual es mayor.

Si queremos conocer todos los proveedores que no venden ning�n art�culo (por ejemplo, para poderlos eliminar de la base de datos), utilizaremos:

   SELECT * 
   FROM SUPPLIER S
   WHERE NOT EXISTS
             (SELECT * FROM SELLS SE
              WHERE SE.SNO = S.SNO);
	

En nuestro ejemplo, obtendremos un resultado vac�o, porque cada proveedor vende al menos un art�culo. N�tese que utilizamos S.SNO de la SELECT externa en la clausula WHERE de la SELECT interna. Como hemos descrito antes, la subconsulta se eval�a para cada tupla de la consulta externa, es decir, el valor de S.SNO se toma siempre de la tupla actual de la SELECT externa.

Uni�n, Intersecci�n, Excepci�n

Estas operaciones calculan la uni�n, la intersecci�n y la diferencia de la teor�a de conjuntos de las tuplas derivadas de dos subconsultas.

Ejemplo 9. Union, Intersect, Except

La siguiente consulta es un ejemplo de UNION:

   SELECT S.SNO, S.SNAME, S.CITY
   FROM SUPPLIER S
   WHERE S.SNAME = 'Jones'
   UNION
   SELECT S.SNO, S.SNAME, S.CITY
   FROM SUPPLIER S
   WHERE S.SNAME = 'Adams';    
	
Dar� el resultado:
                     SNO | SNAME |  CITY
                    -----+-------+--------
                      2  | Jones | Paris
                      3  | Adams | Vienna
	

Aqu� tenemos un ejemplo para INTERSECT:

   SELECT S.SNO, S.SNAME, S.CITY
   FROM SUPPLIER S
   WHERE S.SNO > 1
   INTERSECT
   SELECT S.SNO, S.SNAME, S.CITY
   FROM SUPPLIER S
   WHERE S.SNO > 2;
	
que dar� como resultado:
                     SNO | SNAME |  CITY
                    -----+-------+--------
                      2  | Jones | Paris
         La �nica tupla devuelta por ambas partes de la consulta es la �nica que tiene $SNO=2$.
	

Finalmente, un ejemplo de EXCEPT:

   SELECT S.SNO, S.SNAME, S.CITY
   FROM SUPPLIER S
   WHERE S.SNO > 1
   EXCEPT
   SELECT S.SNO, S.SNAME, S.CITY
   FROM SUPPLIER S
   WHERE S.SNO > 3;
	
que dar� como resultado:
                     SNO | SNAME |  CITY
                    -----+-------+--------
                      2  | Jones | Paris
                      3  | Adams | Vienna
	

Definici�n de Datos

El lenguaje SQL incluye un conjunto de comandos para definici�n de datos.

Create Table

El comando fundamental para definir datos es el que crea una nueva relaci�n (una nueva tabla). La sintaxis del comando CREATE TABLE es:

   CREATE TABLE table_name
                (name_of_attr_1 type_of_attr_1
                 [, name_of_attr_2 type_of_attr_2 
                 [, ...]]);
      

Ejemplo 10. Creaci�n de una tabla

Para crear las tablas definidas en La Base de Datos de Proveedores y Art�culos se utilizaron las siguientes instrucciones de SQL:

   CREATE TABLE SUPPLIER
                (SNO   INTEGER,
                 SNAME VARCHAR(20),
                 CITY  VARCHAR(20));
	
   CREATE TABLE PART
                (PNO   INTEGER,
                 PNAME VARCHAR(20),
                 PRICE DECIMAL(4 , 2));
	
   CREATE TABLE SELLS
                (SNO INTEGER,
                 PNO INTEGER);
	

Tipos de Datos en SQL

A continuaci�n sigue una lista de algunos tipos de datos soportados por SQL:

  • INTEGER: entero binario con signo de palabra completa (31 bits de precisi�n).

  • SMALLINT: entero binario con signo de media palabra (15 bits de precisi�n).

  • DECIMAL (p[,q]): n�mero decimal con signo de p d�gitos de precisi�n, asumiendo q a la derecha para el punto decimal. (15 ≥ pqq ≥ 0). Si q se omite, se asume que vale 0.

  • FLOAT: num�rico con signo de doble palabra y coma flotante.

  • CHAR(n): cadena de caracteres de longitud fija, de longitud n.

  • VARCHAR(n): cadena de caracteres de longitud variable, de longitud m�xima n.

Create Index

Se utilizan los �ndices para acelerar el acceso a una relaci�n. Si una relaci�n R tiene un �ndice en el atributo A podremos recuperar todas la tuplas t que tienen t(A) = a en un tiempo aproximadamente proporcional al n�mero de tales tuplas t m�s que en un tiempo proporcional al tama�o de R.

Para crear un �ndice en SQL se utiliza el comando CREATE INDEX. La sintaxis es:

   CREATE INDEX index_name 
   ON table_name ( name_of_attribute );
      

Ejemplo 11. Create Index

Para crear un �ndice llamado I sobre el atributo SNAME de la relaci�n SUPPLIER, utilizaremos la siguiente instrucci�n:

   CREATE INDEX I
   ON SUPPLIER (SNAME);
      

El �ndice creado se mantiene autom�ticamente. es decir, cada vez que una nueva tupla se inserte en la relaci�n SUPPLIER, se adaptar� el �ndice I. N�tese que el �nico cambio que un usuario puede percibir cuando se crea un �ndice es un incremento en la velocidad.

Create View

Se puede ver una vista como una tabla virtual, es decir, una tabla que no existe f�sicamente en la base de datos, pero aparece al usuario como si existiese. Por contra, cuando hablamos de una tabla base, hay realmente un equivalente almacenado para cada fila en la tabla en alg�n sitio del almacenamiento f�sico.

Las vistas no tienen datos almacenados propios, distinguibles y f�sicamente almacenados. En su lugar, el sistema almacena la definici�n de la vista (es decir, las reglas para acceder a las tablas base f�sicamente almacenadas para materializar la vista) en alg�n lugar de los cat�logos del sistema (vea System Catalogs). Para una discusi�n de las diferentes t�cnicas para implementar vistas, refi�rase a SIM98.

En SQL se utiliza el comando CREATE VIEW para definir una vista. La sintaxis es:

   CREATE VIEW view_name
   AS select_stmt
      
donde select_stmt es una instrucci�n select v�lida, como se defini� en Select. N�tese que select_stmt no se ejecuta cuando se crea la vista. Simplemente se almacena en los cat�logos del sistema y se ejecuta cada vez que se realiza una consulta contra la vista.

Sea la siguiente definici�n de una vista (utilizamos de nuevo las tablas de La Base de Datos de Proveedores y Art�culos ):

   CREATE VIEW London_Suppliers
      AS SELECT S.SNAME, P.PNAME
         FROM SUPPLIER S, PART P, SELLS SE
         WHERE S.SNO = SE.SNO AND
               P.PNO = SE.PNO AND
               S.CITY = 'London';
      

Ahora podemos utilizar esta relaci�n virtual London_Suppliers como si se tratase de otra tabla base:

   SELECT *
   FROM London_Suppliers
   WHERE P.PNAME = 'Tornillos';
      
Lo cual nos devolver� la siguiente tabla:
                       SNAME | PNAME
                      -------+----------
                       Smith | Tornillos
      

Para calcular este resultado, el sistema de base de datos ha realizado previamente un acceso oculto a las tablas de la base SUPPLIER, SELLS y PART. Hace esto ejecutando la consulta dada en la definici�n de la vista contra aquellas tablas base. Tras eso, las cualificaciones adicionales (dadas en la consulta contra la vista) se podr�n aplicar para obtener la tabla resultante.

Drop Table, Drop Index, Drop View

Se utiliza el comando DROP TABLE para eliminar una tabla (incluyendo todas las tuplas almacenadas en ella):

   DROP TABLE table_name;
       

Para eliminar la tabla SUPPLIER, utilizaremos la instrucci�n:

   DROP TABLE SUPPLIER;
      

Se utiliza el comando DROP INDEX para eliminar un �ndice:

   DROP INDEX index_name;
      

Finalmente, eliminaremos una vista dada utilizando el comando DROP VIEW:

   DROP VIEW view_name;
      

Manipulaci�n de Datos

Insert Into

Una vez que se crea una tabla (vea Create Table), puede ser llenada con tuplas mediante el comando INSERT INTO. La sintaxis es:

   INSERT INTO table_name (name_of_attr_1 
                             [, name_of_attr_2 [,...]])
   VALUES (val_attr_1 
           [, val_attr_2 [, ...]]);
      

Para insertar la primera tupla en la relaci�n SUPPLIER (de La Base de Datos de Proveedores y Art�culos) utilizamos la siguiente instrucci�n:

   INSERT INTO SUPPLIER (SNO, SNAME, CITY)
   VALUES (1, 'Smith', 'London');
      

Para insertar la primera tupla en la relaci�n SELLS, utilizamos:

   INSERT INTO SELLS (SNO, PNO)
   VALUES (1, 1);
      

Update

Para cambiar uno o m�s valores de atributos de tuplas en una relaci�n, se utiliza el comando UPDATE. La sintaxis es:

   UPDATE table_name
   SET name_of_attr_1 = value_1 
       [, ... [, name_of_attr_k = value_k]]
   WHERE condition;
      

Para cambiar el valor del atributo PRICE en el art�culo 'Tornillos' de la relaci�n PART, utilizamos:

   UPDATE PART
   SET PRICE = 15
   WHERE PNAME = 'Tornillos';
      

El nuevo valor del atributo PRICE de la tupla cuyo nombre es 'Tornillos' es ahora 15.

Delete

Para borrar una tupla de una tabla particular, utilizamos el comando DELETE FROM. La sintaxis es:

   DELETE FROM table_name
   WHERE condition;
      

Para borrar el proveedor llamado 'Smith' de la tabla SUPPLIER, utilizamos la siguiente instrucci�n:

   DELETE FROM SUPPLIER
   WHERE SNAME = 'Smith';
      

System Catalogs

En todo sistema de base de datos SQL se emplean cat�logos de sistema para mantener el control de qu� tablas, vistas, �ndices, etc est�n definidas en la base de datos. Estos cat�logos del sistema se pueden investigar como si de cualquier otra relaci�n normal se tratase. Por ejemplo, hay un cat�logo utilizado para la definici�n de vistas. Este cat�logo almacena la consulta de la definici�n de la vista. Siempre que se hace una consulta contra la vista, el sistema toma primero la consulta de definici�n de la vista del cat�logo y materializa la vista antes de proceder con la consulta del usuario (vea SIM98 para obtener una descripci�n m�s detallada). Dir�jase aDATE para obtener m�s informaci�n sobre los cat�logos del sistema.

SQL Embebido

En esta secci�n revisaremos como se puede embeber SQL en un lenguaje de host (p.e. C). Hay dos razones principales por las que podr�amos querer utilizar SQLdesde un lenguaje de host:

Un programa que utiliza SQL embebido en un lenguaje de host consiste en instrucciones del lenguaje del host e instrucciones de SQL embebido (ESQL). Cada instrucci�n de ESQL empieza con las palabras claves EXEC SQL. Las instrucciones ESQL se transforman en instrucciones del lenguaje del host mediante un precompilador (que habitualmente inserta llamadas a rutinas de librer�as que ejecutan los variados comandos de SQL).

Cuando vemos los ejemplos de Select observamos que el resultado de las consultas es algo muy pr�ximo a un conjunto de tuplas. La mayor�a de los lenguajes de host no est�n dise�ados para operar con conjuntos, de modo que necesitamos un mecanismo para acceder a cada tupla �nica del conjunto de tuplas devueltas por una instrucci�n SELECT. Este mecanismo puede ser proporcionado declarando un cursor. Tras ello, podemos utilizar el comando FETCH para recuperar una tupla y apuntar el cursor hacia la siguiente tupla.

Para una discusi�n m�s detallada sobre el SQL embebido, dir�jase a [Date and Darwen, 1997], [Date, 1994], o [Ullman, 1988].