Integridad de datos El término integridad de datos se refiere a la corrección y complementación de los datos en una base de datos. Cuando los contenidos se modifican con sentencias INSERT, DELETE o UPDATE, la integridad de los datos almacenados puede perderse de muchas maneras diferentes. Pueden añadirse datos no válidos a la base de datos, tales como un pedido que especifica un producto no existente. Pueden modificarse datos existentes tomando un valor incorrecto, como por ejemplo si se reasigna un vendedor a una oficina no existente. Los cambios en la base de datos pueden perderse debido a un error del sistema o a un fallo en el suministro de energía. Los cambios pueden ser aplicados parcialmente, como por ejemplo si se añade un pedido de un producto sin ajustar la cantidad disponible para vender. Una de las funciones importantes de un DBMS relacional es preservar la integridad de sus datos almacenados en la mayor medida posible. Tipos de restricciones de integridad Datos Requeridos: establece que una columna tenga un valor no NULL. Se define efectuando la declaración de una columna es NOT NULL cuando la tabla que contiene las columnas se crea por primera vez, como parte de la sentencia CREATE TABLE. Chequeo de Validez: cuando se crea una tabla cada columna tiene un tipo de datos y el DBMS asegura que solamente los datos del tipo especificado sean ingresados en la tabla. Integridad de entidad: establece que la clave primaria de una tabla debe tener un valor único para cada fila de la tabla; si no, la base de datos perderá su integridad. Se especifica en la sentencia CREATE TABLE. El DBMS comprueba automáticamente la unicidad del valor de la clave primaria con cada sentencia INSERT Y UPDATE. Un intento de insertar o actualizar una fila con un valor de la clave primaria ya existente fallará. Integridad referencial: asegura la integridad entre las llaves foráneas y primarias (relaciones padre/hijo). Existen cuatro actualizaciones de la base de datos que pueden corromper la integridad referencial: La inserción de una fila hijo se produce cuando no coincide la llave foránea con la llave primaria del padre. La actualización en la llave foránea de la fila hijo, donde se produce una actualización en la clave ajena de la fila hijo con una sentencia UPDATE y la misma no coincide con ninguna llave primaria. La supresión de una fila padre, con la que, si una fila padre -que tiene uno o más hijos- se suprime, las filas hijos quedarán huérfanas. La actualización de la llave primaria de una fila padre, donde si en una fila padre, que tiene uno o más hijos se actualiza su llave primaria, las filas hijos quedarán huérfanas. Normalización de bases de datos El proceso de normalización de bases de datos consiste en aplicar una serie de reglas a las relaciones obtenidas tras el paso del modelo entidad-relación al modelo relacional. Las bases de datos relacionales se normalizan para: Evitar la redundancia de los datos. Disminuir problemas de actualización de los datos en las tablas. Proteger la integridad de los datos. En el modelo relacional es frecuente llamar tabla a una relación, aunque para que una tabla sea considerada como una relación tiene que cumplir con algunas restricciones: Cada tabla debe tener su nombre único. No puede haber dos filas iguales. No se permiten los duplicados. Todos los datos en una columna deben ser del mismo tipo. Terminología relacional equivalente Relación = tabla o archivo Registro = registro, fila , renglón o tupla Atributo = columna o campo Clave = llave o código de identificación Clave Candidata = superclave mínima Clave Primaria = clave candidata elegida Clave Ajena (o foránea) = clave externa o clave foránea Clave Alternativa = clave secundaria Dependencia Multivaluada = dependencia multivalor RDBMS = Del inglés Relational Data Base Manager System que significa,Sistema Gestor de Bases de Datos Relacionales. 1FN = Significa, Primera Forma Normal o 1NF del inglés First Normal Form. Los términos Relación, Tupla y Atributo derivan del álgebra y cálculo relacional, que constituyen la fuente teórica del modelo de base de datos relacional. Todo atributo en una tabla tiene un dominio, el cual representa el conjunto de valores que el mismo puede tomar. Una instancia de una tabla puede verse entonces como un subconjunto del producto cartesiano entre los dominios de los atributos. Sin embargo, suele haber algunas diferencias con la analogía matemática, ya que algunos RDBMS permiten filas duplicadas, entre otras cosas. Finalmente, una tupla puede razonarse matemáticamente como un elemento del producto cartesiano entre los dominios. Dependencia Dependencia funcional B es funcionalmente dependiente de A. Una dependencia funcional es una conexión entre uno o más atributos. Por ejemplo si se conoce el valor de DNI tiene una conexión con Apellido o Nombre. Las dependencias funcionales del sistema se escriben utilizando una flecha, de la siguiente manera: FechaDeNacimiento Edad De la normalización (lógica) a la implementación (física o real) puede ser sugerible tener éstas dependencias funcionales para lograr la eficiencia en las tablas. Propiedades de la Dependencia funcional Existen 3 axiomas de Armstrong: Dependencia funcional Reflexiva Si "y" está incluido en "x" entonces x y A partir de cualquier atributo o conjunto de atributos siempre puede deducirse él mismo. Si la dirección o el nombre de una persona están incluidos en el DNI, entonces con el DNI podemos determinar la dirección o su nombre. Dependencia funcional Aumentativa entonces DNI nombre DNI,dirección nombre,dirección Si con el DNI se determina el nombre de una persona, entonces con el DNI más la dirección también se determina el nombre y su dirección. Dependencia funcional transitiva Sean X, Y, Z tres atributos (o grupos de atributos) de la misma entidad. Si Y depende funcionalmente de X y Z de Y, pero X no depende funcionalmente de Y, se dice entonces que Z depende transitivamente de X. Simbólicamente sería: X Y Z entonces X FechaDeNacimiento Edad Z Edad Conducir FechaDeNacimiento Edad Conducir Entonces tenemos que FechaDeNacimiento determina a Edad y la Edad determina a Conducir, indirectamente podemos saber a través de FechaDeNacimiento aConducir (En muchos países, una persona necesita ser mayor de cierta edad para poder conducir un automóvil, por eso se utiliza este ejemplo). "C será un dato simple (dato no primario), B,será un otro dato simple (dato no primario), A, es la llave primaria (PK). Decimos que C dependerá de B y B dependerá funcionalmente de A." Claves Una clave primaria es aquella columna (o conjunto de columnas) que identifica únicamente a una fila. La clave primaria es un identificador que va a ser siempre único para cada fila. Se acostumbra a poner la clave primaria como la primera columna de la tabla pero es más una conveniencia que una obligación. Muchas veces la clave primaria es numérica auto-incrementada, es decir, generada mediante una secuencia numérica incrementada automáticamente cada vez que se inserta una fila. En una tabla puede que tengamos más de una columna que puede ser clave primaria por sí misma. En ese caso se puede escoger una para ser la clave primaria y las demás claves serán claves candidatas. Una clave ajena (foreign key o clave foránea) es aquella columna que existiendo como dependiente en una tabla, es a su vez clave primaria en otra tabla. Una clave alternativa es aquella clave candidata que no ha sido seleccionada como clave primaria, pero que también puede identificar de forma única a una fila dentro de una tabla. Ejemplo: Si en una tabla clientes definimos el número de documento (id_cliente) como clave primaria, el número de seguro social de ese cliente podría ser una clave alternativa. En este caso no se usó como clave primaria porque es posible que no se conozca ese dato en todos los clientes. Una clave compuesta es una clave que está compuesta por más de una columna. La visualización de todas las posibles claves candidatas en una tabla ayuda a su optimización. Por ejemplo, en una tabla PERSONA podemos identificar como claves su DNI, o el conjunto de su nombre, apellidos, fecha de nacimiento y dirección. Podemos usar cualquiera de las dos opciones o incluso todas a la vez como clave primaria, pero es mejor en la mayoría de sistemas la elección del menor número de columnas como clave primaria. DDL y DML Lenguaje de definición de datos (DDL: Data Definition Language):Sencillo lenguaje artificial para definir y describir los objetos de la base de datos, su estructura, relaciones y restricciones. En la práctica puede consistir en un subconjunto de instrucciones de otro lenguaje informático. Aparte suele poseer dos subconjuntos de instrucciones: Lenguaje de definición del almacenamiento de los datos (DSDL: Data Storage Definition Language): permite especificar características físicas de la base de datos (volúmenes y archivos donde van a ser almacenados los datos, etc). Lenguaje de control de datos (DCL: Data Control Language): encargado del control y seguridad de los datos (privilegios y modos de acceso, etc). Lenguaje de manipulación de datos (DML: Data Manipulation Language): Lenguaje artificial de cierta complejidad que permite el manejo y procesamiento del contenido de la base de datos. En la práctica puede consistir en un subconjunto de instrucciones de otro lenguaje informático. Las aplicaciones que trabajan sobre la base de datos se programan en un lenguaje de programación (C, Cobol, ...) insertando en el código fuente sentencias del DML. Al utilizar un DML se deben especificar los datos que serán afectados por las sentencias del lenguaje. Un DML puede tener o no procedimientos, según sea necesario especificar ademáns cónmo deben obtenerse esos datos. Los DML con procedimientos tienen sentencias de control de flujo como bucles o condicionales. Los DML sin procedimientos son conocidos también como declarativos. Comandos del DDL y del DML Comandos DLL Comando CREATE DROP Descripción Utilizado para crear nuevas tablas, stored procedures e índices Empleado para eliminar tablas, stored procedures e índices ALTER Utilizado para modificar las tablas agregando campos o cambiando la definición de los campos Comandos DML Comando Descripción SELECT Utilizado para consultar registros de la base de datos que satisfagan un criterio determinado. INSERT Utilizado para cargar lotes de datos en la base de datos en una única operación. DELETE Utilizado para modificar los valores de los campos y registros especificados. UPDATE Utilizado para eliminar registros de una tabla de una base de datos. Consultas de Selección Las consultas de selección se utilizan para indicar al motor de datos que devuelva información de las bases de datos, esta información es devuelta en forma de conjunto de registros que se pueden almacenar en un objeto recordset. Este conjunto de registros es modificable. Consultas básicas La sintaxis básica de una consulta de selección es la siguiente: SELECT Campos FROM Tabla En donde campos es la lista de campos que se deseen recuperar y tabla es el origen de los mismos, por ejemplo: SELECT Nombre, Teléfono FROM Clientes Esta consulta devuelve un recordset con el campo nombre y teléfono de la tabla clientes. Ordenar los registros Adicionalmente se puede especificar el orden en que se desean recuperar los registros de las tablas mediante la claúsula ORDER BY Lista de Campos. En donde Lista de campos representa los campos a ordenar. Ejemplo: SELECT CodigoPostal, Telefono FROM Clientes ORDER BY Nombre Nombre, Esta consulta devuelve los campos CodigoPostal, Nombre, Telefono de la tabla Clientes ordenados por el campo Nombre. Se pueden ordenar los registros por mas de un campo, como por ejemplo: SELECT CodigoPostal, Telefono Nombre, FROM Clientes ORDER BY CodigoPostal, Nombre Incluso se puede especificar el orden de los registros: ascendente mediante la claúsula (ASC -se toma este valor por defecto) ó descendente (DESC) SELECT CodigoPostal, Telefono FROM Clientes ORDER BY CodigoPostal Nombre ASC Nombre, DESC, El predicado DISTINCT Se Incluye entre la claúsula y el primer nombre del campo a recuperar. El predicado DISTINCT omite los registros que contienen datos duplicados en los campos seleccionados. Para que los valores de cada campo listado en la instrucción SELECT se incluyan en la consulta deben ser únicos. Por ejemplo, varios empleados listados en la tabla Empleados pueden tener el mismo apellido. Si dos registros contienen López en el campo Apellido, la siguiente instrucción SQL devuelve un único registro: SELECT DISTINCT Apellido FROM Empleados Con otras palabras el predicado DISTINCT devuelve aquellos registros cuyos campos indicados en la cláusula SELECT posean un contenido diferente. El resultado de una consulta que utiliza DISTINCT no es actualizable y no refleja los cambios subsiguientes realizados por otros usuarios. Selección Condicional, Operadores de Comparación y Lógicos Selección Condicional La cláusula WHERE se utiliza para determinar qué registros de las tablas enumeradas en la cláusula FROM aparecerán en los resultados de la instrucción SELECT. Depués de escribir esta cláusula se deben especificar las condiciones expuestas a continuación. Si no se emplea esta cláusula, la consulta devolverá todas las filas de la tabla. WHERE es opcional, pero cuando aparece debe ir a continuación de FROM. Operadores de Comparación Hay nueve operadores de comparación en SQL: = Igual <> Distinto < Menor > Mayor <= Menor Igual <= Mayor Igual between Utilizado para especificar un intervalo de valores. like Utilizado en la comparación de un campo contra un patrón in Utilizado para verificar la existencia de un valor dentro de un conjunto de valores El operador Between Para indicar que deseamos recuperar los registros según el intervalo de valores de un campo emplearemos el operador Between cuya sintaxis es: campo [Not] Between valor1 And valor2 En este caso la consulta devolvería los registros que contengan en "campo" un valor incluido en el intervalo valor1, valor2 (ambos inclusive). Si anteponemos la condición Not devolverá aquellos valores no incluidos en el intervalo. SELECT * FROM Pedidos WHERE CodPostal BETWEEN 28000 and 28999 El Operador Like Se utiliza para comparar una expresión de cadena con un modelo en una expresión SQL. Su sintaxis es: expresión Like modelo En donde expresión es un patrón contra el que se compara expresión. Se puede utilizar el operador like para encontrar valores en los campos que coincidan con el modelo especificado. Por modelo puede especificar un valor completo ("Ana María"), o se pueden utilizar caracteres comodín para encontrar un rango de valores (Like "An%"). El operador like se puede utilizar en una expresión para comparar un valor de un campo con una expresión de cadena. Por ejemplo, si introduce Like "C%" en una consulta SQL, la consulta devuelve todos los valores de campo que comiencen por la letra C. En una consulta con parámetros, puede hacer que el usuario escriba el modelo que se va a utilizar. El Operador in Este operador devuelve aquellos registros cuyo campo indicado coincide con alguno de los valores que se encuentran una lista explicitada. Su sintaxis es: expresión [Not] In(valor1, valor2, . . .) SELECT * FROM Pedidos WHERE Provincia IN ("Santa Fe", "Cordoba", "Buenos Aires") Operadores Lógicos Hay tres operadores lógicos en SQL: AND Es el "y" lógico. Evalua dos condiciones y devuelve un valor de verdad sólo si ambas son ciertas. OR Es el "o" lógico. Evalúa dos condiciones y devuelve un valor de verdar si alguna de las dos es cierta. NOT Negación lógica. Devuelve el valor contrario de la expresión. Agrupamiento de Registros GROUP BY Combina los registros con valores idénticos, en la lista de campos especificados, en un único registro. Para cada registro se crea un valor sumario si se incluye una función SQL agregada, como por ejemplo SUM o COUNT, en la instrucción SELECT. Su sintaxis es: SELECT campos FROM tabla WHERE criterio GROUP BY campos del grupo GROUP BY es opcional. Los valores de resumen se omiten si no existe una función SQL agregada en la instrucción SELECT. Los valores Null en los campos GROUP BY se agrupan y no se omiten. No obstante, los valores Null no se evalúan en ninguna de las funciones SQL agregadas. Se utiliza la cláusula WHERE para excluir aquellas filas que no desea agrupar, y la cláusula HAVING para filtrar los registros una vez agrupados. Todos los campos de la lista de campos de SELECT deben o bien incluirse en la cláusula GROUP BY o como argumentos de una función SQL agregada. SELECT Id_Familia, Sum(Stock) FROM Productos GROUP BY Id_Familia Una vez que GROUP BY ha combinado los registros, HAVING muestra cualquier registro agrupado por la cláusula GROUP BY que satisfaga las condiciones de la cláusula HAVING. HAVING es similar a WHERE, determina qué registros se seleccionan. Una vez que los registros se han agrupado utilizando GROUP BY, HAVING determina cuales de ellos se van a mostrar. SELECT Carrera, Count(*) FROM Alumnos GROUP BY Carrera HAVING Count(*)>100 Esta consulta lista las carreras que tengan más de 100 alumnos Función de Agregación: AVG Calcula la media aritmética de un conjunto de valores contenidos en un campo especificado de una consulta. Su sintaxis es la siguiente Avg(expr) En donde expr representa el campo que contiene los datos numéricos para los que se desea calcular la media o una expresión que realiza un cálculo utilizando los datos de dicho campo. La media calculada por Avg es la media aritmética (la suma de los valores dividido por el número de valores). La función Avg no incluye ningún campo Null en el cálculo. SELECT Avg(Gastos) as Promedio FROM Pedidos WHERE Gastos > 100 Esta consulta lista el promedio de gastos calculado sobre los pedidos en los que se gastó más de 100. Función de Agregación: COUNT Calcula el número de registros devueltos por una consulta. Su sintaxis es la siguiente: Count(expr) En donde expr contiene el nombre del campo que desea contar. Los operandos de expr pueden incluir el nombre de un campo de una tabla, una constante. Aunque expr puede realizar un cálculo sobre un campo, Count simplemente cuenta el número de registros sin tener en cuenta qué valores se almacenan en los registros. La función Count no cuenta los registros que tienen campos null. Si utiliza un asterisco, Count calcula el número total de registros, incluyendo aquellos que contienen campos null. Count(*) es considerablemente más rápida que Count(Campo). SELECT Cont(*) as Total FROM Pedidos Esta consulta lista la cantidad de Pedidos. Funciones de Agregación: MAX y MIN Devuelven el mínimo o el máximo de un conjunto de valores contenidos en un campo especifico de una consulta. Su sintaxis es: Min(expr) Max(expr) En donde expr es el campo sobre el que se desea realizar el cálculo. Expr pueden incluir el nombre de un campo de una tabla, una constante. SELECT Min(Gastos) as ElMinimo FROM Pedidos WHERE Pais = "España" SELECT Max(Gastos) as ElMaximo FROM Pedidos WHERE Pais = "España" Función de Agregación: SUM Devuelve la suma del conjunto de valores contenido en un campo especifico de una consulta. Su sintaxis es: Sum(expr) En donde expr respresenta el nombre del campo que contiene los datos que desean sumarse o una expresión que realiza un cálculo utilizando los datos de dichos campos. SELECT Sum(PrecioUnidad Cantidad) as Total * FROM DetallePedido Operadores Lógicos IN y EXISTS IN Determina si un valor dado coincide con algún valor de una subconsulta o lista. Su sintaxix es: WHERE {Campo | Expresión} [ NOT ] IN ( Sub-Consulta | Constantes [, Constantes, ... n] ) El resultado del operador lógico IN es un valor booleano, es decir Verdadero o Falso, para cada valor de Campo que se encuentre ( o no ) en la sub-consulta. EXISTS Especifica una subconsulta para probar la existencia de filas. Su sintaxis es la siguiente: WHERE [NOT] EXISTS ( Sub - Consulta ) La subconsulta en realidad no produce ningún dato, al igual que IN devuelve el valor Verdadero o Falso. El ejemplo siguiente compara dos consultas que son semánticamente equivalentes. La primera consulta utiliza EXISTS y la segunda consulta utiliza IN. Ambas consultas devuelven la misma información. SELECT Nombre_Editor DISTINCT FROM Editores E WHERE EXISTS ( SELECT * FROM Titulos T WHERE T.IdEditor E.IdEditor AND T.Tipo="Negocios" ) SELECT DISTINCT Nombre_Editor FROM Editores WHERE IdEditor IN ( SELECT IdEditor = FROM Titulos WHERE T.Tipo="Negocios" ) Una forma de implementar ol Operador de División A continuación, se explicará cómo realizar la operación división. Esta operación incluye, en términos del cálculo de predicados, un cuantificador universal del que SOL no dispone, lo que complica bastante su representación. Por otra parte SOL sí dispone, como se vio, de una construcción equivalente al cuantificador existencia: el predicado EXISTS. Recordemos que exists verifica si el subselect que le sigue es vacío o tiene alguna fila como resultado. En el primer caso, como se vió, el predicado resulta falso y en el segundo verdadero. Ejemplo Supongamos que tenemos tres tablas, correspondientes a los esquemas Estudiante (Nro, Nombre, ... ), Materia (Código, Nombre, Año, ... ) y Cursa (Nro, Código) y deseamos saber los nombres de los alumnos que cursan todas las materias de 4º año. En Álgebra Relacional, la respuesta se obtendría evaluando la expresión: Nombre(Nombre (Estudiante |X| (Cursa / (σAño="4º"M(Materia))) Veamos cómo se expresa ahora en SOL: select nombre from Estudiante e where not exists ( select * from Materia m where m.Año = "4º" and not exists ( select * from Cursa c where c.Nro = e.Nro and c.Codigo = m.Codigo ) )