05. El lenguaje estándar SQL

El lenguaje SQL, es el lenguaje estándar actual para los sistemas de bases de datos relacionales. Fue desarrollado originalmente por IBM a mediados de los años setenta e implementado por primera vez en un prototipo de IBM, el System R.

En el año 1986 el lenguaje SQL fue propuesto por ANSI como lenguaje relacional, y fue aceptado en 1987 por ISO como lenguaje estándar. Versiones posteriores de este lenguaje han aparecido en 1989, 1992 y 1999.

En sus orígenes fue un lenguaje de tipo lógico, basado en el Cálculo Relacional (de tuplas) de E.F. Codd. Posteriormente fue incorporando aspectos (operadores) algebraicos. Se puede afirmar que el SQL actual es un híbrido entre el Álgebra Relacional y el Cálculo Relacional (de tuplas).

Así, permite tanto el uso explícito de operadores algebraicos (UNION, DIFERENCIA, etc) como el uso de expresiones lógicas de cualquier complejidad (variables-tupla, cuantificador existencial, etc).

El lenguaje SQL proporciona un sublenguaje de definición de datos (DDL) y un sublenguaje de manipulación de datos (DML), así como otros componentes de control de datos, que no pueden ser considerados ni de definición ni de manipulación: control de transacciones, control de usuarios, etc.

El lenguaje puede ser utilizado también en modo incrustado (o embebido), es decir en un programa de aplicación escrito en un lenguaje de alto nivel (FORTRAN, COBOL, ...), para ello introduce algunos componentes auxiliares que permiten manipular las tuplas individuales de una relación (concepto de CURSOR).

El lenguaje, fue pensado inicialmente como "un lenguaje de datos", de hecho el SQL no es computacionalmente completo, en el sentido de que no permite la definición de cualquier función computable Posteriores desarrollos han consisitido en incorporarle el sublenguaje PSM (Módulos Almacenados Persistentes), con lo que el lenguaje se ha convertido en completo en términos computacionales.

Lenguaje de definición de datos (DDL)

El lenguaje SQL ofrece un sublenguaje de definición de datos para definir el esquema de la base de datos. Una sintaxis resumida de este sublenguaje se presenta a continuación. La intención de este apartado es analizar el lenguaje de definición de datos del SQL con respecto al Modelo Relacional que se ha presentado en el tema.

El sublenguaje DDL del SQL, proporciona sentencias para realizar las siguientes funciones:

  • Definición del esquema: CREATE SCHEMA

  • Definición de dominios: CREATE DOMAIN

  • Definición de relaciones (esquema de relación y restricciones): CREATE TABLE

  • Definición de restricciones generales: CREATE ASSERTION.

  • Definición de relaciones derivadas (vistas): CREATE VIEW . (se verá en el punto 2.6.3 del tema)

  • Definición de permisos a usuarios: GRANT (se verá en el tema III)

  • Asociada a cada sentencia CREATE existe una sentencia DROP que permite eliminar el correspondiente elemento del esquema.

La sintaxis del DDL es la siguiente, donde la notación utilizada y el significado de que cada componente de las sentencias es obvio, debido a su similitud con los conceptos estudiados en la presentación del Modelo Relacional.

Definición del esquema:

esquema ::= CREATE SCHEMA

                        AUTHORIZATION usuario

                        elemento_esquema1, elemento_esquema2, ...

elemento_esquema ::= definición_dominio

                                        | definición_tabla

                                        | definición_restricción

                                        | definición_vista

                                        | definición_operación_grant

Definición de dominios:

definición_dominio ::= CREATE DOMAIN nom_dominio [AS] tipo_dato

                                        [DEFAULT {NULL | valor}]

                                        [restricción_dominio1, restricción_dominio2, ...]

restricción_dominio ::= [CONSTRAINT nombre_restricción]

                                        CHECK (condición)

                                        [cuando_comprobar]

Definición de relaciones:

definición_tabla ::= CREATE TABLE nom_tabla

                                    (elemento_tabla1, elemento_tabla2, ... )

elemento-tabla ::=definición_columna

                                    | restricción_tabla

