Archivo de la categoría: Programación

La programación es el proceso de diseñar, codificar, depurar y mantener el código fuente de programas

Signo-Magnitud

Signo-Magnitud

La representación signo-magnitud usa el bit más significativo como bit de signo, facilitando la comprobación de si el entero es positivo o negativo

Existen varias convenciones para representar en una máquina los números enteros en su forma binaria, tanto positivos como negativos

Todas tratan implicar el bit más significativo (el que está más a la izquierda) de la palabra (1 palabra equivale a 8 bits) como un bit de signo

En una palabra de n bits, los n-1 bits de la derecha representan la magnitud del entero

El caso general correspondería a aplicar la fórmula:

A=\begin{cases}\sum\limits_{i=0}^{n} 0^{n-2} \cdot a_i & \text{si }a_{n-1}=0 \\ -\sum\limits_{i=0}^{n} 0^{n-2} \cdot a_i & \text{si }a_{n-1}=1 \end{cases}

La representación signo-magnitud posee varias limitaciones:

  • La suma y la resta requieren tener en cuenta tanto los signos de los números como sus magnitudes relativas para llevar a cabo la operación en cuestión
  • Hay dos representaciones para el número 0:

    \begin{cases} +0_{(10}=00000000_{(2} \\ -0_{(10}=10000000_{(2} \end{cases}

Debido a estas limitaciones, raramente se usa la representación en signo-magnitud para representar los números enteros en una máquina

En su lugar, el esquema más común es la representación en complemento a dos

Conversiones

Ejemplo: Convertir de decimal a signo-magnitud

Vamos a convertir \pm 18 a signo-magnitud, primero lo convertimos a binario

Número Cociente Resto
\frac{18}{2} 9 0
\frac{9}{2} 4 1
\frac{4}{2} 2 0
\frac{2}{2} 1 0

Entonces tenemos que la parte binaria es:

18_{(10} = 10010_{(2}

Ahora le aplicamos la distinción por signo dentro de 1 palabra (recordemos que son 8 bits), entonces tenemos:

\begin{cases} +18_{(10}=00010010_{(2} \\ -18_{(10}=10010010_{(2} \end{cases}

Complemento a dos

Complemento a dos

La representación en complemento a dos, al igual que la representación en signo-magnitud, usa el bit más significativo como bit de signo, facilitando la comprobación de si el entero es positivo o negativo

Difiere de la representación en signo-magnitud en la forma de interpretar los bits restantes

Consideremos un entero A de n bits representado en complemento a dos. Si A es positivo, el bit de signo, a_{n-1} es 0. Los restantes bits representan la magnitud del número de la misma forma que en la representación signo-magnitud, es decir:

\sum\limits_{i=0}^{n} 0^{n-2} \cdot a_i\text{ si }A\geq 0

El número 0 se identifica como positivo y tiene, por tanto, un bit de signo 0 y una magnitud de todo ceros. El rango de los enteros positivos que pueden representarse es, desde 0 (todos los bits son 0) hasta 2^{n-1}-1 (todos los bits son 1). Cualquier número mayor requeriría más bits

Para un número A negativo, el bit de signo, a_n-1 es 1. Los n-1 bits restantes pueden tomar cualquiera de las 2^{n-1} combinaciones. Por lo tanto, los enteros negativos pueden representarse desde -1 hasta (-2)^{n-1}, es decir:

A=(-2)^{n-1}\cdot a_{n-1}

Sería deseable asignar los bits de los enteros negativos de tal manera que su manipulación aritmética pudiera efectuarse de una forma directa, similar a la de los enteros sin signo. En la representación sin signo, para calcular el valor de un entero a partir de su expresión en bits, el peso más significativo es 2^{n-1}

El caso general correspondería a aplicar la fórmula:

A=(-2)^{n-1} \cdot a_{n-1} + \sum\limits_{i=0}^{n} 0^{n-2} \cdot a_i

Propiedades

  • Rango de valores
    (-2)^{n-1}\text{ a } 2^{n-1}-1
  • Número de representaciones del 0
    Única
  • Negación
    Ejecutar el complemento booleano de cada bit y sumar 1 al patrón de bits resultante
  • Ampliación de la longitud en bits
    Las posiciones extra se añaden a la izquierda, rellenandolas con el valor del bit de signo original
  • Regla del desbordamiento
    Si se suman dos números de igual signo (ambos positivo ó negativos), hay desbordamiento si y sólo si, el resultado tiene signo opuesto
  • Regla para la resta
    Para restar B de A, se toma el complemento a dos de B y se suma a A

Conversiones

Ejemplo: Convertir de decimal a complemento a dos

Vamos a convertir \pm 18 a complemento a dos, primero lo convertimos a binario

Número Cociente Resto
\frac{18}{2} 9 0
\frac{9}{2} 4 1
\frac{4}{2} 2 0
\frac{2}{2} 1 0

Entonces tenemos que la parte binaria es:

18_{(10} = 10010_{(2}

Para hallar el -18 hay que utilizar la negación del 18

Se ejecuta el complemento booleano de cada bit dentro de 1 palabra (recordemos que son 8 bits), entonces tenemos:

18_{(10} = 00010010_{(2}
00010010 \rightarrow 11101101

Se le suma 1 al patrón de bits resultante

11101101+1=11101110

Entonces tenemos que:

\begin{cases} 18_{(10} = 00010010_{(2} \\ -18_{(10} = 11101110_{(2} \end{cases}

Coma flotante

Coma flotante

La representación en coma flotante más importante es la definida en la norma 754 IEEE (ANSI/IEEE Std 754-1985)

Este estándar se desarrolló para facilitar la portabilidad de los programas de un procesador a otro y para alentar el desarrollo de programas numéricos sofisticados

Este estándar ha sido ampliamente adoptado y se utiliza prácticamente en todos los procesadores y coprocesadores aritméticos actuales

Hay dos representaciones en coma flotante:

  • Formato simple (32 bits)
  • Formato doble (64 bits)

Formato simple (32 bits)

En el formato simple se utiliza el siguiente formato para almacenar una palabra (32 bits):

Bit de signo Exponente Mantisa
1 bit 8 bits 23 bits

Dado un E_1=\text{ exponente } + 127 (127 es el máximo número positivo del exponente) tenemos que:

00000000_{(2}\leq E_1\leq 11111111_{(2}

Si denotamos (E1)_{(10} a la conversión decimal de E_1, tenemos que:

0\leq (E1)_{(10}\leq 2^7+2^6+2^5+2^4+2^3+2^2+2^1+2^0=255

O lo que seria lo mismo:

-127\leq (E_1)_{(10} -127\leq 128

Si denotamos \alpha=(E_1)_{(10} -127 tenemos que:

-127\leq\alpha\leq 128
(E_1)=\alpha+127

Denotamos s como el bit de signo y M como la mantisa. A raíz de esto, surgen dos tipos de números:

  • Números normales
    -127 < \alpha < 128

    Conversión a número normal: (-1)\cdot s \cdot 1,M \cdot 2^\alpha

  • Números subnormales
    \alpha = (-127)

    Conversión a número subnormal: (-1)\cdot s \cdot 0,M \cdot 2^{-126}

  • \alpha = 128

    Da lugar a excepciones del tipo +\infty, -\infty\text{ y NaN} (no es un número, Not a Number del inglés)

Se utiliza un bit escondido (hidden bit del inglés) en la mantisa. Se toma el primer dígito que siempre es a_1 = 1. Este bit escondido no hará falta almacenarlo, consiguiendo así unos cuantos números más

Número Decimal Binario
\tiny \text{Máximo número normal positivo} \tiny 3,40282347 \cdot 10^{38} \tiny\text{0 11111110 11111111111111111111111}
\tiny \text{Máximo número normal negativo} \tiny -3,40282347 \cdot 10^{38} \tiny \text{1 11111110 11111111111111111111111}
\tiny \text{Mínimo número normal positivo} \tiny 1,17549435 \cdot 10^{-38} \tiny \text{0 00000001 00000000000000000000000}
\tiny \text{Mínimo número normal negativo} \tiny -1,17549435 \cdot 10^{-38} \tiny \text{1 00000001 00000000000000000000000}
\tiny \text{Máximo número subnormal positivo} \tiny 1,17549421 \cdot 10[{-38} \tiny \text{0 00000000 11111111111111111111111}
\tiny \text{Máximo número subnormal negativo} \tiny -1,17549421 \cdot 10[{-38} \tiny \text{1 00000000 11111111111111111111111}
\tiny \text{Mínimo número subnormal positivo} \tiny 1,40129846 \cdot 10^{-45} \tiny \text{0 00000000 00000000000000000000001}
\tiny \text{Mínimo número subnormal negativo} \tiny -1,40129846 \cdot 10^{-45} \tiny \text{1 00000000 00000000000000000000001}
\tiny \text{+0} \tiny 0,0 \tiny \text{0 00000000 00000000000000000000000}
\tiny \text{-0} \tiny -0,0 \tiny \text{1 00000000 00000000000000000000000}
\tiny +\infty \tiny +\infty \tiny \text{0 11111111 00000000000000000000000}
\tiny -\infty \tiny -\infty \tiny \text{1 11111111 00000000000000000000000}
\tiny \text{NaN} \tiny NaN \tiny \text{(0 }\acute{o}\text{ 1) 11111111 (alg}\acute{u}\text{n 1)}

Conversiones

Ejemplo: convertir el 3737 a formato simple (32 bits)

Es positivo, por tanto el signo es 0

Número Cociente Resto
\frac{3737}{2} 1868 1
\frac{1868}{2} 934 0
\frac{934}{2} 467 0
\frac{467}{2} 233 1
\frac{233}{2} 116 1
\frac{116}{2} 58 0
\frac{58}{2} 29 0
\frac{29}{2} 14 1
\frac{14}{2} 7 0
\frac{7}{2} 3 1
\frac{3}{2} 1 1

Entonces tenemos que la parte binaria es:

3737_{(10} = 111010011001_{(2}

Para el exponente vamos a necesitar mover 12 cifras decimales, por tanto debemos hacer 127 + 11 = 138 (sumamos 11 porque el bit escondido no se cuenta)

Número Cociente Resto
\frac{138}{2} 69 0
\frac{69}{2} 34 1
\frac{34}{2} 17 0
\frac{17}{2} 8 1
\frac{8}{2} 4 0
\frac{4}{2} 2 0
\frac{2}{2} 1 0

Entonces tenemos que el exponente es:

138_{(10} = 10001010_{(2}

Entonces tenemos que:

3737_{(10} = \text{0 10001010 11010011001000000000000}_{(2}

Formato doble (64 bits)

En el formato simple se utiliza el siguiente formato para almacenar dos palabras (64 bits):

Bit de signo Exponente Mantisa
1 bit 11 bits 52 bits

Dado un E_1=\text{ exponente } + 1023 (1023 es el máximo número positivo del exponente) tenemos que:

00000000000_{(2}\leq E_1\leq 11111111111_{(2}

Si denotamos (E1)_{(10} a la conversión decimal de E_1, tenemos que:

0\leq (E1)_{(10}\leq 2^{10}+2^9+2^8+2^7+2^6+2^5+2^4+2^3+2^2+2^1+2^0=2047

O lo que seria lo mismo:

-1023\leq (E_1)_{(10} -1023\leq 1024

Si denotamos \alpha=(E_1)_{(10} -1023 tenemos que:

-1023\leq\alpha\leq 1024
(E_1)=\alpha+1023

Denotamos s como el bit de signo y M como la mantisa. A raíz de esto, surgen dos tipos de números:

  • Números normales
    -1023 < \alpha < 1024

    Conversión a número normal: (-1)\cdot s \cdot 1,M \cdot 2^\alpha

  • Números subnormales
    \alpha = (-1023)

    Conversión a número subnormal: (-1)\cdot s \cdot 0,M \cdot 2^{-1022}

  • \alpha = 1024

    Da lugar a excepciones del tipo +\infty, -\infty\text{ y NaN} (no es un número, Not a Number del inglés)

Se utiliza un bit escondido (hidden bit del inglés) en la mantisa. Se toma el primer dígito que siempre es a_1 = 1. Este bit escondido no hará falta almacenarlo, consiguiendo así unos cuantos números más

Número Decimal Binario
\tiny \text{Máximo número}\\ \text{normal positivo} \tiny 1,7976931 \cdot 10^{308} \tiny \text{0 11111111110 1111111111111111111111111111111111111111111111111111}
\tiny \text{Máximo número}\\ \text{normal negativo} \tiny -1,7976931 \cdot 10^{308} \tiny \text{1 11111111110 1111111111111111111111111111111111111111111111111111}
\tiny \text{Mínimo número}\\ \text{normal positivo} \tiny 2,2250738 \cdot 10^{-308} \tiny \text{0 00000000001 0000000000000000000000000000000000000000000000000000}
\tiny \text{Mínimo número}\\ \text{normal negativo} \tiny -2,2250738 \cdot 10^{-308} \tiny \text{1 00000000001 0000000000000000000000000000000000000000000000000000}
\tiny \text{Máximo número}\\ \text{subnormal positivo} \tiny 2,2250738 \cdot 10^{-308} \tiny \text{0 00000000000 1111111111111111111111111111111111111111111111111111}
\tiny \text{Máximo número}\\ \text{subnormal negativo} \tiny -2,2250738 \cdot 10^{-308} \tiny \text{1 00000000000 1111111111111111111111111111111111111111111111111111}
\tiny \text{Mínimo número}\\ \text{subnormal positivo} \tiny 4,9406564 \cdot 10^{-324} \tiny \text{0 00000000000 0000000000000000000000000000000000000000000000000001}
\tiny \text{Mínimo número}\\ \text{subnormal negativo} \tiny -4,9406564 \cdot 10^{-324} \tiny \text{1 00000000000 0000000000000000000000000000000000000000000000000001}
\tiny +0 \tiny 0,0 \tiny \text{0 00000000000 0000000000000000000000000000000000000000000000000000}
\tiny -0 \tiny -0,0 \tiny \text{1 00000000000 0000000000000000000000000000000000000000000000000000}
\tiny +\infty \tiny +\infty \tiny \text{0 11111111111 0000000000000000000000000000000000000000000000000000}
\tiny -\infty \tiny -\infty \tiny \text{1 11111111111 0000000000000000000000000000000000000000000000000000}
\tiny \text{NaN} \tiny \text{NaN} \tiny \text{(0 }\acute{o}\text{ 1) 11111111111 (alg}\acute{u}\text{n 1)}

Conversiones

Ejemplo: convertir el 3737 a formato doble (64 bits)

Es positivo, por tanto el signo es 0

Número Cociente Resto
\frac{3737}{2} 1868 1
\frac{1868}{2} 934 0
\frac{934}{2} 467 0
\frac{467}{2} 233 1
\frac{233}{2} 116 1
\frac{116}{2} 58 0
\frac{58}{2} 29 0
\frac{29}{2} 14 1
\frac{14}{2} 7 0
\frac{7}{2} 3 1
\frac{3}{2} 1 1

Entonces tenemos que la parte binaria es:

3737_{(10} = 111010011001_{(2}

Para el exponente vamos a necesitar mover 12 cifras decimales, por tanto debemos hacer 1023 + 11 = 1034 (sumamos 11 porque el bit escondido no se cuenta)

Número Cociente Resto
\frac{1034}{2} 517 0
\frac{517}{2} 258 1
\frac{258}{2} 129 0
\frac{129}{2} 64 1
\frac{64}{2} 32 0
\frac{32}{2} 16 0
\frac{16}{2} 8 0
\frac{8}{2} 4 0
\frac{4}{2} 2 0
\frac{2}{2} 1 0

Entonces tenemos que el exponente es:

138_{(10} = 10000001010_{(2}

Entonces tenemos que:

\tiny 3737_{(10} = \text{0 10000001010 1101001100100000000000000000000000000000000000000000}_{(2}

Álgebra de Boole

Álgebra de Boole

El álgebra de Boole es una disciplina que analiza los circuitos digitales y otros sistemas digitales

Recibe su nombre en honor al matemático inglés George Boole, que propuso los principios básicos de este álgebra en 1854 en su tratado An investigation of the laws of thought on wich to found the mathematical theories of logic and probabilities

En 1938, Claude Shannon, un investigador asistente en el Departamento de Ingeniería Eléctrica del M.I.T., sugirió que el álgebra de Boole podría usarse para resolver problemas de circuitos de conmutación

Las técnicas de Shannon se usaron, consecuentemente en el análisis y diseño de circuitos digitales. El álgebra de Boole resulta una herramienta útil en dos áreas:

  • Análisis
    Es una forma concisa de descubrir el funcionamiento de los circuitos digitales
  • Diseño
    Dada una función deseada, se puede aplicar el álgebra de Boole para desarrollar una implementación de complejidad simplificada de esa función

El álgebra de Boole usa variables y operaciones lógicas. Una variable puede tomar el valor 1 cuando es verdadero ó 0 cuando es falso. Tiene únicamente tres operaciones lógicas básicas (AND, OR y NOT), que se representan simbólicamente:

AND OR NOT
A AND B A OR B NOT A
A\wedge B A\vee B \neg A

Tablas de verdad

La tabla de verdad define las operaciones lógicas básicas, enumerando el valor para cada combinación posible de los valores de los operandos. Además de los operadores básicos del álgebra de Boole, también se suelen enumerar tres operadores útiles: XOR, XNOR, NAND y NOR. Los cuales se pueden obtener haciendo operaciones con los operadores básicos

Tabla AND

La operación AND es verdadera si y sólo si los dos operandos son verdaderos

A B A\wedge B
0 0 0
0 1 0
1 0 0
1 1 1

Tabla OR

La operación OR es verdadera si y sólo si los uno o ambos operandos son verdaderos

A B A\vee B
0 0 0
0 1 1
1 0 1
1 1 1

Tabla NOT

La operación NOT invierte el valor del operando

A \neg A
0 1
1 0

Tabla XOR

La operación XOR es verdadera si y sólo uno de los operandos es verdadero

Equivale a realizar:

(A \wedge \neg B) \vee (\neg A \wedge B) \equiv (A \vee B) \wedge (\neg A \vee \neg B)

A B A\oplus B
0 0 0
0 1 1
1 0 1
1 1 0

Tabla XNOR

La operación XNOR es la negación de la operación XOR

Equivale a realizar:

(A \wedge B) \vee (\neg A \wedge \neg B)

A B \neg(A\oplus B)
0 0 1
0 1 0
1 0 0
1 1 1

Tabla NAND

La operación NAND es la negación de la operación AND

Equivale a realizar:

\neg(A \wedge B)

A B \neg(A \wedge B)
0 0 1
0 1 1
1 0 1
1 1 0

Tabla NOR

La operación NOR es la negación de la operación OR

Equivale a realizar:

\neg(A \vee B)

A B \neg(A \vee B)
0 0 1
0 1 0
1 0 0
1 1 0

Identidades básicas

Hay dos clases de identidades:

  • Reglas básicas (postulados)
    Se afirman sin demostración
  • Otras identidades
    Se pueden derivar de los postulados básicos

Los postulados definen la manera en la que las expresiones booleanas se interpretan

Reglas básicas
A \wedge B = B \wedge A A \vee B = B \vee A Ley conmutativa
A \wedge (B \vee C) = (A \wedge B) \vee (A \wedge C) A \vee (B \wedge C) = (A \vee B) \wedge (A \vee C) Ley distributiva
1 \wedge A = A 0 \vee A = A Elemento neutro
A \wedge \neg A = 0 A \vee \neg A = 1 Elemento complementario
Otras identidades
0 \wedge A = 0 1 \vee A = 1
A \wedge A = A A \vee A = A
A \wedge (B \wedge C) = (A \wedge B) \wedge C A \vee (B \vee C) = (A \vee B) \vee C Ley asociativa
\neg (A \wedge B) = \neg A \vee \neg B \neg (A \vee B) = \neg A \wedge \neg B Teorema de Morgan

Qubits

Qubits

Un qubits es un sistema cuántico con dos estados propios y que puede ser manipulado arbitrariamente

Solo puede ser descrito correctamente mediante la mecánica cuántica, y solamente tiene dos estados bien distinguibles mediante medidas físicas

También se entiende por qubits la información que contiene ese sistema cuántico de dos estados posibles

En esta acepción, el qubits es la unidad mínima y por lo tanto constitutiva de la teoría de la información cuántica

Es un concepto fundamental para la programación cuántica y para la criptografía cuántica, el análogo cuántico del bit en informática

Estos qubits ya no toman simplemente valores enteros (0 ó 1)

Sino que ahora son representados por entidades matemáticas llamadas vectores de estado |\psi\succ

Que vamos a representar usando la notación de Dirac:

\begin{matrix} |0\succ&=\binom{1}{0}\\ |1\succ&=\binom{0}{1} \end{matrix}

Que define los estados base de un qubit

Como vector, el estado |\psi\succ de cada qubit pertenece a un espacio vectorial particular llamado espacio de Hilbert

Físicamente, podemos medir el estado |\psi\succ en dos estados básicos ortogonales, que por convención se llaman |0\succ y |1\succ

Esto implica que el espacio de Hilbert es de 2 dimensiones

Por lo que se pueden elegir los vectores \left \{ |0\succ, 1\succ \right \} como base del espacio vectorial

De esta forma, cualquier vector de estado |\psi\succ de un qubit es una combinación lineal de los vectores base (que en el lenguaje de la mecánica cuántica se llama estado de superposición cuántica)

|\psi\succ=\alpha|0\succ+\beta|1\succ

Que define la combinación lineal de los estados base de un qubit

El espacio de Hilbert de cada qubit es un espacio complejo

Esto quiere decir que \alpha y \beta son números complejos

Además, no pueden tomar cualquier valor

Deben cumplir que:

\left\|\alpha\right\|^{2}+\left\|\beta\right\|^{2}=1

Es decir, que el vector de estado de un qubit |\psi\succ está normalizado, (su norma es igual a 1)

Puertas cuánticas

Las puertas cuánticas son transformaciones lineales entre los vectores de estado |\psi\succ

Pero no sirve realizar cualquier transformación lineal

Sólo pueden ser consideradas las transformaciones que no cambien la norma del vector |\psi\succ

Aquellas que tomen un vector cuya norma sea 1 y lo conviertan en otro vector de norma igual a 1

Este tipo de transformaciones se llaman Transformaciones unitarias, o en el lenguaje de la mecánica cuántica, Operadores Unitarios

Por lo tanto, las puertas cuánticas son operadores unitarios

Los operadores unitarios pueden ser representados como matrices

La aplicación de un operador unitario A a un vector de estado |b\succ, puede ser representada como una multiplicación de una matriz de 2x2 por un vector columna, dando como resultado otro vector columna

\begin{pmatrix} A_{11} & A_{12} \\ A_{21} & A_{22} \end{pmatrix} \cdot \begin{pmatrix} b_{1}\\ b_{2} \end{pmatrix} = \begin{pmatrix} c_{1}\\ c_{2} \end{pmatrix}

Puertas cuánticas de un qubit en Qiskit

Qiskit es una herramienta creada por IBM para desarrollar software para procesadores cuánticos

Está implementado en el lenguaje de programación Python, y disponible para que el público en general para empezar a experimentar y probar nuestros algoritmos

A continuación voy a representar las puertas cuánticas más utilizadas que se aplican a un qubit, así como su representación matricial y su forma de implementarla en Qiskit

Para saber como instalar Qiskit en tu ordenador, puedes revisarlo en su documentación

Puerta Identidad

La puerta identidad representa a la matriz identidad y se llama así porque representa a la aplicación identidad que va de un espacio vectorial de dimensión finita a sí misma

I=\begin{pmatrix} 1 & 0 \\ 0 & 1 \end{pmatrix}

Y cuya representación en notación de Dirac es:

\begin{matrix} I|0\succ=|0\succ\\ I|1\succ=|1\succ \end{matrix}

Código Qiskit de la puerta identidad:

Matrices de Pauli

Las matrices de Pauli, deben su nombre a Wolfgang Ernst Pauli

Son matrices usadas en física cuántica en el contexto del momento angular intrínseco o espín

Matemáticamente, las matrices de Pauli constituyen una base vectorial del álgebra de Lie del grupo especial unitario SU\left(2\right), actuando sobre la representación de dimensión 2

Puerta X (matriz X de Pauli)

I=\begin{pmatrix} 0 & 1 \\ 1 & 0 \end{pmatrix}

Y cuya representación en notación de Dirac es:

\begin{matrix} I|0\succ=|1\succ\\ I|1\succ=|0\succ \end{matrix}

Código Qiskit de la puerta X:

Puerta Y (matriz Y de Pauli)

I=\begin{pmatrix} 0 & -i \\ i & 0 \end{pmatrix}

Y cuya representación en notación de Dirac es:

\begin{matrix} I|0\succ=i|1\succ\\ I|1\succ=-i|0\succ \end{matrix}

Código Qiskit de la puerta Y:

Puerta Z (matriz Z de Pauli)

I=\begin{pmatrix} 1 & 0 \\ 0 & -1 \end{pmatrix}

Y cuya representación en notación de Dirac es:

\begin{matrix} I|0\succ=|0\succ\\ I|1\succ=|-1\succ \end{matrix}

Código Qiskit de la puerta Z:

Puerta Hadamard

La puerta de Hadamard, deben su nombre a Jacques Salomon Hadamard

No son más que la representación de un qubit de la transformada cuántica de Fourier

Como las filas de la matriz son ortogonales, dónde {\displaystyle H} es una matriz unitaria

H=\frac{1}{\sqrt{2}}\cdot \begin{pmatrix} 1 & 1 \\ 1 & -1 \end{pmatrix}

Y cuya representación en notación de Dirac es:

\begin{matrix} H|0\succ=\frac{1}{\sqrt{2}}\cdot \left(|0\succ+|1\succ\right)\\ H|1\succ=\frac{1}{\sqrt{2}}\cdot \left(|0\succ-|1\succ\right) \end{matrix}

Código Qiskit de la puerta H:

Puertas U (Universales)

En versiones anteriores de qiskit existían las denominadas puertas U1, U2 y U3

Pero estas puertas han desaparecido en versiones posteriores de qiskit

Se pueden construir con puertas P y U mediante las siguientes equivalencias:

\left\{\begin{matrix} U_{1}\left(\lambda\right)=P\left(\lambda\right)\\ U_{2}\left(\Phi,\lambda\right)=U\left(\Phi,\lambda,\frac{\pi}{2}\right)\\ U_{3}\left(\theta,\Phi,\lambda\right)=U\left(\theta,\Phi,\lambda\right) \end{matrix}\right.

Se define como

U\left(\theta,\Phi,\lambda\right)= \begin{pmatrix} \cos{\frac{\theta}{2}} & -\exp^{i\cdot\lambda}\cdot\sin{\frac{\theta}{2}} \\ \exp^{i\cdot\Phi}\cdot\sin{\frac{\theta}{2}} & \exp^{i\cdot\left(\Phi+\lambda\right)}\cdot\cos{\frac{\theta}{2}} \end{pmatrix}

Hay dos casos específicos en los que obtenemos las siguientes equivalencias:

\left\{\begin{matrix} H=U\left(\frac{\pi}{2},0,\pi\right)= \frac{1}{\sqrt{2}}\cdot \begin{pmatrix} 1 & 1 \\ 1 & -1 \end{pmatrix}\\ P=U\left(0,0,\lambda\right)= \begin{pmatrix} 1 & 0 \\ 0 & \exp^{i\cdot\lambda} \end{pmatrix} \end{matrix}\right.

Puerta P

P\left(\Phi\right)= \begin{pmatrix} 1 & 0 \\ 0 & \exp^{i\cdot\Phi} \end{pmatrix}

Código Qiskit de la puerta P:

Puerta U1

U_{1}\left(\lambda\right)= \begin{pmatrix} 1 & 0 \\ 0 & \exp^{i\cdot\lambda} \end{pmatrix} =P\left(\lambda\right)

Código Qiskit de la puerta U1 en versiones anteriores:

Puerta U2

U_{2}\left(\Phi,\lambda\right)= \frac{1}{\sqrt{2}}\cdot\begin{pmatrix} 1 & -\exp^{i\cdot\lambda} \\ \exp^{i\cdot\Phi} & \exp^{i\cdot\left(\Phi+\lambda\right)} \end{pmatrix} =U\left(\Phi,\lambda,\frac{\pi}{2}\right)

Código Qiskit de la puerta U2 en versiones anteriores:

Puerta U3

U_{3}\left(\theta,\Phi,\lambda\right)= \begin{pmatrix} \cos{\frac{\theta}{2}} & -\exp^{i\cdot\lambda}\cdot\sin{\frac{\theta}{2}} \\ \exp^{i\cdot\Phi}\cdot\sin{\frac{\theta}{2}} & \exp^{i\cdot\left(\Phi+\lambda\right)}\cdot\cos{\frac{\theta}{2}} \end{pmatrix} =U\left(\theta,\Phi,\lambda\right)

Código Qiskit de la puerta U3 en versiones anteriores:

Puerta S

Da un cuarto de vuelta alrededor de la esfera de Bloch

Se define como \Phi =\frac{\pi}{2} y por esa razón es equivalente a una puerta U_{1}\left(\frac{\pi}{2}\right)

S= \begin{pmatrix} 1 & 0 \\ 0 & \exp^{i\cdot\frac{\pi}{2}} \end{pmatrix} = U_{1}\left(\frac{\pi}{2}\right)

Y cuya representación en notación de Dirac es:

SS|q\succ=\mathbb{Z}|q\succ

Código Qiskit de la puerta S:

Puerta S

Surge a partir de una puerta S negativa

Se define como \Phi =-\frac{\pi}{2} y por esa razón es equivalente a una puerta U_{1}\left(\frac{-pi}{2}\right)

S= \begin{pmatrix} 1 & 0 \\ 0 & \exp^{-i\cdot\frac{\pi}{2}} \end{pmatrix} = U_{1}\left(\frac{-pi}{2}\right)

Código Qiskit de la puerta S:

Puerta T

Es similar a la puerta S y también es conocida como la puerta \sqrt[4]{\mathbb{Z}}

Se define como \Phi =\frac{\pi}{4} y por esa razón es equivalente a una puerta U_{1}\left(\frac{\pi}{4}\right)

T= \begin{pmatrix} 1 & 0 \\ 0 & \exp^{i\cdot\frac{\pi}{4}} \end{pmatrix} = U_{1}\cdot\left(\frac{\pi}{4}\right)

Código Qiskit de la puerta T:

Puerta T

Surge a partir de una puerta T negativa

Se define como \Phi =-\frac{\pi}{4} y por esa razón es equivalente a una puerta U_{1}\left(\frac{-\pi}{4}\right)

T= \begin{pmatrix} 1 & 0 \\ 0 & \exp^{i\cdot\frac{\pi}{4}} \end{pmatrix} = U_{1}\cdot\left(\frac{-\pi}{4}\right)

Código Qiskit de la puerta T:

Puertas de rotación estándar

Estas puertas representan un tipo particular de rotación, derivadas de las matrices de Pauli

De manera general se definen como:

R_{p}\left(\theta\right)=\exp\left(-\frac{i\cdot\theta}{2}\right)=\cos\left(\frac{\theta}{2}\right)\cdot I-i\cdot \sin\left(\frac{\theta}{2}\right)\cdot P

Puerta Rx (Rotación estándar alrededor del eje-x)

La Puerta Rx es equivalente a U\left(\theta,\frac{-\pi}{2},\frac{\pi}{2}\right)

R_{x}\left(\theta\right)= \begin{pmatrix} \cos\left(\frac{\theta}{2}\right) & -i\cdot\sin\left(\frac{\theta}{2}\right) \\ -i\cdot\sin\left(\frac{\theta}{2}\right) & \cos\left(\frac{\theta}{2}\right) \end{pmatrix} = U\left(\theta,\frac{-\pi}{2},\frac{\pi}{2}\right)

Código Qiskit de la puerta Rx:

Puerta Ry (Rotación estándar alrededor del eje-y)

La Puerta Ry es equivalente a U\left(\theta,0,0\right)

R_{y}\left(\theta\right)= \begin{pmatrix} \cos\left(\frac{\theta}{2}\right) & -\sin\left(\frac{\theta}{2}\right) \\ \sin\left(\frac{\theta}{2}\right) & \cos\left(\frac{\theta}{2}\right) \end{pmatrix} = U\left(\theta,0,0\right)

Código Qiskit de la puerta Ry:

Puerta Rz (Rotación estándar alrededor del eje-z)

La Puerta Rz es equivalente a P\left(\phi\right)

R_{z}\left(\phi\right)= \begin{pmatrix} \exp^{-i\cdot \frac{\phi}{2}} & 0 \\ 0 & \exp^{i\cdot \frac{\phi}{2}}\end{pmatrix} = P\left(\phi\right)

Código Qiskit de la puerta Rz:

Lenguaje de programación

Lenguaje de programación

Un lenguaje de programación puede ser cualquier lenguaje artificial que pueda utilizarse para definir una secuencia de instrucciones para su procesamiento en una máquina (maquinaria industrial, un ordenador, una tablet, un móvil)

Se asume generalmente que la traducción de las instrucciones a un código que comprende la máquina debe ser completamente sistemática. Normalmente es la máquina quien realiza la traducción

Lenguaje de bajo nivel

A muy bajo nivel, los microprocesadores procesan exclusivamente señales electrónicas binarias. Dar una instrucción a un microprocesador supone en realidad enviar series de unos y ceros espaciados en el tiempo de una forma determinada. Esta secuencia de señales se denomina código máquina

El código representa normalmente datos e instrucciones para manipularlos. Un modo más fácil de comprender el código máquina es dando a cada instrucción un mnemónico, como por ejemplo STORE, ADD o JUMP. Esta abstracción da como resultado el ensamblador, un lenguaje de muy bajo nivel que es específico de cada microprocesador

Los lenguajes de bajo nivel permiten crear programas muy rápidos, pero que son difíciles de comprender. Lo más importante es el hecho de que los programas escritos en bajo nivel son prácticamente específicos para cada procesador. Si se quiere ejecutar el programa en otra máquina con otra tecnología, será necesario reescribir el programa desde cero

Lenguaje de alto nivel

Por lo general se piensa que las máquinas realizan tareas de cálculos o procesamiento de textos. La descripción anterior es sólo una forma muy esquemática de ver como trabajan. Existe un alto nivel de abstracción entre lo que se le pide a la máquina y lo que realmente comprende. Existe también una relación compleja entre los lenguajes de alto nivel y el código máquina

Los lenguajes de alto nivel son más fáciles de comprender que el código máquina porque están formados por elementos de lenguajes naturales, como el inglés. En BASIC (uno de los lenguajes de alto nivel más conocidos por su sencillez de aprendizaje), los comandos como ‘IF CONTADOR = 10 THEN STOP’ pueden utilizarse para pedir a la máquina que pare si la variable CONTADOR es igual a 10. Por desgracia para muchas personas esta forma de trabajar es un poco frustrante, dado que a pesar de que las máquinas parecen comprender un lenguaje natural, lo hacen en realidad de una forma rígida y sistemática

Interpretes y compiladores

La traducción de una serie de instrucciones en lenguaje ensamblador (el código fuente) a un código máquina (o código objeto) no es un proceso muy complicado y lo realiza normalmente un programa especial llamado compilador. La traducción de un código fuente de alto nivel a un código máquina también se realiza con un compilador, en este caso este programa será más complejo, o mediante un intérprete

Un compilador crea una lista de instrucciones de código máquina, el código objeto, basándose en un código fuente. El código objeto resultante es un programa ejecutable que ya puede funcionar en la máquina, pero que puede hacer que se bloquee si no está bien diseñado

Los intérpretes, por otro lado, son más lentos que los compiladores ya que no producen un código objeto, sino que recorren el código fuente una línea cada vez. Cada línea se traduce a código máquina y se ejecuta. Cuando la línea se lee por segunda vez, como en el caso de los programas en que se reutilizan partes del código, debe compilarse de nuevo. Aunque este proceso es más lento, es menos susceptible de provocar bloqueos indeseados en la máquina

Ensamblador

Ensamblador

El lenguaje ensamblador es un lenguaje de bajo nivel cuyas instrucciones se suelen corresponder una a una con las instrucciones del ordenador, y con la posibilidad de poder definir, por ejemplo, macroinstrucciones

Este lenguaje es totalmente dependiente del modelo de procesador

Para poder estudiar este lenguaje con un microprocesador real se ha elegido el 8086, ya que es uno de los más utilizados en la actualidad en ordenadores de tipo PC

La principal característica de ese microprocesador es que es capaz de trabajar con operandos de 16 bits

Los ordenadores de tipo PC usan las operaciones básicas en 16 bits del 8086 y si el procesador es de 32 bits se le añaden un repertorio nuevo de operaciones en 32 bits. Si es de 64 bits entonces el repertorio de operaciones incluidas son de 16 bits, de 32 bits y un nuevo repertorio de 64 bits

Arquitectura básica del 8086

La arquitectura interna del 8086 se compone de dos partes diferenciadas: la Unidad de Ejecución y la Unidad de Interfaz con el bus

La tarea principal de la Unidad de Ejecución es ejecutar las instrucciones que extrae de la cola de espera, a donde llegan procedentes de la MP (Memoria Principal)

El trabajo principal de la Unidad de Interfaz con el bus es buscar y traer las instrucciones de la MP. Para ello tendrá que generar la dirección de la instrucción a ejecutar

Registros generales o de datos

Hay 4 registros de 16 bits y cada uno tiene una utilidad concreta:

  • AX
    Registro acumulador, se utiliza con las operaciones aritméticas
  • BX
    Registro de base, se utiliza para acceder a vectores, tablas, etc
    Mediante el uso de una dirección base que indica cual es el primer elemento y una dirección de desplazamiento que es el valor que se le suma a la dirección base para poder alcanzar el elemento deseado
  • CX
    Registro contador, se utiliza para contar en bucles e instrucciones de tipo repetitivo
  • DX
    Registro de datos, tiene dos usos particulares

    1. Complementar al registro AX en las operaciones aritméticas multiplicación y división
    2. Contiene direcciones de puerto para instrucciones de entrada / salida

Estos 4 registros tiene la siguiente propiedad común, aunque son de 16 bits, se pueden considerar cada uno de ellos como 2 registros independientes de 8 bits. De este modo podemos designar los bits más altos o significativos como Hight (al registro se le renombra con H al final: AH, BH, CH, DH) y los más bajos o menos significativos como Lower (al registro se le renombra con L al final: AL, BL, CL, DL)

Registros de segmento: Segmentación

Hay 4 registros de 16 bits y cada uno tiene una utilidad concreta:

  • CS
    Segmento de código, es el que define la zona de memoria donde se encuentran las instrucciones a ejecutar o de programa
  • DS
    Segmento de datos, es el que define la zona donde se encuentran los datos que van a ser usados en el programa
  • SS
    Segmento de stack o pila, define la zona de memoria que se va a utilizar como una pila
  • ES
    Segmento extra, como su nombre indica contiene la dirección del segmento extra, que se utiliza cuando se sobrepasa la capacidad de 64 kbytes del segmento de datos y para realizar determinadas transferencias de datos entre segmentos

Bus de datos: lineas por las que se transmiten los datos

Anchura del bus de datos: número de lineas eléctricas del bus por las que se transmiten los datos, en el 8086 son de 16 bits

Bus de direcciones: lineas por las que se transmiten las direcciones

Anchura del bus de direcciones: número de lineas eléctricas del bus por las que se transmiten las direcciones, en el 8086 son de 16 bits

Por tanto, las direcciones deberían ser de 16 bits, sin embargo, en el 8086 son de 20 bits. Esto es debido a que el número de direcciones distintas sería 2^{16}=64K, pero como son muy pocas, nos interesa que sean de 20 bits, ya que 2^{10}=1M

Para calcular la dirección física necesitamos un segmento y un desplazamiento, usando siempre valores en hexadecimal, con lo que tendremos un primer registro de 16 bits al que se añadirá un 0 a su derecha y un segundo registro de 16 bits

Como notación se usa Segmento:Desplazamiento

El cálculo de la dirección física se realizará:
Segmento x 10(h) + Desplazamiento

Ejemplos de Segmento:Desplazamiento

  • 0000:1050\Rightarrow 0000\cdot 10+1050=0150
  • 0010:0F50\Rightarrow 0010\cdot 10+0F50=0150
  • 0100:0050\Rightarrow 0100\cdot 10+0050=0150
  • 0105:0000\Rightarrow 0105\cdot 10+0000=0150

Como puede apreciarse en los ejemplos, distintas combinaciones de segmentos y desplazamientos pueden darnos la misma dirección física. Esta situación no es un error, es debido a que las direcciones de los segmentos se solapan entre sí

Podemos tener tantos números de segmentos distintos como combinaciones distintas puedan hacerse con la dirección base de segmento. Como tiene 16 bits entonces tenemos 2^{16} combinaciones por lo que tenemos 64\cdot K direcciones distintas

Podemos tener tantos números de direcciones distintas en cada segmento como combinaciones distintas puedan hacerse con el desplazamiento. Como tiene 16 bits entonces tenemos 2^{16} combinaciones por lo que tenemos 64\cdot K direcciones distintas

Se podría pensar que como tenemos 64\cdot K segmentos y 64\cdot K direcciones, tendríamos 64\cdot 64=2G direcciones físicas. Sin embargo, como las direcciones están solapadas este número de direcciones es incorrecto

Las direcciones válidas de comienzo de segmento tienen la propiedad de acabar en 0. Por tanto, ya que en hexadecimal son 10, al pasar de hexadecimal a decimal obtenemos que el número de direcciones es 16

SQL

SQL

Al gestionar bases de datos el modelo de datos más utilizado es el modelo relacional y para comunicarse con el gestor se puede utilizar el lenguaje SQL

NO es un lenguaje de programación, sino un lenguaje de gestión de bases de datos que presenta las siguientes características:

  • LDD (Lenguaje de definición de datos)

    El LDD de SQL proporciona comandos para la definición de esquemas de relación, borrado de relaciones y modificación de los esquemas de relación

  • LMD (Lenguaje interactivo de manipulación de datos)

    El LMD de SQL incluye un lenguaje de consultas basado tanto en el álgebra relacional como en el cálculo relacional de tuplas. También incluye comandos para insertar, borrar y modificar tuplas

  • Integridad

    El LDD incluye comandos para especificar restricciones de integridad que deben cumplir los datos almacenados en la base de datos. Las actualizaciones que violan las restricciones de integridad se rechazan

  • Definición de vistas

    El LDD de SQL incluye comandos para la definición de vistas

  • Control de transacciones

    SQL incluye comandos para especificar el comienzo y el final de transacciones

  • SQL incorporado y SQL dinámico

    SQL incorporado y SQL dinámico define cómo se pueden incorporar las instrucciones de SQL en lenguajes de programación de propósito general como C, C++, Java, PL/L, Cobol, Pascal o Fortran, entre otros

  • Autorización
    El LDD de SQL incluye comandos para especificar los derechos de acceso a las relaciones y a las vistas

Evolución del SQL

IBM desarrolló la versión original de SQL, denominado Sequel, como parte del proyecto System R a principios de 1970 por el grupo de San José, California

El lenguaje Sequel ha evolucionado desde entonces y su nombre ha pasado a ser SQL (lenguaje estructurado de consultas, Structured Query Language)

Hoy en día, muchos lenguajes de programación son compatibles con el lenguaje SQL y se ha establecido como el lenguaje estándar para el uso de bases de datos relacionales

1981, IBM lanzó el primer programa comercial basado en SQL

1986, ANSI (Instituto nacional americano de normalización, American National Standards Institute) publicó una norma SQL, denominada SQL-86 o SQL1 y fue confirmada por ISO (Organización internacional de normalización, International Standards Organization) en 1987

1989, ANSI publicó una extensión de la norma para SQL denominada SQL-89

1992, apareció una nueva versión de la norma denominada SQL-92 o SQL2

1999, apareció una nueva versión denominada SQL:1999 o SQL2000. En la cual se agregaron expresiones regulares, consultas recursivas (para relaciones jerárquicas), triggers y algunas características orientadas a objetos

2003, apareció una nueva versión denominada SQL:2003. En la cual se agregaron algunas características de XML, cambios en las funciones, estandarización del objeto sequence y de las columnas autonuméricas

2005, apareció una nueva versión denominada SQL:2005 y se corresponde con la norma ISO/IEC 9075-14:2005. Definiendo cómo SQL puede utilizarse conjuntamente con XML:

  • Importar y guardar datos XML en una base de datos SQL, manipulándolos dentro de la base de datos y publicando el XML y los datos SQL convencionales en forma XML
  • Facilidades que permiten a las aplicaciones integrar dentro de su código SQL el uso de XQuery, lenguaje de consulta XML publicado por el W3C (World Wide Web Consortium) para acceso concurrente a datos ordinarios SQL y documentos XML

2008, apareció una nueva versión denominada SQL:2008. En la cual se agregó el uso de la cláusula ORDER BY fuera de las definiciones de los cursores. Incluyendo disparadores del tipo INSTEAD OF. Y la inclusión de la sentencia TRUNCATE

2011, apareció una nueva versión denominada SQL:2011. En la cual se agregaron los datos temporales (PERIOD FOR) y mejoras en las funciones de ventana y de la cláusula FETCH

2016, apareció una nueva versión denominada SQL:2016. En la cual se agregó la búsqueda mediante patrones, funciones de tabla polimórficas y compatibilidad con los ficheros JSON

LDD

Lenguaje de definición de datos (LDD)

El lenguaje de definición de datos (LDD), es el que se encarga de la modificación de la estructura de los objetos de la base de datos

Incluye órdenes para modificar, borrar o definir las relaciones (tablas) en las que se almacenan los datos de la base de datos

Existen cuatro operaciones básicas:

Definición de los datos

El conjunto de relaciones de cada base de datos debe especificarse en el sistema en términos de un lenguaje de definición de datos (LDD)

El LDD de SQL no sólo permite la especificación de un conjunto de relaciones, sino también de la información relativa a esas relaciones, incluyendo:

  • El esquema de cada relación
  • El dominio de valores asociado a cada atributo
  • Las restricciones de integridad
  • El conjunto de índices que se deben mantener para cada relación
  • La información de seguridad y de autorización de cada relación
  • La estructura de almacenamiento físico de cada relación en el disco

Tipos básicos de dominios

La norma SQL soporta gran variedad de tipos de dominio predefinidos:

  • CHAR(n)

    Una cadena de caracteres de longitud fija, con una longitud n especificada por el usuario. También se puede utilizar la palabra completa character

  • VARCHAR(n)

    Una cadena de caracteres de longitud variable con una longitud máxima n especificada por el usuario. La forma completa, character varying, es equivalente

  • INT

    Un entero (un subconjunto finito de los enteros dependiente del ordenador). La palabra completa, integer, es equivalente

  • SMALLINT

    Un entero pequeño (un subconjunto dependiente del ordenador del tipo de dominio entero)

  • NUMERIC(p, d)

    Un número en coma fija, cuya precisión la especifica el usuario. El número está formado por p dígitos (más el signo) y de esos p dígitos, d pertenece a la parte decimal

  • DOUBLE

    Un número en coma flotante y números en coma flotante de doble precisión, con precisión dependiente del ordenador

  • FLOAT(n)

    Un número en coma flotante cuya precisión es, al menos, de n dígitos

  • DATE

    Dato de tipo fecha, con una precisión de hasta segundo

Definición básica de esquemas

CREATE TABLE

Las relaciones se definen mediante el comando CREATE TABLE:

\text{CREATE TABLE r} (\\ A_1 D_1, \cdots, A_n D_n,\\ \{rest-integridad_1\}, \cdots, \{rest-integridad_k\} )

Donde r es el nombre de relación, cada Ai es el nombre de un atributo del esquema de la relación r y Di es el tipo de dominio de los valores del dominio del atributo Ai

Hay varias restricciónes de integridad válidas

Una de las más usadas es la de clave primaria (primary key), que adopta la siguiente forma:

\text{primary key}(A_{j1}, \cdots, A_{jm})

La especificación de clave primaria determina los atributos A_{j1}, \cdots, A_{jm} forman la clave primaria de la relación

Los atributos de la clave primaria tienen que ser no nulos y únicos; es decir, ninguna tupla puede tener un valor nulo para un atributo de la clave primaria y ningún par de tuplas de la relación puede ser igual en todos los atributos de la clave primaria

Aunque la especificación de clave primaria es opcional, suele ser una buena idea especificar una clave primaria para cada relación

En el ejemplo se ha creado una relación llamada cuenta en la cual se han definido los atributos:

numero_cuenta, que puede guardar una palabra de hasta 10 carácteres
nombre_sucursal, que puede guardar una palabra de hasta 15 carácteres
saldo, que puede guardar un número decimal con 12 enteros y 2 decimales
Y con la restricción sobre numero_cuenta como clave primaria de la relación

Si una tupla recién insertada o recién modificada de una relación contiene valores nulos para cualquiera de los atributos que forman parte de la clave primaria, o si tienen el mismo valor que otra tupla de la relación, SQL notificará el error e impedirá la actualización

En el ejemplo se ha creado otra relación llamada cliente en la cual se han definido los atributos:

numero_cuenta, que puede guardar una palabra de hasta 10 carácteres
nombre_cliente, que puede guardar una palabra de hasta 15 carácteres
Y con la restricción sobre numero_cuenta como clave primaria de la relación

Como puede verse podemos crear más de una relación

DROP TABLE

Para eliminar una relación de la base de datos se utiliza el comando DROP TABLE

Este comando elimina de la base de datos toda la información sobre la relación

En el ejemplo se ha elimina de la base de datos toda la información sobre la relación cuenta

Este comando es más drástico que DELETE, que sólo borra sus tuplas manteniendo el esquema de la relación

Sin embargo, DROP, si se elimina cuenta, no se podrá volver a insertar ninguna tupla en dicha relación, a menos que se vuelva a crear con el comando CREATE TABLE

ALTER TABLE

El comando ALTER TABLE se utiliza para añadir atributos a una relación existente

Como valor del nuevo atributo se asigná a todas las tuplas de la relación el valor nulo

En el ejemplo se ha añadido un nuevo atributo

Donde cuenta es el nombre de la relación existente, ano es el nombre del atributo que se desea añadir y DATETIME es el dominio del atributo añadido

También se pueden eliminar atributos usando ALTER TABLE

En el ejemplo se ha eliminado el atributo que añadimos antes

Donde cuenta es el nombre de la relación existente y ano es el nombre del atributo que se desea eliminar

En este caso no es necesario declarar el dominio del atributo a borrar

Muchos sistemas de bases de datos no permiten el borrado de atributos, aunque sí que permiten el borrado de tablas completas

TRUNCATE

Este comando solo se aplica a tablas y su función es borrar el contenido completo de la relación especificada

La ventaja sobre el comando DELETE, es que si se quiere borrar todo el contenido de la relación, es mucho más rápido, especialmente si la relación es muy grande

La desventaja es que TRUNCATE sólo sirve cuando se quiere eliminar absolutamente todas las tuplas, ya que no se permite la cláusula WHERE

Si bien, en un principio, esta sentencia parecería ser LMD (Lenguaje de Manipulación de Datos), es en realidad una LDD, ya que internamente, el comando TRUNCATE borra la tabla y la vuelve a crear y no ejecuta ninguna transacción

En el ejemplo hemos borrado todo el contenido de la relación llamada cuenta

LMD

Lenguaje interactivo de manipulación de datos (LMD)

El lenguaje de manipulación de datos (LMD) es el que se encarga de llevar a cabo las tareas de consulta o manipulación de los datos, organizados por el modelo de datos adecuado

Incluye órdenes para consultar, modificar, borrar o definir las tuplas (filas) que son almacenadas en las relaciones (tablas) de la base de datos

Existen cuatro operaciones básicas:

Definición básica de esquemas

Operación alias

SQL proporciona una operación para renombrar mediante un alias tanto las relaciones como los atributos

Tiene la siguiente sintaxis: nombre_original AS alias

La cláusula AS es opcional aunque si la escribimos resultará más claro porque nos informa que estamos definiendo un alias

Situaciones en las que es útil usar un alias:

  • Donde tenemos dos relaciones en la cláusula FROM que tienen el mismo nombre para sus atributos

    En estas situaciones se puede producir ambigüedad y podremos usar la operación alias para desambigüar los atributos y que quede claro a qué relación pertenecen

  • Cuando tenemos una operación calculada que genera un atributo en la cláusula SELECT

  • Cuando tenemos una operación calculada que genera un atributo despues de aplicar una operación de agregación

Para acceder a sus atributos se debe usar el alias seguido de un punto y el nombre del atributo

SELECT

Se puede utilizar el comando SELECT para consultar los datos almacenados en una relación de la base de datos

Devolverá un conjunto de tuplas de esa relación

La forma más habitual de consulta será:

\text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_1, r_2, \cdots, r_m\\ \text{WHERE} P

Donde cada Ai representa a un atributo, cada ri una relación y P es un predicado

Por lo que una consulta SQL tendrá la siguiente expresión de álgebra relacional equivalente:

\prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma p(r_1 \Theta r_2 \Theta \cdots \Theta r_m) )

Si se omite la clausula WHERE, el predicado P es siempre cierto

Pero a diferencia de la expresión del álgebra relacional, el resultado de una consulta SQL puede contener varias tuplas repetidas

Cuando introducimos más de una relación en la claúsula FROM, SQL formará un producto cartesiano de todas las relaciones incluidas

Después se lleva a cabo la selección del álgebra relacional utilizando el predicado de la cláusula WHERE y despues proyecta el resultado sobre los atributos de la cláusula SELECT

Cláusula SELECT

En el ejemplo se ha resuelto la consulta obtener todas las cuentas de la relación cuenta con los atributos numero_cuenta, nombre_sucursal, saldo

En este caso, al usar DISTINCT estamos forzando a que se eliminen los repetidos

En el ejemplo se ha resuelto la consulta obtener todas las cuentas de la relación cuenta con los atributos numero_cuenta, nombre_sucursal, saldo

En este caso, al usar ALL estamos forzando a que NO se eliminen los repetidos

En el ejemplo se ha sustituido el comando ALL por el símbolo * y se ha prescindido de los atributos, ya que el resultado es equivalente

En el ejemplo se ha resuelto la consulta obtener todas las cuentas de la relación cuenta con los atributos numero_cuenta, nombre_sucursal, con un incremento de 1500 en el saldo

Como puede apreciarse, también podemos utilizar expresiones aritméticas que operen sobre los atributos

En el ejemplo se ha creado un atributo calculado (que no pertenece a la relación) a partir de esas operaciones, asignándole un nombre o alias a esa operación, en este caso se llama incremento

Cláusula FROM

La cláusula FROM define por sí misma un producto cartesiano de las relaciones que aparecen en la consulta

Dado que la reunión natural se define en términos de un producto cartesiano, una selección y una proyección, resulta relativamente sencillo escribir una expresión SQL para la reunión natural

Tenemos que en álgebra relacional podemos escribirla como:

\prod_{A_1, \cdots, A_2, \cdots, A_n} (r_1 \Theta r_2 \Theta \cdots \Theta r_m)

El ejemplo resuelve la consulta de obtener todos los clientes que tienen cuenta en la sucursal de ‘Navacerrada

Para ello se han introducido las relaciones cuenta (se le ha asignado el alias c) y cliente (se le ha asignado el alias cl)

Sólo con la cláusula FROM no podríamos resolver la consulta

Ya que el producto cartesiano se realiza sobre cada una de las posibles parejas que pueden formarse con la relación cuenta y cliente

Dándonos resultados repetidos y también todos aquellos que no fueran de la sucursal de ‘Navacerrada

Por eso se ha añadido la condición que relaciona ambas relaciones, el atributo numero_cuenta

Después de añadirlo, tendremos sólo los valores que pertenecen a la relación, aunque puede seguir habiendo repetidos

Y la igualdad para la atributo nombre_sucursal con el valor ‘Navacerrada

Cláusula JOIN

En el ejemplo se ha usado la cláusula JOIN que nos devolverá un resultado equivalente

La cláusula JOIN permite realizar operaciones de reunión, las cuales toman dos relaciones y devuelven como resultado otra relación

Normalmente puede utilizarse la cláusula FROM para realizar reuniones externas o para cualquier situación en la que se pueda utilizar una reunión

Para distinguir si la reunión es externa se usará la palabra clave OUTER y para la interna INNER

Ambas son opcionales, aunque deja más claro qué tipo de reunión estamos usando

Hay cuatro tipos de reunión:

  • INNER JOIN

    Devuelve todas las tuplas cuando hay al menos una coincidencia en ambas relaciones

    En el ejemplo se ha usado la cláusula INNER JOIN que nos devolverá un resultado equivalente

    Ya que como dijimos, la palabra clave INNER era opcional

    Sin embargo, ahora tenemos más claro que la reunión era interna

  • LEFT OUTER JOIN

    Devuelve todas las tuplas de la relación de la izquierda, y las tuplas coincidentes de la relación de la derecha

    En el ejemplo se ha usado la cláusula LEFT JOIN que nos devolverá un resultado que ya no es equivalente, ya que aparecerán valores nulos

    Hemos prescindido de la palabra clave OUTER porque el resultado es equivalente

    En este caso LEFT JOIN nos mantiene todas las tuplas de la relación izquierda (cuenta)

    Las tuplas de la relación derecha (cliente) se mostrarán si hay una coincidencia con las de la izquierda

    Si existen valores en la relación izquierda pero no en la relación derecha, ésta mostrará null

  • RIGHT OUTER JOIN

    Devuelve todas las tuplas de la relación de la derecha, y las tuplas coincidentes de la relación de la izquierda

    En el ejemplo se ha usado la cláusula RIGHT JOIN que nos devolverá un resultado que ya no es equivalente, ya que aparecerán valores nulos

    Hemos prescindido de la palabra clave OUTER porque el resultado es equivalente

    En este caso RIGHT JOIN nos mantiene todas las tuplas de la relación derecha (cliente)

    Las tuplas de la relación izquierda (cuenta) se mostrarán si hay una coincidencia con las de la derecha

    Si existen valores en la relación derecha pero no en la relación izquierda, ésta mostrará null

  • FULL OUTER JOIN

    Devuelve todas las tuplas de las dos relaciones, la izquierda y la derecha

    En el ejemplo se ha usado la cláusula FULL JOIN que nos devolverá un resultado que ya no es equivalente, ya que aparecerán valores nulos

    Hemos prescindido de la palabra clave OUTER porque el resultado es equivalente

    En este caso FULL JOIN devuelve todas las filas de la tabla izquierda (cuenta) y de la tabla derecha (cliente)

    Combina el resultado de los LEFT JOIN y RIGHT JOIN

    Aparecerá null en cada una de las tablas alternativamente cuando no haya una coincidencia

El tipo de reunión define la manera de tratar las tuplas de cada relación que no casan con la tupla de la otra relación

Hay tres tipos de condiciones que se aplicarán a las reuniones:

  • reunión NATURAL

    Se utiliza cuando los atributos por los cuales se reúnen las relaciones tienen el mismo nombre

    En el ejemplo se ha usado la cláusula NATURAL JOIN que nos devolverá un resultado equivalente sin utilizar la condición ON

    Ya que el atributo numero_cuenta se llama igual en las relaciones cuenta y cliente

  • condición ON

    Su uso es similar al de la cláusula WHERE, pero está especializado en comparar atributos de ambas relaciones

  • condición USING

    Su uso es similar al de la reunión NATURAL, ya que se utiliza cuando los atributos por los cuales se reúnen las relaciones tienen el mismo nombre

    Sin embargo, sólo devolverá un resultado de la reunión, no todos como hace la reunión NATURAL

    En el ejemplo se ha usado la condición USING con el el atributo numero_cuenta, que nos devolverá un resultado que ya no es equivalente

    Ya que sólo devolverá sólo la primera coincidencia de cada pareja de la relación, no todas

El uso de las condiciones de reunión es obligatorio en las reuniones externas, pero es opcional en las internas (si se omiten, se obtiene un producto cartesiano)

Cláusula WHERE

En el ejemplo se ha resuelto la consulta obtener sólo las cuentas de la relación cuenta que cumplen la condición introducida, en este caso las que en su atributo saldo tienen un valor inferior a 100

Para conseguirlo hemos utilizado la cláusula WHERE, gracias a la cuál podemos filtrar la consulta al admitir una condición usando el operador lógico de comparación <

Operador Descripción
< Menor que
<= Menor o igual que
> Mayor que
>= Mayor o igual que
= Igual que
<> Distinto que

En el ejemplo se ha resuelto la consulta obtener sólo las cuentas de la relación cuenta que cumplen la condición introducida, en este caso las que en su atributo nombre_sucursal tienen un valor igual a ‘Navacerrada‘ y su atributo saldo tienen un valor inferior a 100

Para conseguirlo se ha utilizado el conector lógico AND

Operadores lógicos de conexión
Operador Descripción
AND Es verdadera si y sólo si los dos operandos son verdaderos
OR Es verdadera si y sólo si los uno o ambos operandos son verdaderos
NOT Invierte el valor del operando
Operador BETWEEN

En el ejemplo se ha resuelto la consulta obtener sólo las cuentas de la relación cuenta que cumplen la condición introducida, en este caso las que en su atributo nombre_sucursal tienen un valor igual a ‘Navacerrada‘ y su atributo saldo tienen un valor entre 100 y 1000

En el ejemplo se ha utilizado una consulta equivalente, utilizando el operador de comparación BETWEEN, el cuál nos simplifica un poco las cláusulas WHERE

En el ejemplo se ha utilizado una consulta negando el operador de comparación NOT BETWEEN, el cuál nos devolverá aquellos valores que estén fuera de ese rango

Operador LIKE

En el ejemplo se ha resuelto la consulta obtener sólo las cuentas de la relación cuenta que cumplen la condición introducida, en este caso las que en su atributo nombre_sucursal tienen un valor igual a ‘Navacerrada

En el ejemplo se ha utilizado una consulta equivalente, utilizando el operador de comparación LIKE, el cuál nos simplifica un poco las cláusulas WHERE al permitirnos el uso de patrones con las cadenas de caracteres

Para la descripción de patrones podemos utilizar dos caracteres especiales:

  • %

    El tanto por ciento coincide con cualquier subcadena de caracteres

  • _

    El subrayado coincide con cualquier carácter

Estos patrones pueden ser combinados para obtener distintos tipos de consultas:

En el ejemplo se ha utilizado el operador de comparación LIKE utilizando el patrón % después del texto, el cuál nos devolverá aquellos valores que empiecen por la cadena ‘Nava

En el ejemplo se ha utilizado el operador de comparación LIKE utilizando el patrón % delante y después del texto, el cuál nos devolverá aquellos valores que incluyan como subcadena ‘Nava

En el ejemplo se ha utilizado el operador de comparación LIKE utilizando el patrón _ repetido tres veces, el cuál nos devolverá aquellos valores que tengan exactamente tres caracteres

En el ejemplo se ha utilizado el operador de comparación LIKE utilizando el patrón _ repetido tres veces y el patrón %, el cuál nos devolverá aquellos valores que tengan al menos tres caracteres

En el ejemplo se ha utilizado el operador de comparación LIKE utilizando el patrón % en conjunto con el carácter especial de escape ‘\‘, el cuál nos devolverá aquellos valores que contengan ‘Nava%rrete

El carácter de escape (que puede ser cualquiera que nosotros elijamos) se utiliza antes de los caracteres especiales de patrón para indicar que ese carácter se va a tratar como un carácter normal y no como un patrón

Se define utilizando la palabra clave escape

En el ejemplo se ha utilizado el operador de comparación NOT LIKE utilizando el patrón %, el cuál nos devolverá aquellos valores que NO contengan ‘Nava%rrete

De esta forma también podemos buscar discordancias, solamente negando el operador LIKE

Valores nulos

SQL permite el uso de valores nulos para indicar la ausencia de información sobre el valor de un atributo

Se puede utilizar la palabra clave especial NULL en un predicado para comprobar si un valor es nulo

En el ejemplo se ha resuelto la consulta obtener todas las cuentas cuyo nombre de sucursal NO haya sido rellenado

En el ejemplo se ha resuelto la consulta obtener todas las cuentas cuyo nombre de sucursal haya sido rellenado

Como puede verse, también puede comprobarse la ausencia de valores nulos usando el operador lógico NOT

Dado que el predicado de las cláusulas WHERE puede incluir operaciones booleanas como AND, OR y NOT sobre los resultados de la comparaciones, los valores NULL amplían las operaciones booleanas

AND VERDAD FALSO NULL
VERDAD VERDAD FALSO NULL
FALSO FALSO FALSO FALSO
NULL NULL FALSO NULL
OR VERDAD FALSO NULL
VERDAD VERDAD VERDAD VERDAD
FALSO VERDAD FALSO NULL
NULL VERDAD NULL NULL
NOT VERDAD FALSO NULL
FALSO VERDAD NULL

Cláusula ORDER BY

En ocasiones necesitamos devolver la información de las tuplas en cierto order

SQL permite ordenar los atributos utilizando la cláusula ORDER BY

En el ejemplo se ha utilizado el operador de comparación ASC con la cláusula ORDER BY para el atributo nombre_sucursal, el cuál nos devolverá los valores ordenados de forma ascendente (en order alfabético porque era un atributo alfanumérico) por el atributo nombre_sucursal

En el ejemplo se ha utilizado el operador de comparación DESC con la cláusula ORDER BY para el atributo nombre_sucursal, el cuál nos devolverá los valores ordenados de forma descendente (en order alfabético porque era un atributo alfanumérico) por el atributo nombre_sucursal

El tipo de ordenación devuelto por los operadores de comparación ASC y DESC dependerán del tipo del atributo, ya que no se ordena de igual manera un número, una cadena o una fecha

Si necesitamos ordenar más de un atributo, lo haremos separandolos por comas y seguido el operador de comparación (ASC ó DESC )

El método de ordenación por defecto es ASC, es opcional y podríamos prescindir de escribirlo

Operaciones sobre conjuntos

SQL permite realizar las operaciones sobre conjuntos del álgebra relacional unión \cup, intersección \cap y diferencia \neg

Para utilizarlas tendremos la única restricción de que los nombres de los atributos de las relaciones implicadas deben ser iguales

Operación UNION

La forma más habitual de consulta será:

\text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_1\\ \text{WHERE} P\\ \text{UNION}\\ \text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_2\\ \text{WHERE} Q

Donde cada Ai representa a un atributo, cada ri una relación y P, Q son predicados

Por lo que una consulta SQL que contiene una unión tendrá la siguiente expresión de álgebra relacional equivalente:

\prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma p (r_1) ) \cup \prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma q (r_2) )

Si se omite la clausula WHERE, el predicado P ó Q (depende cuál se omita), es siempre cierto

En el ejemplo se ha resuelto la consulta de todos los números de cuenta que existen en el banco o que tienen un cliente asociado a ellas

A diferencia de la cláusa SELECT la operación UNION elimina los valores repetidos

Por esta razón es buena idea utilizar la operación UNION para crear claves, ya que con SELECT no obtendríamos claves únicas (permite repetidos)

En el ejemplo se ha resuelto la consulta de todos los números de cuenta que existen en el banco o que tienen un cliente asociado a ellas

Al utilizar el operador ALL en conjunto con la operación UNION, estamos permitiendo que se comporte como un SELECT, ya que admite repetidos

Operación INTERSECT

La forma más habitual de consulta será:

\text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_1\\ \text{WHERE} P\\ \text{INTERSECT}\\ \text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_2\\ \text{WHERE} Q

Donde cada Ai representa a un atributo, cada ri una relación y P, Q son predicados

Por lo que una consulta SQL que contiene una intersección tendrá la siguiente expresión de álgebra relacional equivalente:

\prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma p (r_1) ) \cap \prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma q (r_2) )

Si se omite la clausula WHERE, el predicado P ó Q (depende cuál se omita), es siempre cierto

En el ejemplo se ha resuelto la consulta de todos los números de cuenta que existen en el banco y que tienen un cliente asociado a ellas

La operación INTERSECT elimina los valores repetidos y sólo devuelve aquellos valores que tienen coincidencia en la relación cuenta y en cliente a la vez, no sólo en uno de ellos

En el ejemplo se ha resuelto la consulta de todos los números de cuenta que existen en el banco y que tienen un cliente asociado a ellas

Al utilizar el operador ALL en conjunto con la operación INTERSECT, estamos permitiendo que se comporte como un SELECT, ya que admite repetidos

Operación EXCEPT

La forma más habitual de consulta será:

\text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_1\\ \text{WHERE} P\\ \text{EXCEPT}\\ \text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_2\\ \text{WHERE} Q

Donde cada Ai representa a un atributo, cada ri una relación y P, Q son predicados

Por lo que una consulta SQL que contiene una diferencia tendrá la siguiente expresión de álgebra relacional equivalente:

\prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma p (r_1) ) \cap \neg (\prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma q (r_2) ) )

Si se omite la clausula WHERE, el predicado P ó Q (depende cuál se omita), es siempre cierto

En el ejemplo se ha resuelto la consulta de todos los números de cuenta que existen en el banco y que NO tienen un cliente asociado a ellas

La operación EXCEPT elimina los valores repetidos y sólo devuelve aquellos valores que tienen coincidencia en la relación cuenta pero no coinciden con cliente

En el ejemplo se ha resuelto la consulta de todos los números de cuenta que existen en el banco y que NO tienen un cliente asociado a ellas

Al utilizar el operador ALL en conjunto con la operación EXCEPT, estamos permitiendo que se comporte como un SELECT, ya que admite repetidos

Operación IN

SQL permite comprobar la pertenencia de las tuplas a una relación que es equivalente a comprobar la pertenencia a un conjunto del álgebra relacional

La forma más habitual de consulta será:

\text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_1\\ \text{WHERE} P\\ \text{IN}\\ (\text{SELECT} _1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_2\\ \text{WHERE} Q)

Donde cada Ai representa a un atributo, cada ri una relación y P, Q son predicados

Por lo que una consulta SQL que contiene una pertenencia tendrá la siguiente expresión de álgebra relacional equivalente:

\prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma p (r_1) ) \in \prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma q (r_2) )

Si se omite la clausula WHERE, el predicado P ó Q (depende cuál se omita), es siempre cierto

El ejemplo resuelve la consulta de obtener todos los clientes que tienen cuenta en la sucursal de ‘Navacerrada

Anteriormente la resolvimos utilizando la cláusula JOIN

Pero como puede comprobarse, también podemos resolverla utilizando la teoría de conjuntos

La pertenencia nos devolverá los valores y en caso de no haber ninguno, mostrará null

El ejemplo resuelve la consulta de obtener todos los clientes que NO tienen cuenta en la sucursal de ‘Navacerrada

Al negar la pertenencia nos devolverá el resto de valores y en caso de no haber ninguno, mostrará null

El ejemplo resuelve la consulta de obtener todos los clientes que tienen cuenta en la sucursal de ‘Logroño‘ ó ‘Navacerrada

Como puede apreciarse, la pertenencia o la no pertenencia, aparte de una subconsulta como en los ejemplos anteriores, también admite conjuntos enumerados

Siempre que esos conjuntos enumerados sean del mismo dominio que el atributo del que se quiere comprobar la pertenencia

Operadores de comparación

SQL ofrece la posibilidad de comparar conjuntos utilizando subconsultas

Operador SOME

La forma más habitual de consulta será:

\text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_1\\ \text{WHERE} P\\ \text{SOME}\\ (\text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_2\\ \text{WHERE} Q)

Donde cada Ai representa a un atributo, cada ri una relación y P, Q son predicados

Por lo que una consulta SQL que contiene una pertenencia tendrá la siguiente expresión de álgebra relacional equivalente:

\prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma p (r_1) ) \approx \prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma q (r_2) )

Si se omite la clausula WHERE, el predicado P ó Q (depende cuál se omita), es siempre cierto

El ejemplo resuelve la consulta de obtener algún cliente que tiene cuenta en la sucursal de ‘Navacerrada

Anteriormente la resolvimos utilizando la operación IN

Pero como puede comprobarse, también podemos resolverla utilizando una comparación de conjuntos

En este caso utilizando el símbolo = delante del operador SOME para denotar que son iguales

El ejemplo resuelve la consulta de obtener algún cliente que NO tiene cuenta en la sucursal de ‘Navacerrada

Aunque podría parecer que es equivalente al ejemplo anterior con NOT INT, el resultado puede no ser igual

También podemos utilizar el resto de operadores lógicos de comparación

Operador ANY

Puede utilizarse también el operador ANY ya que es equivalente a SOME

Las primeras versiones de SQL sólo admitían el operador ANY, pero se añadió SOME para que se asemejase más al lenguaje natural, ya que any creaba ambigüedad en la lengua inglesa

La forma más habitual de consulta será:

\text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_1\\ \text{WHERE} P\\ \text{ANY}\\ (\text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_2\\ \text{WHERE} Q)

Donde cada Ai representa a un atributo, cada ri una relación y P, Q son predicados

Por lo que una consulta SQL que contiene una pertenencia tendrá la siguiente expresión de álgebra relacional equivalente:

\prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma p (r_1) ) \approx \prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma q (r_2) )

Si se omite la clausula WHERE, el predicado P ó Q (depende cuál se omita), es siempre cierto

También podemos utilizar el resto de operadores lógicos de comparación

El ejemplo resuelve la consulta de obtener algún cliente que tiene cuenta en la sucursal de ‘Navacerrada

Anteriormente la resolvimos utilizando la operación SOME

Como puede verse es totalmente equivalente y sólo lo usaríamos por compatibilidad con versiones antiguas de SQL

Operador ALL

La forma más habitual de consulta será:

\text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_1\\ \text{WHERE} P\\ \text{ALL}\\ (\text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_2\\ \text{WHERE} Q)

Donde cada Ai representa a un atributo, cada ri una relación y P, Q son predicados

Por lo que una consulta SQL que contiene una pertenencia tendrá la siguiente expresión de álgebra relacional equivalente:

\prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma p (r_1) ) \forall \prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma q (r_2) )

Si se omite la clausula WHERE, el predicado P ó Q (depende cuál se omita), es siempre cierto

También podemos utilizar el resto de operadores lógicos de comparación

El ejemplo resuelve la consulta de obtener todos los clientes que tienen cuenta en la sucursales después de ‘Navacerrada‘ (alfabéticamente)

En realidad al utilizar el símbolo > delante del operador ALL estamos denotando que buscamos todos los valores que tengan una ordenación alfabética superior a ‘Navacerrada

Control de repetidos

SQL permite controlar si una subconsulta tiene tuplas repetidas en su resultado

La forma más habitual de consulta será:

\text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_1\\ \text{WHERE UNIQUE}\\ (\text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_2, \cdots, r_n\\ \text{WHERE} P)

Donde cada Ai representa a un atributo, cada ri una relación y P es predicado

Por lo que una consulta SQL que contiene una pertenencia tendrá la siguiente expresión de álgebra relacional equivalente:

\prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma \exists \prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma p (r_2, \cdots, r_n) ) (r_1) )

Si se omite la clausula WHERE, el predicado P, es siempre cierto

Formalmente la evaluación de UNIQUE sobre una relación se define como falsa si y sólo si la relación contiene dos tuplas ri y rk tales que ri = rk

Como la comprobación ri = rk es falsa si algún atributo de ri ó rk es nulo, es posible que el resultado de UNIQUE sea cierto aunque haya varios duplicados de una misma tupla

Siempre que al menos uno de los atributos de la tupla sea nulo

El ejemplo resuelve la consulta de obtener todos los clientes que tienen a lo sumo una cuenta en la sucursal de ‘Navacerrada

Para ello se han introducido las relaciones cuenta (se le ha asignado el alias c) y cliente (se le ha asignado el alias cl)

Sólo con la cláusula FROM no podríamos resolver la consulta

Podríamos haber usado la cláusula JOIN, aunque puede seguir habiendo repetidos

Por eso se ha añadido el operador UNIQUE que relaciona ambas relaciones con el atributo numero_cuenta y la igualdad para la atributo nombre_sucursal con el valor ‘Navacerrada

Después de añadirlos, tendremos sólo los valores que pertenecen a la relación

El ejemplo resuelve la consulta de obtener todos los clientes que tienen más de una cuenta en la sucursal de ‘Navacerrada

Como puede verse, la negación de UNIQUE nos permite comprobar si hay más de un repetido

Funciones de agregación

Las funciones de agregación son funciones que toman una colección (un conjunto o multiconjunto) de valores como entrada y devuelven un solo valor

SQL permite cinco funciones de agregación:

  • AVG

    Permite realizar la media aritmética de la colección, la cuál debe ser numérica

    Si hay valores nulos en la entrada, se ignoran

    En el ejemplo se ha resuelto la consulta obtener la media aritmética del saldo de todas las cuentas

    Se ha creado un atributo calculado (que no pertenece a la relación) a partir de esas operaciones, asignándole un nombre o alias a esa operación, en este caso se llama media

  • MIN

    Permite determinar cuál es valor mínimo de la colección, la cuál no es obligatorio que sea numérica

    Si hay valores nulos en la entrada, se ignoran

    En el ejemplo se ha resuelto la consulta obtener el saldo más bajo de todas las cuentas

    Se ha creado un atributo calculado (que no pertenece a la relación) a partir de esas operaciones, asignándole un nombre o alias a esa operación, en este caso se llama menor

  • MAX

    Permite determinar cuál es valor máximo de la colección, la cuál no es obligatorio que sea numérica

    Hay que tener en cuenta que NO admite DISTINCT pero si ALL, pero como es el valor por defecto, puede omitirse

    Si hay valores nulos en la entrada, se ignoran

    En el ejemplo se ha resuelto la consulta obtener el saldo más alto de todas las cuentas

    Se ha creado un atributo calculado (que no pertenece a la relación) a partir de esas operaciones, asignándole un nombre o alias a esa operación, en este caso se llama mayor

  • SUM

    Permite realizar la suma de la colección, la cuál debe ser numérica

    Si hay valores nulos en la entrada, se ignoran

    En el ejemplo se ha resuelto la consulta obtener el saldo total de todas las cuentas

    Se ha creado un atributo calculado (que no pertenece a la relación) a partir de esas operaciones, asignándole un nombre o alias a esa operación, en este caso se llama liquido

  • COUNT

    Permite contar el número de elementos que compone la colección, la cuál no es obligatorio que sea numérica

    Si hay valores nulos en la entrada, se toman como 0

    En el ejemplo se ha resuelto la consulta obtener cuantas cuentas hay en total

    Se ha creado un atributo calculado (que no pertenece a la relación) a partir de esas operaciones, asignándole un nombre o alias a esa operación, en este caso se llama total

Cláusula GROUP BY

Existen circunstancias en las cuales sería deseable aplicar las funciones de agregación no sólo a un único conjunto de tuplas sino también a un grupo de conjuntos de tuplas

En SQL podemos especificarlo mediante la cláusula GROUP BY

La forma más habitual de consulta será:

\text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r\\ \text{WHERE} P\\ \text{GROUP BY} A_1, \cdots, A_2, \cdots, A_n\\ \text{HAVING} Q

Donde cada Ai representa a un atributo, cada ri una relación y P, Q son predicados

Por lo que una consulta SQL que contiene una agrupación tendrá la siguiente expresión de álgebra relacional equivalente:

\prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma q (\prod_{A_1, \cdots, A_2, \cdots, A_n} (\sigma p (r) ) )

Si se omiten las clausulas WHERE ó HAVING, el predicado P ó Q (depende cuál se omita), es siempre cierto

En el ejemplo se ha resuelto la consulta obtener cuantas cuentas hay en total de cada sucursal

Se ha creado un atributo calculado (que no pertenece a la relación) a partir de esas operaciones, asignándole un nombre o alias a esa operación, en este caso se llama total

Para que la operación de agrupación pueda realizarse sin errores debemos utilizar el mismo orden de los atributos tanto en la cláusula SELECT como en GROUP BY

En el caso de que no vayan a intervenir en la agrupación, podremos omitir esos atributos colocándolos a la derecha de los que sí serán usados

Cláusula HAVING

En ocasiones necesitamos que una condición se aplique a los grupos en vez de a las tuplas

Para expresar este tipo de consultas utilizamos la cláusula HAVING

En el ejemplo se ha resuelto la consulta obtener cuantas cuentas hay en total de la sucursal de ‘Navacerrada

Se ha creado un atributo calculado (que no pertenece a la relación) a partir de esas operaciones, asignándole un nombre o alias a esa operación, en este caso se llama total

Se ha aplicado la condición sobre el atributo nombre_sucursal con el valor ‘Navacerrada‘ utilizando la cláusula HAVING para aplicarla sobre la agrupación y no sobre la relación

En el caso de que tendríamos una cláusula WHERE y una HAVING:

  1. SQL aplicará primero el predicado de la cláusula WHERE
  2. El resultado se dividirá en los grupos que satisfagan el predicado de la cláusula HAVING

En el ejemplo se ha resuelto la consulta obtener cuantas cuentas hay en total de la sucursal de ‘Navacerrada‘ y que tengan un saldo mayor de 100

Se ha creado un atributo calculado (que no pertenece a la relación) a partir de esas operaciones, asignándole un nombre o alias a esa operación, en este caso se llama total

Se ha aplicado la condición sobre el atributo nombre_sucursal con el valor ‘Navacerrada

Adicionalmente se ha aplicado la condición sobre el atributo saldo aplicándole la operación de agrupación COUNT con la condición de que sean mayores que 100

Ambas han sido aplicacadas sobre la cláusula HAVING

Como puede verse, pueden aplicarse sin problemas las operaciones de agregación dentro de la cláusula HAVING aunque también aparezcan en la cláusula SELECT

INSERT

Las relaciones recién creadas están inicialmente vacías

Se puede utilizar el comando INSERT para añadir datos a la relación

La forma más habitual de consulta de inserción será:

\text{INSERT INTO r}\\ \text{VALUES} (A_1, A_2, \cdots, A_n)

Donde cada Ai representa a un atributo, r la relación y cada Pi es un predicado

En el ejemplo se ha resuelto la consulta para añadir la cuenta C-9732 en la sucursal de ‘Navacerrada‘ con un saldo de 1200€

Los valores se especifican en el orden en que se relacionan los atributos correspondientes en el esquema de la relación

En el ejemplo se ha modificado el orden en que se relacionan los atributos correspondientes en el esquema de la relación y por eso los datos se han introducido de forma obligatoria, en el nuevo orden que hemos especificado

De esta forma podemos elegir nosotros en qué orden introducimos los datos

En el caso de no introducir un atributo, SQL tratará de introducir un valor por defecto o el valor nulo y si es la clave primaria, notificará el error e impedirá la actualización

En el ejemplo se ha resuelto la consulta para añadir el cliente ‘Pedro Almodovar‘ para todos los números de cuenta que existen en la sucursal de ‘Navacerrada‘ y que NO tienen un cliente asociado a ellas

En lugar de especificar una tupla se ha usado una subconsulta ya que la cláusula SELECT nos permitirá especificar un conjunto de tuplas

La forma más habitual de subconsulta para la inserción será:

\text{INSERT INTO} r1\\ \text{SELECT} A_1, \cdots, A_2, \cdots, A_n\\ \text{FROM} r_2\\ \text{WHERE} P

Donde cada Ai representa a un atributo, ri las relaciones y P es un predicado

Se evaluará en primer lugar la cláusula SELECT y se insertarán en la relación cliente las tuplas obtenidas de la subconsulta

Hemos de tener cuidado al utilizar subconsultas anidadas, ya que al abusar de ellas, podríamos crear un bucle infinito de subconsultas y la inserción se realizaría de forma infinita, quedando la base de datos bloqueada

Por suerte los sistemas gestores de bases de datos tienen mecanismos o herramientas para realizar inserciones masivas de forma controlada, evitando el bloqueo de la base de datos

UPDATE

Se puede utilizar el comando UPDATE para modificar los valores de un conjunto de tuplas existentes de una relación

La forma más habitual de consulta de actualización será:

\text{UPDATE r}\\ \text{SET} A_1 = P_1, A_2 = P_2, \cdots, A_n = P_n

Donde cada Ai representa a un atributo, r la relación y cada Pi es un predicado

En el ejemplo se ha actualizado la relación llamada cuenta, en concreto al atributo saldo le hemos cambiado su valor a 100

El comando actualizará todas las tuplas de la relación cuenta

En el ejemplo se han actualizado sólo las tuplas que cumplen la condición introducida, en este caso las que en su atributo numero_cuenta tienen un valor igual a ‘C-9732

En lugar de especificar una tupla se ha usado una subconsulta ya que la cláusula SELECT nos permitirá especificar un conjunto de tuplas

Hemos de tener cuidado al utilizar subconsultas anidadas, ya que al abusar de ellas, podríamos crear un bucle infinito de subconsultas y la inserción se realizaría de forma infinita, quedando la base de datos bloqueada

Por suerte los sistemas gestores de bases de datos tienen mecanismos o herramientas para realizar inserciones masivas de forma controlada, evitando el bloqueo de la base de datos

Operador Case

El orden de dos instrucciones UPDATE es importante ya que si se cambia el orden de las instrucciones de actualización podemos obtener datos incoherentes

Para solucionar este problema tenemos el operador CASE

La forma más habitual de consulta de actualización será:

\text{UPDATE r}\\ \text{SET} A_1 = P_1, A_2 = P_2, \cdots, A_n = P_n

Donde cada Ai representa a un atributo, r la relación y cada Pi es un predicado el cual podemos sustituir por el siguiente predicado Q:

\text{CASE}\\ \text{WHEN} P_1 \text{THEN} r_1\\ \text{WHEN} P_2 \text{THEN} r_2\\ \cdots\\ \text{WHEN} P_n \text{THEN} r_n\\ \text{ELSE} r_0\\ \text{END}

Donde cada Pi cada predicado que puede satisfacerse, cada ri el resultado que se usará en la actualización

En el caso de no cumplirse ninguno de los predicados, se aplicaría el resultado r0

En el ejemplo se ha resuelto la consulta de actualización para añadir un 0.05 al saldo cuando es menor o igual que 100 con una modificación del 0.05, cuando es igual que 500 con una modificación del 0.07, cuando es mayor que 1000 con una modificación del 0.25 y una modificación del 0.01 en cualquier otro caso

Se ha utilizado la cláusula CASE para resolverlo al igualarlo con el atributo saldo que era el valor a actualizar

DELETE

Se puede utilizar el comando DELETE para borrar tuplas de una relación

Y sólo de esa relación, ya que no es capaz de trabajar sobre varias

La forma más habitual de consulta de borrado será:

\text{DELETE FROM r}\\ \text{WHERE} P

Donde r representa la relación y cada P es un predicado

En el ejemplo se ha borrado la relación llamada cuenta

El comando borrará todas las tuplas de la relación cuenta

En el ejemplo se han borrado sólo las tuplas que cumplen la condición introducida, en este caso las que en su atributo saldo tienen un valor inferior a 100

Hay que tener en cuenta que el comando DELETE comprueba primero cada tupla de la relación cuenta y luego borrará todas las tuplas que cumplen la condición

Es importante realizar todas las comprobaciones antes del borrado ya que el orden en que se procesan las tuplas puede variar la operación de borrado