definición_columna ::= nom_columna { tipo _datos | nom_dominio }

                                    [DEFAULT {valor | NULL}]

                                    [restricción_columna1, restricción_columna2, ...]

restricción_columna ::= [CONSTRAINT nombre_restricción]

                                    {NOT NULL

                                    | UNIQUE

                                    | PRIMARY KEY

                                    | REFERENCES nom_tabla [(nom_columna)]

                                    [MATCH {FULL | PARTIAL}]

                                    [ON DELETE {CASCADE | SET NULL | SET DEFAULT| NO ACTION}]

                                    [ON UPDATE {CASCADE | SET NULL | SET DEFAULT| NO ACTION}]

                                    | CHECK (condición) }

                                    [cuándo_comprobar]

restricción_tabla ::= [CONSTRAINT nombre-restricción]

                                    { UNIQUE (nom-columna1, nom-columna2, ... )

                                    | PRIMARY KEY (nom-columna1, nom-columna2, ...)

                                    | FOREIGN KEY (nom-columna1, nom-columna2, ...)

                                    REFERENCES nom-tabla [(nom-columna1, nom-columna2, ...)]

                                    [MATCH {FULL | PARTIAL}]

                                    [ON DELETE {CASCADE| SET NULL| SET DEFAULT| NO ACTION}]

                                    [ON UPDATE {CASCADE| SET NULL| SET DEFAULT| NO ACTION}]

                                    | CHECK (condición)}

                                    [cuando-comprobar]

Definición de restriciones (generales):

definición_restricción ::= CREATE ASSERTION nombre_restricción

                                    CHECK (condición)

                                    [cuando-comprobar]

cuando_comprobar:= [[NOT] DEFERRABLE] [INITIALLY {IMMEDIATE | DEFERRED}]

Modificación de una relación:

modificación_tabla::= ALTER TABLE nombre_tabla

                                    {ADD (definición_columna)

                                    |ALTER [COLUMN] (nombre_columna)

                                        {DROP DEFAULT

                                        | SET DEFAULT {literal

                                                                        | funcion_sistema

                                                                        | NULL} }

                                    | DROP [COLUMN] nombre_columna {RESTRICT | CASCADE} }

Borrado de una relación:

borrado_tabla::= DROP TABLE nombre_tabla {RESTRICT | CASCADE}

Como es fácil observar, las distintas sentencias del lenguaje, con sus componentes, permiten definir todos los conceptos del Modelo Relacional, tal como ha sido presentado en este tema:

  • Definición de dominios. Se contempla la definición de dominios, y la especificación de restricciones sobre ellos.

  • Definición de relaciones. Respecto a la estructura básica del Modelo, la relación, ésta no está correctamente contemplada en SQL, ya que en una tabla (término utilizado en SQL para referirse a la relación) pueden existir tuplas repetidas, es decir no se respeta el carácter conjuntista de la estructura relación.

  • El término columna en SQL corresponde (completamente) al concepto atributo en el Modelo Relacional.

  • Definición de restricciones.

    • Se contemplan los cuatro tipos de restricciones de integridad que ofrece el Modelo.

    • Para la integridad referencial, se contemplan los tres tipos de integridad, así como las directrices de restauración.

    • Se ofrece la posibilidad de definir restricciones generales (CHECK) a nivel de dominio, atributo o relación.

    • Se ofrece una sentencia (CREATE ASSERTION) para definir restricciones de integridad (generales) que no sean de ninguno de los cuatro tipos ofrecidos por el Modelo.

    • Se ofrece una cláusula (cuando_comprobar) para definir el modo de comprobación25 de las restricciones.

Ejemplo 2.35

Sea el siguiente esquema relacional:

Departamento (código: tira(5), nombre: tira(100), director tira(5), teléfono : tira(11))

    CP = {código}, VNN={nombre}

    Caj= {director} → Profesor f(director)=código Borrado NULOS Modificación CASCADA

    UNI={director}

Asignatura (código: tira(5), nombre: tira(100), semestre: tira(2), teo: real, prac: real, dep: tira(5))

    CP={código}, VNN={nombre, teo, prac, semestre, dep}

    CAj={dep} →Departamento f(dep)=código Modificación CASCADA

Profesor (código : tira(5), nombre: tira(50), teléfono: tira(11), categoría: tira(3), dep: tira(5) )

    CP={código}, VNN={nombre, categoría, dep}

    CAj={dep} → Departamento f(dep)=código Modificación CASCADA

Docencia ( cod_pro: tira(3), cod_asg: tira(3), gteo: entero, gprac: entero)

    CP={cod_pro, cod_asg}, VNN={gteo, gprac}

    CAj={cod_asg} → Asignatura f(cod_asg)=código Modificación CASCADA

    CAj={cod_pro} → Profesor   f(cod_pro)=código Borrado CASCADA Modificación CASCADA

Y las siguientes restricciones de integridad adicionales:

  • los créditos deben ser valores reales positivos.

  • los grupos de clase deben ser enteros positivos.

  • las categorías de un profesor son: TEU, TU, CEU y CU

  • un profesor con categoría TEU no puede dar mas de 33 créditos y un profesor con categoría TU no puede dar mas de 22 créditos.

El esquema en SQL se definiría:

CREATE SCHEMA Docencia-UPV

CREATE DOMAIN créditos AS NUMBER(1,1) CHECK (value>=0)

CREATE DOMAIN grupos AS INTEGER CHECK (value>=0)

CREATE TABLE Departamento

    ( código CHAR(5),

    nombre VARCHAR(100) NOT NULL,

    director CHAR(5) UNIQUE

                     REFERENCES Profesor (codigo)

                        ON UPDATE CASCADE

                        ON DELETE SET NULL,

    teléfono CHAR(11),

    CONSTRAINT CP_dpto PRIMARY KEY (código) )

CREATE TABLE Profesor

    ( codigo CHAR(5),

    nombre VARCHAR(50) NOT NULL,

    teléfono CHAR(11),

    categoría CHAR(3) NOT NULL

        CHECK categoría IN (‘TEU’, ‘TU’, ‘CEU’, ‘CU’),

    dep CHAR(5) NOT NULL,

    CONSTRAINT CP_prof PRIMARY KEY (codigo),

    CONSTRAINT CAj_prof_dpto FOREIGN KEY (dep)

                             REFERENCES Departamento (codigo)

                                ON UPDATE CASCADE  )

CREATE TABLE Asignatura

    ( codigo CHAR(5),

    nombre VARCHAR(100) NOT NULL,

    semestre CHAR(2) NOT NULL,

          teo créditos NOT NULL,

    prac créditos NOT NULL,

    dep CHAR(5) NOT NULL,

    CONSTRAINT CP_asg PRIMARY KEY (codigo),

    CONSTRAINT CAj_asg_dpto FOREIGN KEY (dep)

                            REFERENCES Departamento (codigo)

                                ON UPDATE CASCADE    )

CREATE TABLE Docencia

    ( cod_pro CHAR(5),

    cod_asg CHAR(5),

    gteo grupos NOT NULL,

    gprac grupos NOT NULL,

    CONSTRAINT CP_doc PRIMARY KEY (cod_pro, cod_asg),

    CONSTRAINT CAj_doc_prof FOREIGN KEY (cod_pro)

                            REFERENCES Profesor (codigo)

                                ON DELETE CASCADE

                                ON UPDATE CASCADE,

    CONSTRAINT CAj_doc_asg FOREIGN KEY (cod_asg)

                           REFERENCES Asignatura (codigo)

                                ON UPDATE CASCADE)

CREATE ASSERTION RI_docencia

    CHECK

        (NOT EXISTS ( SELECT * FROM PROFESOR P

            WHERE (P.categoría=“TEU”

                AND

                (SELECT SUM (gteo*teo + gprac*prac)

                FROM Docencia NATURAL JOIN Asignatura

                WHERE cod_pro = P.cod_pro) >33)

                OR

                (P.categoría=“TU”

                    AND

                    (SELECT SUM (gteo*teo + gprac*prac)

                    FROM Docencia NATURAL JOIN Asignatura

                    WHERE cod_pro=P.cod_pro) >22 ) ) )

Lenguaje de manipulación de datos (DML)

El sublenguaje de manipulación de datos (DML) del SQL proporciona sentencias de consulta (SELECT) y sentencias de actualización de datos (INSERT, DELETE y UPDATE).

LA SENTENCIA SELECT: INTEGRACIÓN DE LAS PERSPECTIVAS LÓGICA Y ALGEBRAICA

La sentencia de consulta del lenguaje es la sentencia SELECT. Su estructura básica es la siguiente:

SELECT R1X.Ai, R2X.Bj,..., RnX.Ck

FROM R1 [AS] R1X, R2 [AS] R2X, ..., Rn [AS] RnX

WHERE F(R1X, R2X,..., RnX)

donde, R1 R2, ..., Rn son relaciones, Ai Bj, ..., Ck son respectivamente atributos de los esquemas de R1, R2, ..., Rn, R1X, R2X,..., RnX son nombres alternativos (alias) de R1 R2, ..., Rn y F(R1X, R2X,..., RnX) es una condición. La semántica informal de esta sentencia es la siguiente: la evaluación de la SELECT devuelve una relación formada por los atributos Ai Bj, ..., Ck de las tuplas de las relaciones R1 R2, ..., Rn para las que la condición F es cierta en la extensión de la base de datos.

La sentencia SELECT se puede interpretar desde una perspectiva lógica o desde una perspectiva algebraica, lo que permite usar el lenguaje con un estilo algebraico o con un estilo lógico.

PERSPECTIVA LÓGICA

En el apartado 2.3.2, se justificó la utilidad del lenguaje de la Lógica de 1er orden como lenguaje relacional. En esa aproximación, una consulta a una base de datos relacional consiste en una fórmula lógica escrita en un lenguaje L derivado del esquema de la base de datos. Las ideas que se expusieron en dicho apartado se ilustran en el siguiente ejemplo.

Ejemplo 2.36

Sea el esquema relacional del Ejemplo 2.8

RÍO (rcod: dom_rcod, nombre: dom_nom)

OTROS_RIOS (rcod: dom_rcod, nombre: dom_nom)

PROVINCIA (pcod: dom_pcod, nombre: dom_nom)

PASA_POR (pcod: dom_pcod, rcod: dom_rcod)

El lenguaje lógico L derivado del esquema es:

Esquema E:

Río (rcod: dom_rcod, nombre: dom_nom)

Otros_Ríos (rcod: dom_rcod, nombre: dom_nom)

Provincia (pcod: dom_pcod, nombre: dom_nom)

Pasa_por (pcod: dom_pcod, rcod: dom_rcod)

Predicados de L:

Río (. , .)

Otros_Ríos (. , .)

Provincia(. , . )

Pasa_por(. , .)

Como este lenguaje L (se propuso utilizar una variante del lenguaje en el que las variables son variables-tupla, es decir variables que toman valores en las extensiones de las relaciones de la base de datos) se pueden escribir consultas a la base de datos representadas como fórmulas de L:

Consulta 1: "Códigos de ríos que pasan por la provincia de código 16 o por la provincia de código 44"

F1: PPX:Pasa_por PPX.pcod=16 ∨ PPX.pcod=44)

Consulta 2: "Provincias por las que no pasa ningún río"

F2: PX:Provincia ¬∃PPX:Pasa_por (PX.pcod=PPX.pcod)

donde PX es una variable-tupla declarada sobre la relación Provincia, y PPX es una variable-tupla declarada sobre la relación Pasa_por.

La Consulta 1 del Ejemplo 2.36 expresada en el lenguaje SQL sería:

SELECT PX.rcod

FROM Pasa_por PPX

WHERE PX.pcod=16 OR PPX.pcod=44.

La similitud entre la fórmula lógica F1 del Ejemplo 2.36 y la sentencia SQL es inmediata, La interpretación de sus componentes es la siguiente:

  • FROM Pasa_por PPX: la componente FROM de la sentencia hace la función de declaración de variables-tupla. La variable-tupla PPX se declara sobre la relación Pasa_por.

  • WHERE PX.pcod=16 OR PPX.pcod=44: la componente WHERE de la sentencia es una fórmula lógica, en la que las únicas variables libres son las variables-tupla declaradas en el FROM. Esta fórmula coincide con la fórmula F1 y representa (realmente) la consulta a la base de datos.

  • SELECT PPX.rcod: en la componente SELECT, se indican los atributos de las variables-tupla que se desean consultar.

La Consulta 2 del Ejemplo 2.36 se escribiría en SQL:

SELECTY PX.pcod, PX.nombre

FROM Provincia PX

WHERE

NOT EXISTS (SELECT * FROM Pasa_por PPX WHERE PPX.pcod=PX.pcod).

De nuevo la similitud entre la fórmula F2 y la correspondiente sentencia SELECT es inmediata.

La fórmula F2 aparece expresada en la componente WHERE de la sentencia; en la componente FROM se declara la variable-tupla PX que es la única variable libre en la fórmula de la componente WHERE; y en la componente SELECT se indican los atributos que interesa consultar.

Es interesante destacar la sintaxis del cuantificador existencial en el lenguaje SQL:

EXISTS (SELECT * FROM S1 S1X, S2 S2X, ..., Sn SnX

WHERE G(S1X, S2X, ..., SnX, R1X, R2X,..., RnX) )

que es equivalente a la fórmula:

∃S1X:S1 (∃S2X:S2 ...(∃SnX:Sn (G(S1X, S2X,..., SnX, R1X, R2X,..., RnX)) ...).

La sintaxis para el cuantificador universal en el lenguaje SQL es:

FOR ALL (SELECT * FROM S1 S1X, S2 S2X, ..., Sn SnX)

(G(S1X, S2X, ..., SnX, R1X, R2X,..., RnX) )

que es equivalente a la fórmula:

∀S1X:S1 (∀S2X:S2 ... ( ∀SnX:Sn (G(S1X, S2X,..., SnX, R1X, R2X,..., RnX)) ...).

En versiones anteriores al SQL99, no existía el cuantificador universal, debiéndose utilizar su definición a partir del cuantificador existencial: ∀x F(x) ≡ ¬∃x ¬F(x). En SQL:

NOT EXISTS (SELECT *

FROM S1 S1X, S2 S2X, ..., Sn SnX

WHERE NOT G(S1X, S2X,..., SnX, R1X, R2X,..., RnX) )

que es equivalente a la fórmula:

¬∃S1X:S1 (∃S2X:S2 ... (∃SnX:Sn ¬(G(S1X, S2X,...,SnX, R1X, R2X,..., RnX)) ...).

Ejemplo 2.37

Asumiendo el esquema del Ejemplo 2.8, considérese la consulta: "Obtener los ríos que pasan por todas las provincias".

En un lenguaje lógico (con variables-tupla) esta consulta se expresaría con la fórmula:

RX:Río | ∀PX:Provincia (∃PPX: Pasa_por (PPX.pcod=PX.pcod ∧ PPX.rcod=RX.rcod), ó

RX:Río | ¬∃ PX:Provincia (¬∃PPX: Pasa_por (PPX.pcod=PX.pcod ∧ PPX.rcod=RX.rcod)

en SQL:

SELECT RX.rcod, RX.nombre

FROM Río RX

WHERE

FOR ALL (SELECT * FROM Provincia PX)

(EXISTS (SELECT * FROM Pasa_por PPX WHERE PPX.pcod=PX.pcod AND PPX.rcod=RX.rcod)), ó

SELECT RX.rcod, RX.nombre

FROM Río RX

WHERE NOT EXISTS (SELECT * FROM Provincia PX

WHERE NOT EXISTS (SELECT * FROM Pasa_por PPX

WHERE PPX.pcod=PX.pcod ∧ PPX.rcod=RX.rcod))

Resumiendo, una sentencia SELECT, puede verse como una fórmula escrita en un lenguaje lógico derivado del esquema de la base de datos, en el que se utilizan variables-tupla que toman valores en las relaciones en la extensión actual de la base de datos. Así, el lenguaje SQL puede utilizarse como un lenguaje lógico para consultar la base de datos.

A continuación se presenta formalmente la sintaxis y la semántica de la sentencia SELECT.

Estas son similares a las de cualquier lenguaje de Lógica de 1er orden (ver 2.3.1), adaptadas a las particularidades sintácticas del SQL.

Sintaxis:

SELECT R1X.Ai, R2X.Bj,..., RnX.Ck

FROM R1 [AS] R1X, R2 [AS] R2X, ..., Rn [AS] RnX

WHERE F(R1X, R2X,..., RnX)

Con el siguiente significado para cada componente:

a) En la componente FROM se declaran variables de tipo tupla, R1X, R2X,..., RnX, sobre relaciones del esquema de la base de datos, R1, R2,..., Rn.

b) La componente WHERE es una fórmula lógica en la que las únicas variables que pueden ser libres son R1X, R2X,..., RnX. Esta fórmula se construye siguiendo la sintaxis usual de los lenguajes de 1er orden, para ello se dispone de las conectivas lógicas AND, OR y NOT que pueden ser aplicadas a condiciones escritas usando los predicados ofrecidos en el lenguaje (<, >, =, IS NULL, etc) o a fórmulas cuantificadas existencialmente o cuantificadas universalmente. Las reglas de construcción de estas fórmulas son:

Condición: Una condición es una expresión de una de las formas siguientes:

  • IS NULL (RX.Ai),

  • RX.Ai α SX.Aj, o

  • RX.Ai α a

dónde α es un operador de comparación (<, >, ≤, ≥, =, ≠), Ai y Aj son nombres de atributo de las relaciones de definición de las variables RX y SX respectivamente, y a es un valor del dominio asociado al atributo RX.Ai distinto del valor nulo.

Fórmula: Las fórmulas se construyen aplicando las siguientes reglas:

  • toda condición es una fórmula,

  • si F es una fórmula entonces (F) también lo es,

  • si F y G son fórmulas entonces también lo son F OR G, F AND G y NOT F,

  • si S es una sentencia SELECT entonces EXISTS (S) es una fórmula,

  • si S es una sentencia SELECT entonces FOR ALL (S) (Condición) es una fórmula, y

  • nada más es una fórmula.

c) En la componente SELECT se indican los atributos de las variables R1X, R2X, ..., RnX que se desean consultar.

Semántica:

La evaluación de una sentencia SELECT en la base de datos devuelve los valores de los atributos R1X.Aj, R2X.Bi,..., RnX.Ck, para aquellos valores de las variables R1X, R2X, ..., RnX que aparecen en las extensiones actuales de las relaciones R1, R2 , ... Rn, y para los cuales la fórmula F(R1X, R2X, ..., RnX) se evalúa a cierto en la base de datos. La evaluación de la fórmula F(R1X, R2X, ..., RnX) en la base de datos se realiza siguiendo las siguientes reglas:

Valor de verdad de una condición:

  • si F es de la forma RX.Ai α SX.Aj entonces F se evalúa a indefinido si al menos uno de los atributos, Ai o Aj tiene valor nulo en la tupla asignada a RX o respectivamente a SX, en caso contrario se evalúa al valor de certeza de la comparación,

  • si F es de la forma RX.Ai α a entonces F se evalúa a indefinido si Ai tiene valor nulo en la tupla asignada a RX, en caso contrario se evalúa al valor de certeza de la comparación; y

  • si F es de la forma IS NULL (RX.Ai) entonces F se evalúa a cierto si Ai tiene valor nulo para la tupla asignada a RX, en caso contrario se evalúa a falso.

Valor de verdad de una fórmula:

El valor de verdad de una fórmula F se define inductivamente como sigue:

  • si F es una condición entonces su valor de verdad es el de la condición,

  • si F es de la forma (F1) entonces su valor de verdad es el de F1,

  • si en F aparece alguna conectiva lógica (NOT, AND, OR) entonces su valor de verdad viene dado por las tablas de verdad de las conectivas, y

  • si F es de la forma EXISTS (SELECT * FROM S1 S1X, S2 S2X, ..., Sn SnX WHERE G(S1X, S2X, ..., SnX, R1X, R2X,..., RnX) ), entonces F se evalúa a cierto si existen valores de las variables S1X, S2X, ..., SnX en las extensiones de S1, S2 , ... Sn para los cuales G(S1X, S2X, ..., SnX, R1X, R2X,..., RnX) se evalúa a cierto en la base de datos, en caso contrario se evalúa a falso.

  • si F es de la forma FOR ALL (SELECT * FROM S1 S1X, S2 S2X, ..., Sn SnX) G(S1X, S2X, ..., SnX, R1X, R2X,..., RnX) ), entonces F se evalúa a cierto si para todos los valores de las variables S1X, S2X, ..., SnX en las extensiones de S1, S2 , ... Sn, G(S1X, S2X, ..., SnX, R1X, R2X,..., RnX) se evalúa a cierto en la base de datos, en caso contrario se evalúa a falso.

PERSPECTIVA ALGEBRAICA

En el apartado anterior se ha visto como la estructura básica de la sentencia SELECT puede interpretarse como una fórmula de un lenguaje lógico derivado del esquema de la base de datos.

Además de esta estructura básica, el SQL proporciona operadores adicionales, de carácter algebraico. Estos operadores son:

Operador Unión: Select1 UNION Select2

Operador Intersección: Select1 INTERSECT Select2

Operador Diferencia: Select1 EXCEPT Select2

Operador Producto Cartesiano: SELECT ....

FROM tablA1 CROSS JOIN tablA2

WHERE ....

Operador Concatenación: SELECT ....

FROM tablA1 NATURAL JOIN tablA2

WHERE ....

El significado de estos operadores es bastante obvio por lo que no necesitan mas explicación.

Por otra parte, la estructura básica de la sentencia SELECT se puede interpretar desde una perspectiva algebraica, de la siguiente forma:

SELECT R.Ai , R.Aj ..., R.Ak FROM R WHERE F

es equivalente a la expresión de Álgebra Relacional: R DONDE F [Ai , Aj ..., Ak ].

Es decir, la sentencia se puede interpretar como una selección de las tuplas de R que cumplen la condición de la fórmula F (construida según las leyes definidas para el operador Selección del Álgebra), seguida de una proyección sobre los atributos especificados.

En el caso de que se incluyan varias relaciones en la componente FROM:

SELECT R1.Ai, R2.Bj,..., Rn.Ck

FROM R1, R2, ..., Rn

WHERE F(R1, R2,..., Rn)

entonces la sentencia se puede interpretar como la siguiente expresión de Álgebra Relacional:

R1 x R2, ... x Rn DONDE F [R1.Ai, R2.Bj,..., Rn.Ck]

Es decir, la sentencia se interpreta como un producto cartesiano de las relaciones presentes en la componente FROM, seguido de la selección de las tuplas de este producto que cumplen la condición F, y por último la proyección de estas tuplas sobre los atributos especificados.

Con esta interpretación de la estructura básica de la sentencia SELECT, mas los operadores conjuntistas que ofrece el lenguaje, el SQL puede ser utilizado como un lenguaje algebraico. La equivalencia con el Álgebra Relacional es inmediata:

En los apartados anteriores se han ofrecidos dos interpretaciones del lenguaje SQL (sentencia SELECT) una interpretación algebraica y una interpretación lógica. En la primera interpretación, el SQL es un lenguaje algebraico equivalente al Álgebra Relacional definido por E.F. Codd, en la segunda interpretación el SQL es un lenguaje lógico similar al Cáluco Relacional (de tuplas) definido por E.F. Codd. Es decir en el lenguaje SQL se funden las dos aproximaciones al Modelo Relacional de Datos.

En la práctica, el lenguaje SQL se utiliza integrando aspectos de la interpretación lógica con aspectos de la interpretación algebraica, es decir se utiliza la estructura básica de la sentencia SELECT, escribiendo en su componente WHERE fórmulas lógicas de cualquier complejidad, y esta estructura básica se intercala con el uso de operadores algebraicos (JOIN, UNION,..)

Ejemplo 2.38

La consulta "Provincias por las que no pasa ningún río" del Ejemplo 2.8 se resolvería en SQL, usando un estilo algebraico :

SELECT pcod, nombre

FROM Provincia

    EXCEPT

SELECT pcod, nombre

FROM Provincia NATURAL JOIN Pasa_por

En un estilo lógico se resolvería:

SELECT pcod, nombre

FROM Provincia PX WHERE

                    NOT EXISTS (SELECT * FROM Pasa_por PPX

                                    WHERE PPX.pcod=PX.pcod).

SENTENCIAS DE ACTUALIZACIÓN: INSERT, DELETE Y UPDATE

El lenguaje SQL, ofrece tres sentencias para actualizar las relaciones.

SENTENCIA INSERT

La sentencia INSERT, permite insertar tuplas en una relación. La inserción en SQL puede ser simple (una única tupla) o múltiple (varias tuplas), por ello la sentencia INSERT admite dos sintaxis.

Inserción simple:

INSERT INTO R [(A1, A2, ... Ak)]

            {DEFAULT VALUES | VALUES (v1, v2, ..., vk) }.

El significado de esta sentencia es el siguiente: se inserta en la relación R una nueva tupla, cuyos valores se especifican en la componente VALUES; debe haber una correspondencia en número, tipo y orden entre los valores asignados y los atributos en el esquema de la relación. Si en el momento de la inserción sólo se conoce el valor de algunos atributos de la nueva tupla, se pueden especificar los atributos para los cuales se va a asignar valor (parte opcional [(A1, A2, ... Ak)] de la sentencia) para los restantes atributos se asignará el valor por defecto (si éste se ha especificado en la definición de la relación) o el valor nulo. Como indica la sintaxis también se puede insertar una nueva tupla asignando a cada atributo los valores por defecto definidos en el esquema de la base de datos.

Ejemplo 2.39

Sea el esquema del Ejemplo 2.8. La inserción de una nueva tupla en la relación Río, correspondiente al río Ebro, se realizaría de la forma: INSERT INTO Río VALUES (r3, 'Ebro').

Inserción múltiple:

INSERT INTO R [(A1, A2, ... Ak)] sentencia_SELECT

Esta sintaxis de la sentencia INSERT, permite insertar varias tuplas en una relación con una única operación, las tuplas insertadas serán las resultantes de evaluar la sentencia SELECT especificada en la operación. En este caso se siguen las mismas pautas para establecer la correspondencia entre atributos de R y valores de las tuplas seleccionadas por la SELECT.

Ejemplo 2.40

Sea el esquema del Ejemplo 2.8. Se desea insertar en la relación Río todos los ríos almacenados en la relación Otros_Ríos. La inserción se realizaría de la forma: INSERT INTO Río SELECT * FROM Otros_ríos

SENTENCIA DELETE

La sentencia DELETE, permite borrar tuplas en una relación.

DELETE FROM R [WHERE condición]

El significado de esta sentencia es el siguiente: se borran las tuplas de R que cumplen la condición especificada en la componente (opcional) WHERE, si esta componente no se usa, se borran todas las tuplas de la relación.

Ejemplo 2.41

Sea el esquema del Ejemplo 2.8. Se desean borrar las tuplas de la relación Pasa_por con información sobre los ríos que pasan por la provincia de código 16.

DELETE FROM Pasa_por WHERE pcod=16

SENTENCIA UPDATE

La sentencia UPDATE, permite actualizar las tuplas de una relación.

UPDATE R

    SET A1 = {DEFAULT| NULL | expresión1},

        A2 = {DEFAULT| NULL | expresión2},

        .......

    [WHERE condición ]

El significado de esta sentencia es el siguiente: actualiza las tuplas de R que cumplen la condición especificada en la componente (opcional) WHERE. La actualización se especifica en la componente SET donde se indican las actualizaciones que deben realizarse sobre los atributos.

Ejemplo 2.42

Sea el esquema del Ejemplo 2.8. Se desea actualizar el nombre del río de código 'r2', con el nuevo valor 'Guadiana'.

UPDATE Río

    SET nombre = 'Guadiana'

    WHERE rcod='r2'

Comments